AGE Development Blog (Advanced Graphics Engine for AmosPro / Amiga AGA)

Started by kevin, March 17, 2012, 08:34:43 PM

Previous topic - Next topic

kevin

 
AMOS AGA - AGE Development Blog (Advanced Graphics Engine for AmosPro / Amiga AGA)


 
 
What Is it?


   AGE is a bare bones graphics engine / library for the Amos / AmosPro developers on the Amiga platform.    The library allows the user to perform various graphical effects, but mainly gives the user the ability to the use the Amiga's AGA chipset from AMOS / AMOSPRO.  

   The project was originally active between 1996 -> 1998, with that version of the library being release around 2000.  It hasn't been updated since.  Given the age of library, it'd be easy to say why bother, well, the recent updates just clean up the code and make it more user friendly.   The previous release examples were very complicated to follow and virtually impossible to use without low level knowledge.    Having said, some new features have been added, but those have mostly been cosmetic.  

    The changes to the package are in the examples..  There are now example, where there wasn't previously.


 
Can I use the library under AMIGA emulation ?


     Yes,  that's how recent updates of the package have been developed.   For those without real AMIGA hardware anymore (like myself), there's also package versions of AMOSPRO (WinUAE + AMOS) that be run directly on Windows.     Well worth a bit of nostalgia..  




Can I use the library from other BASIC languages on AMIGA ?


   Yes, you could.  The library is presented as a pre-assembled chunk of machine code with AMOS wrapper.  Therefore you can use AGE from any language that allows you set the registers and call a function by pointer.    




Didn't you write AMOS AGA


      Yes;  decaded ago now I wrote a collection of simple demos that used AGA in AMOS

      https://aminet.net/package/dev/amos/AmosAGA






 
Home Page?


    AGE From Home Page  (NOTE: OLD 2000 Version )



 
Beta Downloads?


    AGE V1.02 BETA #1  (21st,Apr,2012)




Videos


   








Work In Progress.


     Given the age of the library, I'm not going to be updating it on a regular basis, the following updates just make the library a lot more user friendly.  Firstly the library now comes as an separate AMOS file.    So the user just includes the file into their project (at the top of the code) and then is ready to use AGE function bellow that.

     Some of functions/procedure names have been changed and well as some helper functions have been added.   As new functionality is added it'll be documented here.




Function List.


    While the library supports PLANAR, INTERLEAVED PLANAR and CHUNKY pixel formats, not ALL drawing functions do.  




  System

     AGE_ALLOC_RESOURCES[SCRNS,COPS,BLOCKS,BANKS,FONTS,FILECACHE,DATACACHE]       ; This function basically opens the library so you can use it.  The library was designed to be fairly flexible in terms of resources, so rather than it allocate memory for the various resource tables.  You'll need to supply this function withe the sizes of various buffers the library will use.  When you call it, this allocates the base the AGE resource structure the entire library then uses.

           SCRNS       = Number of Screens you want
           COPS         =  Number of Coppers you want
           BLOCKS      =  Numbers of Blocks banks you want
           BANKS       = Number of banks
           FONTS       = Number of fonts
           FILECACHE  = Size of temporary file buffer for loading.
           DATACACHE =  Set users required data cache size
 

     AGE_TAKE_SYSTEM[COPADDR]       ; This function takes over system and sets up the low level machine state.  The function expects the address of the COPPER List to install upon execution.

     AGE_RESTORE_SYSTEM       ; Restore system state after it's been taken over.

     AGE_FORBID_TASKING       ; Disable the Amiga OS from multi tasking

     AGE_PERMIT_TASKING       ; Allow the Amiga OS to multi task




  Screen

      AGE_OPEN_SCREEN[SCRN,WIDTH,HEIGHT,DEPTH,TYPE]      ; Creates a screen of width/height/depth, of particular type.  Supports Planar / Interleaved & Chunky screen types.  The screen default to being created in chip memory, but can be forced into Fast.

      AGE_OPEN_CHUNKY_SCREEN[SRCN,WIDTH,HEIGHT]      ; Creates a 8bit chunky screen in fast memory.

      AGE_DELETE_SCREEN[SRCN]      ; Releases a screens memory.  Beware that if this screen is the current copper list screen you'll get undefined results.

      AGE_LOAD_IFF_TO_SCREEN[FILENAME$,SCRN]      ; Loads an IFF file into a previously created screen.   Supports 1 to 8bit IFF images


      AGE_SAVE_IFF[FILENAME$,SCRN]      ; Save screen to disk as IFF file.

      AGE_EXAMINE_IFF[FILENAME$      ; Queries IFF file for it's size information.  The function returns the Width/Height/Depth in the dregs(0),dregs(1),dregs(2)

      AGE_SET_SCREEN[SCRN]      ; Make the library direct rendering to this screen from now on.

      AGE_SCREEN_VIEWPORT[X1,Y1,X2,Y2]      ; Set the viewport (Render area) of the current output screen.  This lets you clip rendering to within a certain care of the screen.

      AGE_RESTORE_SCREEN_VIEWPORT          ; Restore the view port to the screens original size.

      AGE_GET_SCREEN_VIEWPORT          ; The screens current view port size.  Values returns in dreg 0,1,2,3


      AGE_GET_BITPLANE_ADDR[SCRN,BP]          ; Get Address of bit plane within this screen.

      AGE_GET_SCREEN_WIDTH[SCRN]          ; Get width of screen.  Param  or  dreg(0)=result
      AGE_GET_SCREEN_HEIGHT[SCRN]          ; Get height of screen.  Param  or  dreg(0)=result
      AGE_GET_SCREEN_DEPTH[SCRN]          ; Get depth of screen.  Param  or  dreg(0)=result
      AGE_GET_SCREEN_TYPE[SCRN]          ; Get type of screen.  Param  or  dreg(0)=result




    Copper

      AGE_CREATE_COPPER[Index, ScreenIndex, BurstMode, BurstModulo]      ; Creates a standard copper list in chip memory.  The view settings are is based upon a screen you provide
 
      AGE_DELETE_COPPER[Index]      ; Delete a copper list from chip memory.  
 
      AGE_SHOW_COPPER[Index]         ; Set the copper hardware to view your copper list.  Sme as AGE_SET_COPPER, except this version flushs the display hardware.

      AGE_SET_COPPER[Index]         ; Set the copper hardware to view your copper list

      AGE_REFRESH_COPPER_PALETTE[COPPER_INDEX,PAL_POINTER]         ; Update the colour table in the copper with a user defined list of 256  32bit RGB colour values.

      AGE_GET_COPPER_PTR[COPPER_INDEX]         ; This functions returns a pointer to the copper list in chip memory.  You can modify it all you want.  The only limit is that copper lists allocated by the library, must be smaller than 4096 bytes..







  Graphics

      AGE_DOT[x,y]              ; Draw DOT in current ink colour (CLIPPED)  to current surface   (Supports PLANAR / CHUNKY)  
      AGE_DOTC[x,y,colour]    ; Draw DOT in user defined  ink colour (CLIPPED) to current surface  

      AGE_DOT_NC[x,y]      ; Draw DOT in current ink colour (NO CLIPPED)  to current surface   (Supports PLANAR / CHUNKY)  
      AGE_DOTC_NC[x,y,colour]    ; Draw DOT in user defined  ink colour (NO CLIPPED) to current surface  

      AGE_LINE[x1,y1,x2,y2]      ; Draw Lines in current ink colour (CLIPPED)    (Supports PLANAR / CHUNKY  )  
      AGE_LINEC[x1,y1,x2,y2]    ; Draw Lines in user defined  ink colour (CLIPPED)  


      AGE_BOX[X1,Y1,X2,Y2]      ; Draws a filled rectangle in current ink colour.  (Supports PLANAR / INTERLEAVED PLANAR & CHUNKY)  

      AGE_BOXC[X1,Y1,X2,Y2,PCOL]      ; Draws a filled rectangle in user defined colour.  (Supports PLANAR & CHUNKY)  

      AGE_DRAW_FILLED_BOX[X1,Y1,X2,Y2,PLANEMASK]      ; Draws a filled rectangle on the user defined planes.  (Supports PLANAR)  

      AGE_DRAW_CLEAR_BOX[X1,Y1,X2,Y2,PLANEMASK]      ; Clears a filled rectangle on the user defined planes.  (Supports PLANAR)  
   
      AGE_DRAW_SHADE_BOX[X1,Y1,X2,Y2,C1,C2,C3,C4]      ; Grads a gouraud shaded rectangle to the current screen  (Supports Chunky)  


      AGE_CIRCLE[X,Y,RAdius]      ; Draws a filled circle in current ink colour.  (Supports PLANAR & CHUNKY)  

      AGE_CIRCLEC[X,Y,RAdius,PCOL]      ; Draws a filled circle in user defined colour.  (Supports PLANAR & CHUNKY)  


      AGE_COPY_RECT[SrcScreen,X1,Y1,X2,Y2,DestScreen,DestX,DestY]      ; Copy a section from the source image to the destination.     (Supports PLANAR & CHUNKY)  


      AGE_COPY_RECT_QUEUE[QUERE_POINTER, X_OFFSET,Y_OFFSET, NUMB_OF_ITEMS_IN_QUEUE]      ; Render a list of queued copy rect's.  The output location can be displaced  using with X & Y offsets.  The structure is expected to be 16 bytes wide (16 bytes per queue item)   (Supports PLANAR & CHUNKY)


      AGE_SET_RECT_QUEUE[QUERE_POINTER, INDEX,SrcScreen,X1,Y1,X2,Y2,DestScreen,DestX,DestY]      ; This is a wrapper function to set the source rect and destination position of the rect to be copied.  The Function requires a user allocated buffer big enough to fit the queue data.  If you wanted to store 50 items, then you'd need to allocate at least 50*16 (16 bytes per item) for the buffer.   Each item in the queue is accessed via an Index, ranging from 0 to Number_Of_items -1



      AGE_TRI[x1,y1,x2,y2,x3,y3]      ; Draws a triangle in the current INK colour.     (Chunky)

      AGE_TRIC[x1,y1,x2,y2,x3,y3,Colour]      ; Draws a triangle in a user defined colour  (Chunky)

      AGE_QUADC[x1,y1,x2,y2,x3,y3,x4,y4,Colour]      ; Draws a 4 sided polygon in user defined  colour, the vertex given to the function must form a CONVEX polygon     (Chunky)


      AGE_GOURAUDTRI[x1,y1,Colour1,x2,y2,Colour2,x3,y3,Colour3]      ; Draws a gouraud shaded triangle to the current screen.  (Chunky)

      AGE_GOURAUDQUAD[x1,y1,Colour1,x2,y2,Colour2,x3,y3,Colour3,x4,y4,Colour4]      ; Draws a gouraud shaded 4 sided convex polygon to the current screen.  (Chunky)



 Fonts

     AGE_LOAD_FONT[FILENAME$,INDEX]       ; Load a Font into a available font buffer.  

     AGE_DELETE_FONT[Index]                    ; Delete a front from memory

     AGE_FONT_PLANE_MASK[INDEX,MASK]           ; Specify which bitplanes the font should write to when drawn.  Defaults to %11111111 (All Planes)

     AGE_GET_FONT_PLANE_MASK[INDEX[Index]                    ; Get the bitplane mask this font is using.

     AGE_GET_FONT_HEIGHT[INDEX]                    ; Get the fonts overall height.

     AGE_SET_FONT[INDEX]                    ; Set default font for rendering functions like AGE_PRINT

     AGE_GET_FONT                    ; Get the current output font if any.


     AGE_INK[ColourIndex]             ; Set the current INK colour for rendering functions.

     AGE_GET_INK             ; Set the current INK colour for rendering functions.

     AGE_SET_CURSOR             ; Set the current cursor position (X/Y) coordinates.

     AGE_PRINT[t$]             ; Prints the String T$ at current cursor position, in the current colour and font.  NOTE:  Only seem to support rendering to PLANAR formatted screens

     AGE_TEXT[T$,X,Y,C]      ; Render text at any position on the current screen. Using the current font.


     
NOTE:  PRINT & TEXT functions truncate the X coordinate to nearest byte when rendering, and there only seems to be clipping on the vertical axis.




  C2p (Chunky To Planar)

     AGE_C2P[SourceChunkyScreen,TargetPlanarScreen]       ; Convert the chunky formatted source image to an 8bit planat screen.

     AGE_C2P_CLS[SourceChunkyScreen,TargetPlanarScreen]       ; Convert the chunky formatted source image to 8bit planar screen with chunky CLS (colour 0).



  Colours

     RGB[R,G,B]       ; Merges the three 8Bit R,G,B values into packed 32bit colour value.

     RGBR[ThisRGB]       ; Get the 8Bit Red Value from colour , result in Param
     RGBG[ThisRGB]       ; Get the 8Bit Green Value from colour , result in Param
     RGBB[ThisRGB]       ; Get the 8Bit Blue Value from colour , result in Param

     RGB_24TO12[RGB]       ; Convert 24bit RGB value into 12Bit RGB value, result in Param
     RGB_12TO24[RGB]       ; Convert 12bit RGB value into 24Bit RGB value, result in Param

     RGB_ALPHA_BLEND[RGB1,RGB2,SCALE#]       ; Alpha Blend Two RGB colours, scale range 0.0 to 1.0,  result in Param
     RGB_INT_ALPHA_BLEND[RGB1,RGB2,INTSCALE]       ; Alpha Blend Two RGB colours, IntScale Range 0 To 255,  result in Param

     RGB_ALPHA_ADD[RGB1,RGB2]       ; Alpha Add  Two RGB colours,  result in Param
     RGB_ALPHA_SUB[RGB1,RGB2]       ; Alpha Subtract Two RGB colours,  result in Param

     RGB_FADE[THISRGB,SCALE#]       ; Scale the input RGB colour.  (Scale range 0 to 1.0)  result in Param
     RGB_INTFADE[THISRGB,IntSCALE]       ; Scale the input RGB colour.  (IntScale range 0 to 255)  result in Param




  Blitter

     AGE_OWN_BLITTER       ; Take exclusive control over the blitter chip.
     AGE_DISOWN_BLITTER  ; Release control over the blitter
     AGE_WAIT_BLIT           ; Wait for blitter to complete it's current work.




  Banks

     AGE_CREATE_BANK[BANK,SIZE]       ; CReate a bank of SIZE (in bytes)
     AGE_DELETE_BANK[BANK]       ; Deletes a BANK from memory
     AGE_LOAD_BANK[FILENAME$,BANK]       ; Load Data directly to a Bank
     AGE_GET_BANK_PTR[BANK]       ; Returns the address (pointer) of the first byte in a bank
     AGE_GET_BANK_SIZE[BANK]       ; Returns the size in bytes of a bank

     You can use the Amos Peek/Poke commands to modify the banks content at will




  Fixed Point Math / Trig Functions

     AGE_COS[ANGLE]       ; Cosine of angle (in degrees), returns fixed point 16:16 integer
     AGE_SIN[ANGLE]        ; Sine of angle (in degrees), returns fixed point 16:16 integer

     AGE_COSRADIUS[ANGLE]       ; Cosine of angle (degrees) * RADIUS, returns fixed point 16:16 integer
     AGE_SINRADIUS[ANGLE]        ; Sine of angle (degrees) * RADIUS, returns fixed point 16:16 integer

     AGE_POLAR[ANGLE]              ; returns X / Y in dreg(0) and dreg(1) returns fixed point 16:16 integer

     AGE_SINRADIUS[ANGLE]        ; Sine of angle (degrees) * RADIUS, returns fixed point 16:16 integer

      AGE_ROTATE2D[ANGLE,X,Y]   ; Rotate a 2d coordinate by ANGLE degrees. Result returned in D0/D1 registers.

      AGE_ROTATE2D_BATCH[SRCPTR,SRCVERTEXMODULO,DESTPTR,DESTVERTEXMODULO,METHOD,ANGLE,VERTEXCOUNT]
   ; 2D Rotate a set of points.   See Here for More Info

     ANGLES are wrapped to 360 degrees internally.  To convert from fixed point to Integer  we divide  the value by $10000.   Some functions will do this for you, others won't to keep the precision.  



kevin

 AGE Example - Loading 256 Colour Picture In AmosPro

 In very short this video we see the AGE library wrapper being used from AmosPRO.  The demo frame work sets up the library,  create a screen, loads the 8bit (256 colour) IFF, creates a copper list and then displays it.  

Developed By:
https://www.underwaredesign.com









Set Buffer 50

' *=-------------------------------------------------------------------=*
'
'                         AGE - Loading 256 Colour IFF's    
'
'                                      By  
'
'                                By Kevin Picone
'
'                         Last Updated - 14th, Mar, 2012                  
'
'                (c) Copyright 1997/98/1999/2000- 2012, Kevin Picone
'
'                             www.UnderwareDesign.com        
'
' *=-------------------------------------------------------------------=*
'

   ' Sorry but AMOSPRO seems to require absolute include paths ??  
   '  SO,  YOU'LL HAVE TO TWEAK THE PATHS IN ORDER TO RUN
   '  THE DEMOS FROM AMOS/AMOSPRO correctly on your machine    


   ' To make the pathing less annoying, here we store the 'root path'  
   '  in a variable APPPATH$ .. Then use this through our program.  


     APPPATH$="Dh0:/AGE_V102/"



    ' Set the location of the AGE lib..  
      AGE_LIBRARY_PATH$=APPPATH$+"Includes/Asm/Age.lib"

    ' Include the AGE wrapper into your AMOS project
      Include "Dh0:/AGE_V102/INCLUDES/AMOS/AGE_V064.AMOS"




'   *=-----------------------------------------------------------------=*    
'
'                        >> ALLOC AGE RESOURCE TABLEs <<
'
'   *=-----------------------------------------------------------------=*    

           SCRNS=15
           COPS=15
           BLKDATAS=10
           BANKS=11

           FONTS=12
           FILECACHESIZE=50000
           DCACHESIZE=10000

           AGE_ALLOC_RESOURCES[SCRNS,COPS,BLKDATAS,BANKS,FONTS,FILECACHESIZE,DCACHESIZE]




        ' -----------------------------------  
        ' Create our LOWRES / INTERLEAVED  AGE screen in Chip Memory
        ' -----------------------------------  

           TYPE=AGE_LOWRES
           TYPE=TYPE+AGE_INTERLEAVED
           AGE_OPEN_SCREEN[0,320,256,8,TYPE]



        ' -----------------------------------  
        '  Load IFF into this screen.  
        ' -----------------------------------  
           FILE$=APPPATH$+"GFXFILES/PICTURES/DRAGONAA.IFF"
           AGE_LOAD_IFF_TO_SCREEN[FILE$,0]


        ' -----------------------------------  
        ' Create a standard/ simple copper list for viewing this screen.  
        ' -----------------------------------  
           AGE_OPEN_STANDARD_COPPER[0,0,3,8]



        ' -----------------------------------  
        '  Create copper to view our AGE screen  
        ' -----------------------------------  
           Doke $DFF096,$180 : Rem Kill Bitplane + copper DMA  

           AGE_WAIT_TOP_OF_FRAME

           AGE_SHOW_COPPER[0]

           Doke $DFF096,$8180 : Rem restore Bitplane + copper DMA  


        ' -----------------------------------  
        ' Direct ALL RENDERING To OUR Screen
        ' -----------------------------------  
           AGE_SET_SCREEN[0]



        ' -----------------------------------  
        '  Wait for a key
        ' -----------------------------------  

           Wait Key



        ' -----------------------------------  
        ' Clean Up/Close Down AGE  
        ' -----------------------------------  

           AGE_CLEAN_UP







kevin

AGE Clean Up

   The original library was written using AsmOne on the my Amiga 1200,  but sadly this is really unstable under emulation, so in order to update the library i've had to change assemblers.   Which means running the code through a make ship translator written in PlayBASIC.  Even so, it still took a few hours to get it assembling under PHXASS.   So the build process now,  is editing code on the PC side, switching to WinUAE and assembly through the command line.  A little messy, but it's fairly comfortable really once you get going.  

   While looking through the command set of the library, there's some obvious pitfalls in the commands, by that i mean, there's some missing functionality to tie some parts together better.   One such issue, was that you couldn't update the display copper colour list once it'd be created from the parent screen.  Might not sound like a big deal, but it meant you couldn't change the palette colours.     So I've added a function to write a custom palette back into the copper list on demand.   

    Here's an example that grabs the palette from the source screen,  then fades it out after hitting a key.



Set Buffer 50

' *=-------------------------------------------------------------------=*
'
'           AGE - Loading 256 Colour IFF's  With Palette fade    
'
'                                      By  
'
'                                By Kevin Picone
'
'                         Last Updated - 16th, Mar, 2012                  
'
'                (c) Copyright 1997/98/1999/2000- 2012, Kevin Picone
'
'                             www.UnderwareDesign.com        
'
' *=-------------------------------------------------------------------=*
'

   ' Sorry but AMOSPRO seems to require absolute include paths ??  
   '  SO,  YOU'LL HAVE TO TWEAK THE PATHS IN ORDER TO RUN
   '  THE DEMOS FROM AMOS/AMOSPRO correctly on your machine    


   ' To make the pathing less annoying, here we store the 'root path'  
   '  in a variable APPPATH$ .. Then use this through our program.  


     APPPATH$="Dh0:/AGE_V102/"



    ' Set the location of the AGE lib..  
      AGE_LIBRARY_PATH$=APPPATH$+"Includes/Asm/Age.lib"

    ' Include the AGE wrapper into your AMOS project
      Include "Dh0:/AGE_V102/INCLUDES/AMOS/AGE_V064.AMOS"



'   *=-----------------------------------------------------------------=*    
'
'                        >> ALLOC AGE RESOURCE TABLEs <<
'
'   *=-----------------------------------------------------------------=*    

           SCRNS=15
           COPS=15
           BLKDATAS=10
           BANKS=11

           FONTS=12
           FILECACHESIZE=50000
           DCACHESIZE=10000

           AGE_ALLOC_RESOURCES[SCRNS,COPS,BLKDATAS,BANKS,FONTS,FILECACHESIZE,DCACHESIZE]




        ' -----------------------------------  
        ' Create our LOWRES / INTERLEAVED  AGE screen in Chip Memory
        ' -----------------------------------  

           TYPE=AGE_LOWRES
           TYPE=TYPE+AGE_INTERLEAVED
           AGE_OPEN_SCREEN[0,320,256,8,TYPE]



        ' -----------------------------------  
        '  Load IFF into this screen.  
        ' -----------------------------------  
           FILE$=APPPATH$+"GFXFILES/PICTURES/DRAGONAA.IFF"
           AGE_LOAD_IFF_TO_SCREEN[FILE$,0]



        ' -----------------------------------  
        '  Read the Colour Palette from the this screen
        ' -----------------------------------  

           Dim CURRENT_PALETTE(256)

           AGE_SCREEN_COPY_PALETTE_TO_ARRAY[0,Varptr(CURRENT_PALETTE(0))]




        ' -----------------------------------  
        ' Create a standard / simple copper list for viewing this screen.    
        ' -----------------------------------  
           AGE_OPEN_STANDARD_COPPER[0,0,3,8]



        ' -----------------------------------  
        '  Create copper to view our AGE screen  
        ' -----------------------------------  
           Doke $DFF096,$180 : Rem Kill Bitplane + copper DMA  

           AGE_WAIT_TOP_OF_FRAME

           AGE_SHOW_COPPER[0]

           Doke $DFF096,$8180 : Rem restore Bitplane + copper DMA  


        ' -----------------------------------  
        ' Direct ALL RENDERING To OUR Screen
        ' -----------------------------------  
           AGE_SET_SCREEN[0]









        ' -----------------------------------  
        '  Wait for a key
        ' -----------------------------------  
           Wait Key



        ' -----------------------------------  
        '  FAde Screen Out
        ' -----------------------------------  


        Dim TEMP_PALETTE(256)


       LEVEL=100

       Repeat


           LEVEL=LEVEL-2
           SCALE#=LEVEL/100.0

          ' --------------------------------------------------------
          ' Fade all the colours in our copy of the screens palette
          ' --------------------------------------------------------

           For LP=0 To 255
              ' grab the screens original palette colour
              C=CURRENT_PALETTE(LP)

              ' fade this colour by the required amount

               RGB_FADE[C,SCALE#]

              ' store the new colour in a second temp array of palette colours
               TEMP_PALETTE(LP)=Param
           Next



           AGE_WAIT_TOP_OF_FRAME


          ' get a pointer to the Faded array of colour values
           PAL_POINTER=Varptr(TEMP_PALETTE(0))

          '  Copy this array of colour values to this copper list
           AGE_REFRESH_COPPER_PALETTE[0,PAL_POINTER]

       Until LEVEL<1

        ' -----------------------------------  
        ' Clean Up/Close Down AGE  
        ' -----------------------------------  
           AGE_CLEAN_UP



      Just picking through the library,  there does seem to be some command sets that require specially formatted external data such as FONTS and MAPS.  I haven't looked at the block map stuff, but fonts seems to have some problems in the updated version of the Library.   Hopefully that's an easy fix, as if it's not,  it may well stay broken.  We'll see.  


kevin

AGE - Double Buffering / Animation

     Been picking through the library in my spare time, it's a bit hit and miss as to some things.  Took a while to set up a working double buffering example, not because the buffer swapping wasn't working, it turned out that the LINE function has a bug in it, where it will only draw to SCREEN 0.  So you can draw to one frame buffer and not the other. 

     Anyway so here we have simple set up example.  The demo creates two frame buffers and two copper lists, a variable CURRENT_BUFFER is the index of the current SCREEN we're rendering to, so while we're drawing to CURRENT_SCREEN, we show the other screens copper list.    The main loop is of the demo is copying a 256 colour picture to the current screen, then draws some orbiting filled circles over the top. 



Set Buffer 50

' *=-------------------------------------------------------------------=*
'
'                      AGE - DOUBLE BUFFER / ANIMATION     
'
'                                      By 
'
'                                By Kevin Picone
'
'                         Last Updated - 19th, Mar, 2012                   
'
'                (c) Copyright 1997/98/1999/2000- 2012, Kevin Picone
'
'                             www.UnderwareDesign.com       
'
' *=-------------------------------------------------------------------=*


    ' Sorry but AMOSPRO seems to require absolute include paths ??   
    '  SO,  YOU'LL HAVE TO TWEAK THE PATHS IN ORDER TO RUN
    '  THE DEMOS FROM AMOS/AMOSPRO correctly on your machine     


    ' To make the pathing less annoying, here we store the 'root path'   
    '  in a variable APPPATH$ .. Then use this through our program. 


      APPPATH$="Dh0:/AGE_V102/"



     ' Set the location of the AGE lib.. 
       AGE_LIBRARY_PATH$=APPPATH$+"Includes/Asm/Age.lib"

     ' Include the AGE wrapper into your AMOS project
       Include "Dh0:/AGE_V102/INCLUDES/AMOS/AGE_V067.AMOS"



'   *=-----------------------------------------------------------------=*   
'
'                        >> ALLOC AGE RESOURCE TABLEs <<
'
'   *=-----------------------------------------------------------------=*   

            SCRNS=15
            COPS=15
            BLKDATAS=10
            BANKS=11

            FONTS=12
            FILECACHESIZE=50000
            DCACHESIZE=10000

            AGE_ALLOC_RESOURCES[SCRNS,COPS,BLKDATAS,BANKS,FONTS,FILECACHESIZE,DCACHESIZE]


         ' ----------------------------------- 
         ' Create our LOWRES / INTERLEAVED  AGE screen in Chip Memory '
         ' ----------------------------------- 
             TYPE=AGE_LOWRES
'            TYPE=TYPE+AGE_INTERLEAVED
             TYPE=TYPE+AGE_PLANAR

             AGE_OPEN_SCREEN[0,320,256,8,TYPE]
             AGE_OPEN_SCREEN[1,320,256,8,TYPE]

             CURRENT_BUFFER=0


         ' ----------------------------------- 
         '  Load IFF into this a temp screen.   
         ' ----------------------------------- 

              FILE$=APPPATH$+"GFXFILES/PICTURES/DRAGONAA.IFF"
              AGE_OPEN_SCREEN[3,320,256,8,TYPE]
              AGE_LOAD_IFF_TO_SCREEN[FILE$,3]

        ' copy the palette from the backdrop picture in the chip buffers

              AGE_SCREEN_COPY_PALETTE[3,0]
              AGE_SCREEN_COPY_PALETTE[3,1]


         ' ----------------------------------- 
         ' Create two copper lists for viewing our screens.   
         ' ----------------------------------- 
              AGE_CREATE_COPPER[0,0,3,8]
              AGE_CREATE_COPPER[1,1,3,8]


         ' ----------------------------------- 
         '  Set copper to view our AGE screen   
         ' ----------------------------------- 
             Doke $DFF096,$180 : Rem Kill Bitplane + copper DMA   

             AGE_WAIT_TOP_OF_FRAME

             AGE_SHOW_COPPER[1-CURRENT_BUFFER]

             Doke $DFF096,$8180 : Rem restore Bitplane + copper DMA 


        ' ----------------------------------- 
        ' Direct ALL RENDERING To OUR Screen
        ' ----------------------------------- 
             AGE_SET_SCREEN[CURRENT_BUFFER]


       ' ----------------------------------- 
       ' Load a Font
       ' ----------------------------------- 

             FONTS$=APPPATH$+"gfxfiles/fonts/"
             AGE_LOAD_FONT[FONTS$+"Alex8.font",2]
             AGE_SET_FONT[2]


       ' ----------------------------------- 
'
       ' ----------------------------------- 

Degree

        Do




          ' -------------------------------------------------
          ' Swap Buffers
          ' -------------------------------------------------

              CURRENT_BUFFER=1-CURRENT_BUFFER

              AGE_SET_SCREEN[CURRENT_BUFFER]

              AGE_SET_COPPER[(1-CURRENT_BUFFER)]

              AGE_WAIT_TOP_OF_FRAME


          ' -------------------------------------------------
          ' Copy the temp image to the current render buffer
          ' -------------------------------------------------

             AGE_COPY_SCREEN[3,0,0,320,256,CURRENT_BUFFER,0,0]


          ' -------------------------------------------------
          ' Draw spinning circles
          ' -------------------------------------------------

            RENDER_STAR[160,128,BASEANGLE]
            BASEANGLE=(BASEANGLE+1) mod 360


          ' ---------------------------
          ' Render some text on the scene 
          ' ---------------------------

             AGE_TEXT["Double Buffering",10,10,1]


          ' ---------------------------
          ' Check for key press
          ' ---------------------------

             KEYPRESS$=Inkey$()
             If KEYPRESS$=" " Then Exit

        Loop



         ' ----------------------------------- 
         ' Clean Up/Close Down AGE 
         ' ----------------------------------- 
            AGE_CLEAN_UP


           End



Procedure RENDER_STAR[X,Y,BASEANGLE]

       ' -----------------------------------------------------------------
       ' Draw a bunch of rotating circles in orbit around the screen center
       ' -----------------------------------------------------------------

           AGE_OWN_BLITTER

            For ANGLE=0 To 359 Step 30

                ANGLE2=BASEANGLE+ANGLE
              '  ANGLE2=ANGLE mod 360

                X2=X+Cos(ANGLE2)*100
                Y2=Y+Sin(ANGLE2)*100

                Inc INDEX
                AGE_INK[INDEX]

                AGE_CIRCLE[X2,Y2,20]



            Next

            AGE_DISOWN_BLITTER

End Proc












kevin

AGE - Gouraud Shaded Cube in Amos Pro (AGA)

    Tonights little goal was to get the C2P side of library all tested,  so I can throw together some examples to wrap it all up... But you know as soon as you make plans,  the ground shifts and another adjustment is required.  On this occasion, it turns out the C2p conversion routines in the library weren't working anymore after the port.   Was initially thinking the issue was just me not remembering how to set up the buffers anymore (it's been over 12 years after all all), but after some trail and error it turns out the Chunky to planar conversion routines weren't working.  Which after a bit more detective work, the fault was caused by the new assembler optimizing out what it through was redundant offsets, but that's fixed now.  

     So bellow we have a picture of an AMOS PRO remake of the gouraud shaded cube demo (the demo found in the PLLBC2p library).  Now granted  it's not going to be as fast as the native assembly version,  given that's doing more work than that demo, but it's still fairly quick when running under JIT enabled emulation,  without even compiling the demo.  Moreover, the library doesn't have any built in rotation support, so all the rotation/ projection and back face culling are running in little old AMOS.

     Will post a video later..  



AGE Gouraud Cube  (AmosPro / Amiga AGA)

In this video, I'm using the AGE library from AmosPRO to draw a chunky 8Bit AGA scene with gouraud shaded cube.  The program is drawing the 320*256 backdrop picture, some orbiting circles and the gouraud shaded cube each frame.  All the grunt work is done by the library, expect the 3D stuff (rotation/projection/back face culling) which is done in little old Amos.  

 The clip is recording running from WinUAE with no jit and without compiling the Amos example.  It runs surprisingly quickly with JIT, even the Amos Interpreter, so it should give those Amos fans a bit of fun.  

Developed By:
https://www.underwaredesign.com







Here's the AmosPro source code to this demo.



Set Buffer 50

' *=-------------------------------------------------------------------=*
'
'                              AGE - GOURAUD CUBE      
'
'                                      By  
'
'                                By Kevin Picone
'
'                         Last Updated - 21st, Mar, 2012                  
'
'                (c) Copyright 1997/98/1999/2000- 2012, Kevin Picone
'
'                             www.UnderwareDesign.com        
'
' *=-------------------------------------------------------------------=*
'

   ' Sorry but AMOSPRO seems to require absolute include paths ??  
   '  SO,  YOU'LL HAVE TO TWEAK THE PATHS IN ORDER TO RUN
   '  THE DEMOS FROM AMOS/AMOSPRO correctly on your machine    


   ' To make the pathing less annoying, here we store the 'root path'  
   '  in a variable APPPATH$ .. Then use this through our program.  


     APPPATH$="Dh0:/AGE_V102/"



    ' Set the location of the AGE lib..  
      AGE_LIBRARY_PATH$=APPPATH$+"Includes/Asm/Age.lib"

    ' Include the AGE wrapper into your AMOS project
      Include "Dh0:/AGE_V102/INCLUDES/AMOS/AGE_V069.AMOS"



'   *=-----------------------------------------------------------------=*    
'
'                        >> ALLOC AGE RESOURCE TABLEs <<
'
'   *=-----------------------------------------------------------------=*    

           SCRNS=15
           COPS=15
           BLKDATAS=10
           BANKS=11

           FONTS=12
           FILECACHESIZE=50000
           DCACHESIZE=10000

           AGE_ALLOC_RESOURCES[SCRNS,COPS,BLKDATAS,BANKS,FONTS,FILECACHESIZE,DCACHESIZE]


        ' -----------------------------------  
        ' Create our LOWRES / PLANAR  AGE screens in Chip Memory  
        ' -----------------------------------  
            TYPE=AGE_LOWRES+AGE_PLANAR

            AGE_OPEN_SCREEN[0,320,256,8,TYPE]
            AGE_OPEN_SCREEN[1,320,256,8,TYPE]



            CURRENT_BUFFER=0


        ' -----------------------------------  
        ' CReate CHUNKY temp screen.    
        ' -----------------------------------  

            CHUNKY_BUFFER=3

            AGE_OPEN_CHUNKY_SCREEN[CHUNKY_BUFFER,320,256]



        ' -----------------------------------  
        '  Load IFF into another chunky screen.  
        ' -----------------------------------  

             CHUNKY_PICTURE=4

              FILE$=APPPATH$+"GFXFILES/PICTURES/DRAGONAA_156.IFF"

            AGE_OPEN_CHUNKY_SCREEN[CHUNKY_PICTURE,320,256]
            AGE_LOAD_IFF_TO_SCREEN[FILE$,CHUNKY_PICTURE]

       ' Fill the palette with a gradient from colours 256 to 255
            MAKE_PALETTE[CHUNKY_PICTURE,$443355,$FFBB88,156,255]

' Copy the pictures palette to the chunk buffers
             AGE_SCREEN_COPY_PALETTE[CHUNKY_PICTURE,0]
             AGE_SCREEN_COPY_PALETTE[CHUNKY_PICTURE,1]





        ' -----------------------------------  
        ' Create standard / simple copper list for viewing our screens.    
        ' -----------------------------------  
             AGE_CREATE_COPPER[0,0,3,8]
             AGE_CREATE_COPPER[1,1,3,8]


        ' -----------------------------------  
        '  Set copper to view our AGE screen  
        ' -----------------------------------  
            Doke $DFF096,$180 : Rem Kill Bitplane + copper DMA  

            AGE_WAIT_TOP_OF_FRAME

            AGE_SHOW_COPPER[1-CURRENT_BUFFER]

            Doke $DFF096,$8180 : Rem restore Bitplane + copper DMA  



       Degree


Gosub _INIT_3D



       Do


         ' -------------------------------------------------
         ' Swap Buffers
         ' -------------------------------------------------


             AGE_C2P_SCRN_CLS[CHUNKY_BUFFER,CURRENT_BUFFER]


             CURRENT_BUFFER=1-CURRENT_BUFFER

             AGE_SET_COPPER[(1-CURRENT_BUFFER)]

             AGE_WAIT_TOP_OF_FRAME

             AGE_SET_SCREEN[CHUNKY_BUFFER]



             AGE_COPY_SCREEN[CHUNKY_PICTURE,0,0,320,256,CHUNKY_BUFFER,0,0]





         ' -------------------------------------------------
         ' Copy the temp image to the current render buffer
         ' -------------------------------------------------

             RENDER_STAR[160,128,BASEANGLE]

             BASEANGLE=(BASEANGLE+1) mod 360



         ' -------------------------------------------------
         ' Render 3D Scene
         ' -------------------------------------------------

   Gosub _UPDATE_3D



            KEYPRESS$=Inkey$()
            If KEYPRESS$=" " Then Exit

       Loop


        ' -----------------------------------  
        ' Clean Up/Close Down AGE  
        ' -----------------------------------  
           AGE_CLEAN_UP


          End




'  ---------------------------------------------------------------
'    -----------------------------------------------------------  
'     -------------->> SUB ROUTINES & FUNCTIONS <<-------------
'    -----------------------------------------------------------  
'  ---------------------------------------------------------------  

_INIT_3D:


   'Define our number system.  In this demo i'm using 24:8
   ' (24 bit whole part, 8 bit fractional) fixed point  

     Global ACC
     ACC=256



   ' Vertex Buffer for the object, XYZ order groups of 3
    Dim VERTEX_BUFFER(2000)

   ' Rotated vertex buffer
    Dim ROTATED_VERTEX_BUFFER(2000)

   ' Face list for Object
     Dim FACE_LIST(1000)

   '  CReate SIN/COS Tables
     Dim CS(720)
     Dim SN(720)
     Shared CS()
     Shared SN()

     INIT_MATH_TABLES[720]


    ' CReate a Cube mesh in the vertex buffer array

      PTR=Varptr(VERTEX_BUFFER(0))

      INIT_CUBE_VERTEX_BUFFER[PTR,BX_WIDTH,BX_HEIGHT,BX_DEPTH]

      PTR=Varptr(FACE_LIST(0))

      INIT_CUBE_FACE_LIST[PTR]

      FACECOUNT=Param


    Return



'  ---------------------------------------------------------------
'    -----------------------------------------------------------  
'          -------------->> UPDATE 3D SCENE <<-------------
'    -----------------------------------------------------------  
'  ---------------------------------------------------------------  

_UPDATE_3D:


     SRCPTR=Varptr(VERTEX_BUFFER(0))
     DESTPTR=Varptr(ROTATED_VERTEX_BUFFER(0))


      VERTS=8

      ROTATE_POINTS[SRCPTR,DESTPTR,8,160,128,300,ALPHA,BETA,GAMMA]

      ALPHA=(ALPHA+1) mod 360
      BETA=(BETA+2) mod 360
       GAMMA=(GAMMA+3) mod 360

      VERTCOUNT=(VERTS-1)*3
       For LP=0 To VERTCOUNT Step 3

           X=ROTATED_VERTEX_BUFFER(LP)
           Y=ROTATED_VERTEX_BUFFER(LP+1)

           AGE_CIRCLEC[X,Y,5,100]


       Next


      COUNT=(FACECOUNT-1)*3
       For LP=0 To COUNT Step 3

           V1=FACE_LIST(LP)*3
           V2=FACE_LIST(LP+1)*3
           V3=FACE_LIST(LP+2)*3

           X1=ROTATED_VERTEX_BUFFER(V1)
           Y1=ROTATED_VERTEX_BUFFER(V1+1)

           X2=ROTATED_VERTEX_BUFFER(V2)
           Y2=ROTATED_VERTEX_BUFFER(V2+1)

           X3=ROTATED_VERTEX_BUFFER(V3)
           Y3=ROTATED_VERTEX_BUFFER(V3+1)

           AX=X2-X1
           AY=Y2-Y1
 
           BX=X3-X1
           BY=Y3-Y1

           If((AX*BY)-(BX*AY))<0

            Z1=ROTATED_VERTEX_BUFFER(V1+2)
            Z2=ROTATED_VERTEX_BUFFER(V2+2)
            Z3=ROTATED_VERTEX_BUFFER(V3+2)

            C1=(Z1/500.0)*100
            C2=(Z2/500.0)*100
            C3=(Z3/500.0)*100
Add C1,156
Add C2,156
Add C3,156

                AGE_GOURAUDTRI[X1,Y1,C1,X2,Y2,C2,X3,Y3,C3]

           End If

       Next

     Return




'  ---------------------------------------------------------------
'    -----------------------------------------------------------  
'          -------->> INIT MATH (COS/SIN) Tables <<----------
'    -----------------------------------------------------------  
'  ---------------------------------------------------------------  


Procedure INIT_MATH_TABLES[SIZE]
  For LP=0 To SIZE
      CS(LP)=Cos(LP)*ACC
      SN(LP)=Sin(LP)*ACC
  Next
End Proc


' --------------------------------------------------------------------
'    ROTATE POINTS
' --------------------------------------------------------------------

Procedure ROTATE_POINTS[SRCPTR,DESTPTR,VERTS,XPOS,YPOS,ZPOS,ALPHA,BETA,GAMMA]

  AX=ALPHA
  AY=BETA
  AZ=GAMMA

' cos&sin alpha pre calcs
  CA=CS(AX)
  SA=SN(AX)

' Cos & Sin Beta pre calc
  CB=CS(AY)
  SB=SN(AY)


' Cos & Sin Gamma pre calcs
  CG=CS(AZ)
  SG=SN(AZ)

  XPOS2=XPOS*ACC
  YPOS2=YPOS*ACC


     For I=0 To VERTS
 
        X=Leek(SRCPTR)
        Y=Leek(SRCPTR+4)
        Z=Leek(SRCPTR+8)

        SRCPTR=SRCPTR+12

        Y2=((Y*CA)+(Z*SA))/ACC
        Z=((Z*CA)-(Y*SA))/ACC
     '   Y=Y2
        X2=((X*CB)+(Z*SB))/ACC
        Z=((Z*CB)-(X*SB))/ACC
        '   X=X2
        Y=(Y2*CG)+(X2*SG)
        X=(X2*CG)-(Y2*SG)
 
        Add Z,ZPOS


        Loke DESTPTR,(X/Z)+XPOS
        Loke DESTPTR+4,(Y/Z)+YPOS
        Loke DESTPTR+8,Z

        DESTPTR=DESTPTR+12


  Next I


End Proc



Procedure INIT_CUBE_VERTEX_BUFFER[VERTBUFFERPTR,BX_WIDTH,BX_HEIGHT,BX_DEPTH]

  BX_WIDTH=120
  BX_HEIGHT=120
  BX_DEPTH=120

  DESTPTR=VERTBUFFERPTR

  For Z=1 To -1 Step -2

     ZPOS=(BX_DEPTH/2)*(Z)

     For Y=-1 To 1 Step 2

        YPOS=(BX_HEIGHT/2)*(Y)
        For X=-1 To 1 Step 2
       
           XPOS=(BX_WIDTH/2)*(X)

           Loke DESTPTR,XPOS
           Loke DESTPTR+4,YPOS
           Loke DESTPTR+8,ZPOS

           DESTPTR=DESTPTR+12

        Next X
     Next Y
  Next Z


End Proc



Procedure INIT_CUBE_FACE_LIST[FACEBUFFERPTR]

  PTR=FACEBUFFERPTR

 ' front  
  SET_FACE[PTR,0,1,3] : Add PTR,12
  SET_FACE[PTR,0,3,2] : Add PTR,12

 ' Back  
  SET_FACE[PTR,5,4,6] : Add PTR,12
  SET_FACE[PTR,5,6,7] : Add PTR,12


 ' top      
  SET_FACE[PTR,4,5,1] : Add PTR,12
  SET_FACE[PTR,4,1,0] : Add PTR,12

 ' bottom      
  SET_FACE[PTR,2,3,7] : Add PTR,12
  SET_FACE[PTR,2,7,6] : Add PTR,12


 ' left      
  SET_FACE[PTR,0,2,6] : Add PTR,12
  SET_FACE[PTR,0,6,4] : Add PTR,12

 ' right        
  SET_FACE[PTR,1,5,7] : Add PTR,12
  SET_FACE[PTR,1,7,3] : Add PTR,12



 FACECOUNT=12

End Proc[FACECOUNT]



Procedure SET_FACE[PTR,V1,V2,V3]
  Loke PTR,V1
  Loke PTR+4,V2
  Loke PTR+8,V3
End Proc








Procedure RENDER_STAR[X,Y,BASEANGLE]

        AGE_INK[1]

      ' -----------------------------------------------------------------
      ' Draw a bunch of rotating circles in orbit around the screen center
      ' -----------------------------------------------------------------

           For ANGLE=0 To 359 Step 20

               ANGLE2=BASEANGLE+ANGLE
             '  ANGLE2=ANGLE mod 360

               X2=X+Cos(ANGLE2)*100
               Y2=Y+Sin(ANGLE2)*100


               AGE_CIRCLE[X2,Y2,20]

               Inc INDEX
                AGE_INK[INDEX]


           Next


End Proc



Procedure MAKE_PALETTE[THISSCREEN,RGB1,RGB2,INDEX_START,INDEX_END]

   RANGE#=INDEX_END-INDEX_START

   For LP=0 To RANGE#

      SCALER#=LP/RANGE#

      RGB_ALPHA_BLEND[RGB1,RGB2,SCALER#]
      AGE_SCREEN_SET_PALETTE_COLOUR[THISSCREEN,INDEX_START+LP,Param]
    Next

End Proc





ATLUS


kevin

AGE - 300 triangle Gouraud Donut (Torus) in Amos Pro ( AGA)

     This is only a small step from the previous demo, here we're just upping the vertex and polygon counts dramatically,  from the humble cube of 6 verts and 12 polygons (triangles), to a 300 triangle torus..  While the scene  / polygon count are old hat for assembly programmers on the AMIGA,  I don't recall ever seeing anything in AMOS do this,  so it's likely to be world first in AMOS anyway. 

     The demo is doing all the 3D worlk in interpreted AMOS, so it's rotating / projecting and rotating the 150 vertexes, back facing and rendering the 300 faces (approximate 150 odd visible faces),  the drawing all AGE obviously..  But it shows that you can certainly have a bit of fun with the library if you put your mind to it.   


kevin

   AGE-  Copy Rect / Copy Rect Queue

     Still making my way through the commands when free time appears, fixed a number of little issues here and there.  Most of the changes have been to function names or adding the odd little helper function.   In the older version of the library, there's a copy image / rect function, with a long but complete name, while descriptive, it wasn't practical.  So that's been renamed to AGE_COPY_RECT.  This function copies 'blocks' of graphics from one screen surface to another.   Now since we're running the library from interpreted AMOS,  you'll notice there's some QUEUED versions of functions also. Basically, these allows us to set to list of things to draw as batch.  


     In the example bellow we're using the Copy Rect Queue function to create a randomized scrolling block map.  To build the queue, we need to allocate some memory of suitable size, here i'm using an array but you can use a bank or whatever.    Each item in the queue is 16 bytes,  so to store a 100 items in the queue you'd allocate 100*16 bytes.    To write to the queue there's a helper function called AGE_SET_RECT_QUEUE  which requires the pointer to the first item in the queue, the Offset this item should be stored at, then Screen Index, source rect and destination and location.  For this example it's just randomly picking 16*16 blocks from the dragon picture.  

     Now to help avoid some Amos overhead, we can draw the queue with an X and Y offset.  So to make the scene scroll, we're just drawing the queue items offset from their output location.  




  Set Buffer 100

' *=-------------------------------------------------------------------=*
'
'                AGE - Copy Rect Queues (Block Map Example)
'
'                                      By  
'
'                                By Kevin Picone
'
'                         Last Updated - 28th, Mar, 2012                  
'
'                (c) Copyright 1997/98/1999/2000- 2012, Kevin Picone
'
'                             www.UnderwareDesign.com        
'
' *=-------------------------------------------------------------------=*
'

   ' Sorry but AMOSPRO seems to require absolute include paths ??  
   '  SO,  YOU'LL HAVE TO TWEAK THE PATHS IN ORDER TO RUN
   '  THE DEMOS FROM AMOS/AMOSPRO correctly on your machine    


   ' To make the pathing less annoying, here we store the 'root path'  
   '  in a variable APPPATH$ .. Then use this through our program.  


     APPPATH$="Dh0:/AGE_V102/"



    ' Set the location of the AGE lib..  
      AGE_LIBRARY_PATH$=APPPATH$+"Includes/Asm/Age.lib"

    ' Include the AGE wrapper into your AMOS project
      Include "Dh0:/AGE_V102/INCLUDES/AMOS/AGE_V071.AMOS"



'   *=-----------------------------------------------------------------=*    
'
'                        >> ALLOC AGE RESOURCE TABLEs <<
'
'   *=-----------------------------------------------------------------=*    

           SCRNS=15
           COPS=15
           BLKDATAS=10
           BANKS=11

           FONTS=12
           FILECACHESIZE=50000
           DCACHESIZE=10000

           AGE_ALLOC_RESOURCES[SCRNS,COPS,BLKDATAS,BANKS,FONTS,FILECACHESIZE,DCACHESIZE]


        ' -----------------------------------  
        ' Create our LOWRES / PLANAR  AGE screens in Chip Memory  
        ' -----------------------------------  
            TYPE=AGE_LOWRES+AGE_PLANAR

            AGE_OPEN_SCREEN[0,320,256,8,TYPE]
            AGE_OPEN_SCREEN[1,320,256,8,TYPE]


            CURRENT_BUFFER=0


        ' -----------------------------------  
        ' CReate  Load IFF into this a temp screen.    
        ' -----------------------------------  

            CHUNKY_BUFFER=3

            AGE_OPEN_CHUNKY_SCREEN[CHUNKY_BUFFER,320,256]



        ' -----------------------------------  
        '  Load IFF into this a temp screen.  
        ' -----------------------------------  

             CHUNKY_PICTURE=4

            FILE$=APPPATH$+"GFXFILES/PICTURES/DRAGONAA_156.IFF"

            AGE_OPEN_CHUNKY_SCREEN[CHUNKY_PICTURE,320,256]
            AGE_LOAD_IFF_TO_SCREEN[FILE$,CHUNKY_PICTURE]


       ' copy the palette from the backdrop picture in the chip buffers


             AGE_SCREEN_COPY_PALETTE[CHUNKY_PICTURE,0]
             AGE_SCREEN_COPY_PALETTE[CHUNKY_PICTURE,1]





        ' -----------------------------------  
        ' Create standard / simple copper list for viewing our screens.    
        ' -----------------------------------  
             AGE_CREATE_COPPER[0,0,3,8]
             AGE_CREATE_COPPER[1,1,3,8]


        ' -----------------------------------  
        '  Set copper to view our AGE screen  
        ' -----------------------------------  
            Doke $DFF096,$180 : Rem Kill Bitplane + copper DMA  

            AGE_WAIT_TOP_OF_FRAME

            AGE_SHOW_COPPER[1-CURRENT_BUFFER]

            Doke $DFF096,$8180 : Rem restore Bitplane + copper DMA  



       Degree





        ' -------------------------------------------------
        ' Init the scene
        ' -------------------------------------------------


           Gosub _CREATE_RECT_QUEUE



           AGE_SET_SCREEN[CHUNKY_BUFFER]


       Do


         ' -------------------------------------------------
         ' Swap Buffers
         ' -------------------------------------------------


             AGE_C2P[CHUNKY_BUFFER,CURRENT_BUFFER]

             CURRENT_BUFFER=1-CURRENT_BUFFER

             AGE_SET_COPPER[(1-CURRENT_BUFFER)]

             AGE_WAIT_TOP_OF_FRAME


         ' -------------------------------------------------
         ' Copy the Backdrop picture to the main chunky buffer screen
         ' -------------------------------------------------

         '    AGE_COPY_RECT[CHUNKY_PICTURE,0,0,319,256,CHUNKY_BUFFER,-SCRLLX,0]
         '    AGE_COPY_RECT[CHUNKY_PICTURE,0,0,319,256,CHUNKY_BUFFER,-SCRLLX+320,0]

              AGE_COPY_RECT_QUEUE[QUEUE_POINTER,-SCRLLX,-SCRLLY,BLOCK_COUNT]
              AGE_COPY_RECT_QUEUE[QUEUE_POINTER,-SCRLLX+320,-SCRLLY,BLOCK_COUNT]


              AGE_COPY_RECT_QUEUE[QUEUE_POINTER,-SCRLLX,-SCRLLY+256,BLOCK_COUNT]
              AGE_COPY_RECT_QUEUE[QUEUE_POINTER,-SCRLLX+320,-SCRLLY+256,BLOCK_COUNT]


              SCRLLX=(SCRLLX+1) mod 320
              SCRLLY=(SCRLLY+1) mod 256



         ' -------------------------------------------------
         ' Check for any key presses
         ' -------------------------------------------------

            KEYPRESS$=Inkey$()
            If KEYPRESS$=" " Then Exit

       Loop


        ' -----------------------------------  
        ' Clean Up/Close Down AGE  
        ' -----------------------------------  
           AGE_CLEAN_UP


   End





'  ---------------------------------------------------------------
'    -----------------------------------------------------------  
'     -------------->> SUB ROUTINES & FUNCTIONS <<-------------
'    -----------------------------------------------------------  
'  ---------------------------------------------------------------  

_CREATE_RECT_QUEUE:


        ' -------------------------------------------------
        ' Fill the Copy Rect Queue
        ' -------------------------------------------------

           ' This routine makes a queue of 100,  16*16 block
           ' to be drawn at a target.  The target can be offset
           ' at run time. So you cna make block map.

            BLOCKS_WIDE=(320/16)
            BLOCKS_HIGH=(256/16)


            BLOCK_COUNT=BLOCKS_WIDE*BLOCKS_HIGH


          ' DIm an array to hold all the queue data in.
          ' each queue item takes 16 bytes

            Dim BLOCKQUEUE((BLOCK_COUNT+1)*16)


            QUEUE_POINTER=Varptr(BLOCKQUEUE(0))

         ' Fill in the queue wwith the copy rects

          For LP=0 To BLOCK_COUNT-1

              THISBLOCK=Rnd(BLOCK_COUNT-1)

              SRCY1=THISBLOCK/BLOCKS_WIDE
              SRCX1=THISBLOCK mod BLOCKS_WIDE

              SRCX1=SRCX1*16
              SRCY1=SRCY1*16

              SRCX2=SRCX1+16
              SRCY2=SRCY1+16

              AGE_SET_RECT_QUEUE[QUEUE_POINTER,LP,CHUNKY_PICTURE,SRCX1,SRCY1,SRCX2,SRCY2,CHUNKY_BUFFER,DEST_XPOS,DEST_YPOS]

              DEST_XPOS=DEST_XPOS+16
              If DEST_XPOS=>320

                    DEST_XPOS=0
                    DEST_YPOS=DEST_YPOS+16

              End If

          Next

    Return







kevin


   AGE-  Star Field / Dot Queue

       In keeping with the previous demo,  here we're another golden oldie, the star field.   The demo is drawing 5 layers of 500 pixels (in chunky) over the top of the scrolling picture and the orbiting circles.  Yep, it's cut 'n;paste from the same template as most of the other demos are.    Each layer of dots is scrolling faster than the previous layer. 

       To make the star field,  we're creating a dot queue for each layer in the scene.  This time rather than use Amos arrays for our queue data, were allocated AGE Bank's for each queue.   Then storing random dot positions in the queue's via the helper function AGE_SET_DOT_QUEUE.  This function write the coordinate and colour into our allocated buffer.    Each dot in the queue costs us  6 bytes, (16bit X, 16bit Y, 16bit Colour).  So the size of the dot queue of 50 points is going to use up (50*6)=300 bytes. 

       Just like the copy rect demo, we're able to render a queue offset from a user defined position. So to make the fields move, we're just bumping a scroll speed variable  each layer. Then using that to offset the batch.
 


   Set Buffer 100

' *=-------------------------------------------------------------------=*
'
'                  AGE - Star Field (DOT QUEUE Example)
'
'                                      By 
'
'                                By Kevin Picone
'
'                         Last Updated - 31st, Mar, 2012                   
'
'                (c) Copyright 1997/98/1999/2000- 2012, Kevin Picone
'
'                             www.UnderwareDesign.com       
'
' *=-------------------------------------------------------------------=*
'

    ' Sorry but AMOSPRO seems to require absolute include paths ??   
    '  SO,  YOU'LL HAVE TO TWEAK THE PATHS IN ORDER TO RUN
    '  THE DEMOS FROM AMOS/AMOSPRO correctly on your machine     


    ' To make the pathing less annoying, here we store the 'root path'   
    '  in a variable APPPATH$ .. Then use this through our program. 


      APPPATH$="Dh0:/AGE_V102/"



     ' Set the location of the AGE lib.. 
       AGE_LIBRARY_PATH$=APPPATH$+"Includes/Asm/Age.lib"

     ' Include the AGE wrapper into your AMOS project
       Include "Dh0:/AGE_V102/INCLUDES/AMOS/AGE_V072.AMOS"



'   *=-----------------------------------------------------------------=*   
'
'                        >> ALLOC AGE RESOURCE TABLEs <<
'
'   *=-----------------------------------------------------------------=*   

            SCRNS=15
            COPS=15
            BLKDATAS=10
            BANKS=11

            FONTS=12
            FILECACHESIZE=50000
            DCACHESIZE=10000

            AGE_ALLOC_RESOURCES[SCRNS,COPS,BLKDATAS,BANKS,FONTS,FILECACHESIZE,DCACHESIZE]


         ' ----------------------------------- 
         ' Create our LOWRES / PLANAR  AGE screens in Chip Memory   
         ' ----------------------------------- 
             TYPE=AGE_LOWRES+AGE_PLANAR

             AGE_OPEN_SCREEN[0,320,256,8,TYPE]
             AGE_OPEN_SCREEN[1,320,256,8,TYPE]


             CURRENT_BUFFER=0


         ' ----------------------------------- 
         ' CReate  Load IFF into this a temp screen.   
         ' ----------------------------------- 

             CHUNKY_BUFFER=3

             AGE_OPEN_CHUNKY_SCREEN[CHUNKY_BUFFER,320,256]



         ' ----------------------------------- 
         '  Load IFF into this a temp screen.   
         ' ----------------------------------- 

              CHUNKY_PICTURE=4

             FILE$=APPPATH$+"GFXFILES/PICTURES/DRAGONAA_156.IFF"

             AGE_OPEN_CHUNKY_SCREEN[CHUNKY_PICTURE,320,256]
             AGE_LOAD_IFF_TO_SCREEN[FILE$,CHUNKY_PICTURE]


        ' copy the palette from the backdrop picture in the chip buffers


              AGE_SCREEN_COPY_PALETTE[CHUNKY_PICTURE,0]
              AGE_SCREEN_COPY_PALETTE[CHUNKY_PICTURE,1]





         ' ----------------------------------- 
         ' Create standard / simple copper list for viewing our screens.   
         ' ----------------------------------- 
              AGE_CREATE_COPPER[0,0,3,8]
              AGE_CREATE_COPPER[1,1,3,8]


         ' ----------------------------------- 
         '  Set copper to view our AGE screen   
         ' ----------------------------------- 
             Doke $DFF096,$180 : Rem Kill Bitplane + copper DMA   

             AGE_WAIT_TOP_OF_FRAME

             AGE_SHOW_COPPER[1-CURRENT_BUFFER]

             Doke $DFF096,$8180 : Rem restore Bitplane + copper DMA 



        Degree





         ' -------------------------------------------------
         ' Init the scene
         ' -------------------------------------------------


            Gosub _CREATE_STAR_FIELDS


            AGE_SET_SCREEN[CHUNKY_BUFFER]


        Do


          ' -------------------------------------------------
          ' Swap Buffers
          ' -------------------------------------------------


              AGE_C2P[CHUNKY_BUFFER,CURRENT_BUFFER]

              CURRENT_BUFFER=1-CURRENT_BUFFER

              AGE_SET_COPPER[(1-CURRENT_BUFFER)]

              AGE_WAIT_TOP_OF_FRAME


          ' -------------------------------------------------
          ' Copy the Backdrop picture to the main chunky buffer screen
          ' -------------------------------------------------

               AGE_COPY_RECT[CHUNKY_PICTURE,0,0,319,256,CHUNKY_BUFFER,-SCRLLX,0]
               AGE_COPY_RECT[CHUNKY_PICTURE,0,0,319,256,CHUNKY_BUFFER,-SCRLLX+320,0]


               SCRLLX=(SCRLLX+1) mod 320
               SCRLLY=(SCRLLY+1) mod 256






          ' -------------------------------------------------
          ' Render a bunch of orbiting circles
          ' -------------------------------------------------

                 RENDER_CIRCLES[160,128,BASEANGLE]

                 BASEANGLE=(BASEANGLE+1) mod 360



          ' -------------------------------------------------
          ' Render Star field 
          ' -------------------------------------------------

               Gosub _RENDER_STAR_FIELD



          ' -------------------------------------------------
          ' Check for any key presses
          ' -------------------------------------------------

             KEYPRESS$=Inkey$()
             If KEYPRESS$=" " Then Exit

        Loop


         ' ----------------------------------- 
         ' Clean Up/Close Down AGE 
         ' ----------------------------------- 
            AGE_CLEAN_UP


    End





'  ---------------------------------------------------------------
'    -----------------------------------------------------------   
'     -------------->> SUB ROUTINES & FUNCTIONS <<-------------
'    -----------------------------------------------------------   
'  ---------------------------------------------------------------   

_CREATE_STAR_FIELDS:

     Global ACC
      ACC=256


     Dim CS(720)
     Dim SN(720)
     Shared CS()
     Shared SN()
     INIT_MATH_TABLES[720]


         ' -------------------------------------------------
         ' Each Star Field Is a  DOT Queue 
         ' -------------------------------------------------

            ' Number of dots in each layer

             STAR_COUNT=500


            ' Number of star Layers
             STAR_LAYERS=5


            ' Dim array to store the layers SCroll offsets

             Dim STAR_SCROLLX(STAR_LAYERS)



           ' Calc the size of the Star layer in bytes
             LAYER_SIZE_IN_BYTES=(STAR_COUNT+1)*6


           ' Init the star queue (buffers)
             For LP=0 To STAR_LAYERS-1
                 AGE_CREATE_BANK[LP,LAYER_SIZE_IN_BYTES]

                 AGE_GET_BANK_PTR[LP]

                 _FILL_QUEUE[Param,STAR_COUNT]

            Next

     Return




_RENDER_STAR_FIELD:


             For LP=0 To STAR_LAYERS-1


               AGE_GET_BANK_PTR[LP]
               QUEUE_POINTER=Param

               If QUEUE_POINTER

                  X=STAR_SCROLLX(LP)
                   X=X+(LP+1)
                   STAR_SCROLLX(LP)=X mod 320

                   AGE_DOT_QUEUE[QUEUE_POINTER,-X,0,STAR_COUNT]
                   AGE_DOT_QUEUE[QUEUE_POINTER,-X+320,0,STAR_COUNT]

               End If

            Next


   Return





'  ---------------------------------------------------------------
'  -----------------------------------------------------------   
'    >> FILL DOT QUEUE with random dots <<----------
'  -----------------------------------------------------------   
'  ---------------------------------------------------------------   


Procedure _FILL_QUEUE[PTR,STARS]

          ' Fill in the queue with some random pixels

           For STARLP=0 To STARS-1

               X=Rnd(319)
               Y=Rnd(255)
               C=Rnd(255)

               AGE_SET_DOT_QUEUE[PTR,STARLP,X,Y,C]

           Next
End Proc









'  ---------------------------------------------------------------
'  -----------------------------------------------------------   
'    >> INIT MATH (COS/SIN) Tables <<----------
'  -----------------------------------------------------------   
'  ---------------------------------------------------------------   


Procedure INIT_MATH_TABLES[SIZE]
   For LP=0 To SIZE
       CS(LP)=Cos(LP)*ACC
       SN(LP)=Sin(LP)*ACC
   Next
End Proc






' -----------------------------------------------------------------
' -----------------------------------------------------------------
'   >> Render Circles <<
' -----------------------------------------------------------------
' -----------------------------------------------------------------


Procedure RENDER_CIRCLES[X,Y,BASEANGLE]

         AGE_INK[1]


       ' -----------------------------------------------------------------
       ' Draw a bunch of rotating circles in orbit around the screen center
       ' -----------------------------------------------------------------

            For ANGLE=0 To 359 Step 10

                ANGLE2=BASEANGLE+ANGLE

                X2=CS(ANGLE2)*100
                Y2=SN(ANGLE2)*100

                X2=X+(X2/ACC)
                Y2=Y+(Y2/ACC)

                Inc INDEX

                AGE_CIRCLEC[X2,Y2,20,INDEX]

            Next


End Proc



kevin

   AGE - Texture Mapped Dragon

     AGE supports texture mapped triangles, the lib is a lot like PlayBASIC really, just not as complete.    The texture mapping works in AGE, but i'm not 100% happy with the rendering code,  mainly the edges conversion is a bit dodgy, so the left and right fill convention doesn't seem all that accurate.  I'd like to re-write it, and probably will, but better not just now.  

      Anyway, in this picture you can see the Dragon model (converted from quake MD2 format, into vertex and face lists)  spinning in the middle of the screen.  It's here we find a few omissions in the scene buffer implementation in AGE.   AGE uses a capturing interface where we create a Z buffer cache, then call special functions to buffer our items up in the cache.    When we're done, we call the Render scene function, which sorts and renders the scene. This eliminates the need to sort the triangles in AMOS.  The issue with the buffer is that it's missing support for texture mapped triangles.  So the scene bellow is not actually z buffered..  Will have to fix that in order to make the library more useful.  

      If you're wondering how fast this stuff is, well it's not express, but of you're only interested in AMOS programming under emulation, then with WinUAE's  JIT enabled it's quite fast considering.  It'll be interesting seeing what people can knock up with it.  

kevin

  AGE - Line Clipping

       As mentioned previously, the library has a lot of meat on the bones in some areas and then in others there's glaring omissions.    The line support was another part of the library that I'm not comfortable re-releasing as is.   There's a few reasons for this,  primarily the existing version of the LINE function only supports rendering to chip memory via Blitter and the clipping isn't stellar.   While it works, it's a bit of bottleneck.   But there's a problem looming for me, which is time and a complete lack of it for such side projects.

       To speed up development of the library and to make extending it more viable in the future, i'm now using a mixture of C and Assembly via VBCC / Phxass.  Which just means that in In terms of convenience, I can leverage the code base that PlayBASIC is based upon.   So far, i've just been tinkering with it tonight, but i'm already satisfied it's a workable solution.  Although was having a few dramas initially.. But the VBCC compiler seems more than  happy to produce some decent inner loops,  can always inline them if they're not.     

       One difference to the PB libraries is that AGE is all fixed point integer operations, where PB's is generally floating point with integer inner loops.   So rather than drag and drop the line clipper across, found myself having to write an integer version instead... yes... typical.. :) .  Anyway, whats interesting is that while I've looked at the older clipper a million times,  tonight it dawned on me there's another (pretty obvious) simplification just waiting to be implemented.   So with a little messing around, the pure integer version seems to work rather well in the test.  Will have to add that in not only to AGE, but PB also...


kevin


  AGE - Line Render (With Brute Force Clipping)

     Ok, so last nights little chore (see understatement..), was to drag some of the PB render functions over and make AGE friendly versions.   The PB backend is generally C++ (but with C styled render functions) and we're moving to VBCC which is a C compiler,  which creates a few syntax issues here and there.  But ya get that. 
 
     Figured I'd just use VBCC to process the C code to asm,  add some macros for our functions and bobs your uncle.     But soon run into some problems with compile speed and ultimately collision issues on the assembler side.   Had assumed the  C compiler would use local labels in the output, but it doesn't seem to, there may well be a switch to turn such a  feature on, I dunno.   

     How i imagined this working,  was that I'd  just compiling all the C stuff into one blob of assembly, renaming some labels and include.  But when compiling the code on the Amiga side,  through winUae with -O4 enabled, the process turned out to be  pretty time consuming, given it's length.  So figured a better (easier/quicker) solution would be to split the C side up into seperate stand alone files.   Then compile the parts are needed.  This works pretty well speed wise, but we get collisions in the output code from the labels. 

     To counter the collision hurdle, ended up writing a little app in PlayBASIC to run through and clean up the fragments.  So the work flow is drop the function into C,  convert that to 68K, clean the output code and include the resulting assembly output into AGE.   A bit of messing around, but not too bad, had worse.. :)  -   Could probably have written the line draw stuff in assembly is less time, but this is just easier all around.  Yeah, i'm getting lazy in my old age..

     Ok after all that messing around we're now got a Draw Line function that draw to chunky screens.   The version of the function you're looking at is brute force clipped (every dot is clipped to the viewport),  since i'm yet to drag the clipper across.  Had figured all that'd all be done yesterday, but then all the above happened.   None the less the routine works pretty well in AGE, when with brute force clipping.   This version only draws to chunky screens though, the old blitter based solution is used on planar screens.   The trouble with blitter version is there's all this latency between each planar pass.   Haven't tested it, but I've sneaking suspicion a cpu filler would be better.

     Anyway, here's a bit of scene made from the star field demo with some clipped lines on top of that.. 

   

kevin

  AGE - 8bit Planar Dot Render (Brute Force)

        After adding the chunky line function, i've been having somewhat of an adventure with dot rendering on planar surfaces.  Those who are familiar with planar know the pain for dot rendering to such surfaces.   While i've trimmed some fat from the PLANAR DOT rendering routines in AGE, it's certainly not going to be express.     But it's supported just in case you absolute have to have it.

       The dot plot routine basically is a loop of Bit Sets / Clears across the planes.  Rendering to an 8Bit surface, means there's 8 iterations per dot to set the correct colour.   Had a play with unrolling the bitsets, which seemed a little quicker, but couldn't justify the bulk of unrolling every colour combination would create.   Those you know some AMOS and a little 680x0 assembly knowledge,  you could probably allocate a bank and unroll the code into memory yourself then just call it.   This approach is commonly found in many old school Amiga demos..    

        Personally, I'd recommend you avoid Planar screen types altogether and just use CHUNKY screens and C2P the result to the planar display.   The performance of this approach  under emulation is pretty good with JIT enabled in WinUAE.. I'm guessing those more familiar with AMOS, will be able to squeeze out more performance than me also.    None of the examples are compiled in BTW,  I'm just running them through the AMOS interpreter, so there's certainly some meat on the bones performance wise.

       
       Anyway, here's the code for the demo.   Finally changed backdrop pictures.. :)  

   


Set Buffer 50

' *=-------------------------------------------------------------------=*
'
'             AGE - ANIMATION  - PLANAR DOT RENDERING (Brute Force)  
'
'                                      By  
'
'                                By Kevin Picone
'
'                         Last Updated - 9th, Apr, 2012                  
'
'                (c) Copyright 1997/98/1999/2000- 2012, Kevin Picone
'
'                             www.UnderwareDesign.com        
'
' *=-------------------------------------------------------------------=*
'

   ' Sorry but AMOSPRO seems to require absolute include paths ??  
   '  SO,  YOU'LL HAVE TO TWEAK THE PATHS IN ORDER TO RUN
   '  THE DEMOS FROM AMOS/AMOSPRO correctly on your machine    


   ' To make the pathing less annoying, here we store the 'root path'  
   '  in a variable APPPATH$ .. Then use this through our program.  


     APPPATH$="Dh0:/AGE_V102/"


    ' Set the location of the AGE lib..  
      AGE_LIBRARY_PATH$=APPPATH$+"Includes/Asm/Age.lib"

    ' Include the AGE wrapper into your AMOS project
      Include "Dh0:/AGE_V102/INCLUDES/AMOS/AGE_V074.AMOS"



'   *=-----------------------------------------------------------------=*    
'
'                        >> ALLOC AGE RESOURCE TABLEs <<
'
'   *=-----------------------------------------------------------------=*    

           SCRNS=15
           COPS=15
           BLKDATAS=10
           BANKS=11

           FONTS=12
           FILECACHESIZE=50000
           DCACHESIZE=10000

           AGE_ALLOC_RESOURCES[SCRNS,COPS,BLKDATAS,BANKS,FONTS,FILECACHESIZE,DCACHESIZE]


        ' -----------------------------------  
        ' Create our LOWRES / INTERLEAVED  AGE screen in Chip Memory '
        ' -----------------------------------  
            TYPE=AGE_LOWRES
'            TYPE=TYPE+AGE_INTERLEAVED
            TYPE=TYPE+AGE_PLANAR

            AGE_OPEN_SCREEN[0,320,256,8,TYPE]
            AGE_OPEN_SCREEN[1,320,256,8,TYPE]

            CURRENT_BUFFER=0



        ' -----------------------------------  
        '  Load IFF into this a temp screen.  
        ' -----------------------------------  

              FILE$=APPPATH$+"GFXFILES/PICTURES/TREE.IFF"

             AGE_OPEN_SCREEN[3,320,256,8,TYPE]
             AGE_LOAD_IFF_TO_SCREEN[FILE$,3]

       ' copy the palette from the backdrop picture in the chip buffers

             AGE_SCREEN_COPY_PALETTE[3,0]
             AGE_SCREEN_COPY_PALETTE[3,1]


        ' -----------------------------------  
        ' Create standard / simple copper list for viewing our screens.    
        ' -----------------------------------  
             AGE_CREATE_COPPER[0,0,3,8]
             AGE_CREATE_COPPER[1,1,3,8]


        ' -----------------------------------  
        '  Set copper to view our AGE screen  
        ' -----------------------------------  
            Doke $DFF096,$180 : Rem Kill Bitplane + copper DMA  

            AGE_WAIT_TOP_OF_FRAME

            AGE_SHOW_COPPER[1-CURRENT_BUFFER]

            Doke $DFF096,$8180 : Rem restore Bitplane + copper DMA  


       ' -----------------------------------  
       ' Direct ALL RENDERING To OUR Screen
       ' -----------------------------------  
            AGE_SET_SCREEN[CURRENT_BUFFER]


      ' -----------------------------------  
      ' Load a Font
      ' -----------------------------------  


            FONTS$=APPPATH$+"gfxfiles/fonts/"

            AGE_LOAD_FONT[FONTS$+"Alex8.font",2]

            AGE_SET_FONT[2]



Degree


            TIME=Timer
            REDRAWS=0
            FPS=0


       Do

         ' -------------------------------------------------
         ' Swap Buffers
         ' -------------------------------------------------

             CURRENT_BUFFER=1-CURRENT_BUFFER

             AGE_SET_SCREEN[CURRENT_BUFFER]

             AGE_SET_COPPER[(1-CURRENT_BUFFER)]

             AGE_WAIT_TOP_OF_FRAME


         ' -------------------------------------------------
         ' Copy the temp image to the current render buffer
         ' -------------------------------------------------

            AGE_COPY_RECT[3,0,0,320,256,CURRENT_BUFFER,0,0]


         ' -------------------------------------------------
         ' Draw Layer Of Colour Dots to the 8bit planar screen  
         ' -------------------------------------------------

            PAD=8

            XPOS=(XPOS+1) mod PAD

            RENDER_DOT_LAYER[-XPOS,PAD]

            COUNT=Param


         ' ---------------------------
         ' Render some text on the scene  
         ' ---------------------------

            AGE_TEXT["Brute Force PLANAR Dot Rendering",10,10,50]
            AGE_TEXT["Dot Count:"+Str$(COUNT),10,20,50]
            AGE_TEXT["Fps::"+Str$(FPS),10,30,50]


          ' calc the fps of this demo

            FRAMESPAST=Timer-SECOND_START

            RENDER=RENDER+1
            If FRAMESPAST=>50
                   FPS=RENDER
                   RENDER=0
                   SECOND_START=Timer
            End If



            KEYPRESS$=Inkey$()


             If KEYPRESS$=" " Then Exit
       Loop




        ' -----------------------------------  
        ' Clean Up/Close Down AGE  
        ' -----------------------------------  
           AGE_CLEAN_UP


          End







Procedure RENDER_DOT_LAYER[XPOS,PAD]

  For YLP=0 To 256 Step PAD

     XS=0+XPOS
     XE=320+XPOS

     For XLP=XS To XE Step PAD
          AGE_DOTC[XLP,YLP,XLP]
     Next

     COUNT=COUNT+(XLP/PAD)

  Next

End Proc[COUNT]




       NOTE: Not using a a DOT QUEUE in this example



 AGE - 8bit Planar Dot Render (QUEUE VERSION)

        This is basically the same demo, but this one has brute and queued (batching) in it.  In queued mode it'll draw about 5000 (8bit) planar points.  Building the queue is a little more hasle, but we get rid of lots of Amos function calling overhead by going the extra mile.  Even on planar screen, the speed is pretty good running under jitted emulation .




Set Buffer 50

' *=-------------------------------------------------------------------=*
'
'             AGE - ANIMATION  - PLANAR DOT RENDERING (Brute Force)  
'
'                                      By  
'
'                                By Kevin Picone
'
'                         Last Updated - 10th, Apr, 2012                  
'
'                (c) Copyright 1997/98/1999/2000- 2012, Kevin Picone
'
'                             www.UnderwareDesign.com        
'
' *=-------------------------------------------------------------------=*
'

   ' Sorry but AMOSPRO seems to require absolute include paths ??  
   '  SO,  YOU'LL HAVE TO TWEAK THE PATHS IN ORDER TO RUN
   '  THE DEMOS FROM AMOS/AMOSPRO correctly on your machine    


   ' To make the pathing less annoying, here we store the 'root path'  
   '  in a variable APPPATH$ .. Then use this through our program.  


     APPPATH$="Dh0:/AGE_V102/"


    ' Set the location of the AGE lib..  
      AGE_LIBRARY_PATH$=APPPATH$+"Includes/Asm/Age.lib"

    ' Include the AGE wrapper into your AMOS project
      Include "Dh0:/AGE_V102/INCLUDES/AMOS/AGE_V074.AMOS"



'   *=-----------------------------------------------------------------=*    
'
'                        >> ALLOC AGE RESOURCE TABLEs <<
'
'   *=-----------------------------------------------------------------=*    

           SCRNS=15
           COPS=15
           BLKDATAS=10
           BANKS=11



           FONTS=12
           FILECACHESIZE=50000
           DCACHESIZE=10000

           AGE_ALLOC_RESOURCES[SCRNS,COPS,BLKDATAS,BANKS,FONTS,FILECACHESIZE,DCACHESIZE]


        ' -----------------------------------  
        ' Create our LOWRES / INTERLEAVED  AGE screen in Chip Memory '
        ' -----------------------------------  
            TYPE=AGE_LOWRES
'            TYPE=TYPE+AGE_INTERLEAVED
            TYPE=TYPE+AGE_PLANAR

            AGE_OPEN_SCREEN[0,320,256,8,TYPE]
            AGE_OPEN_SCREEN[1,320,256,8,TYPE]

            CURRENT_BUFFER=0



        ' -----------------------------------  
        '  Load IFF into this a temp screen.  
        ' -----------------------------------  

              FILE$=APPPATH$+"GFXFILES/PICTURES/TREE.IFF"

             AGE_OPEN_SCREEN[3,320,256,8,TYPE]
             AGE_LOAD_IFF_TO_SCREEN[FILE$,3]

       ' copy the palette from the backdrop picture in the chip buffers

             AGE_SCREEN_COPY_PALETTE[3,0]
             AGE_SCREEN_COPY_PALETTE[3,1]


        ' -----------------------------------  
        ' Create standard / simple copper list for viewing our screens.    
        ' -----------------------------------  
             AGE_CREATE_COPPER[0,0,3,8]
             AGE_CREATE_COPPER[1,1,3,8]


        ' -----------------------------------  
        '  Set copper to view our AGE screen  
        ' -----------------------------------  
            Doke $DFF096,$180 : Rem Kill Bitplane + copper DMA  

            AGE_WAIT_TOP_OF_FRAME

            AGE_SHOW_COPPER[1-CURRENT_BUFFER]

            Doke $DFF096,$8180 : Rem restore Bitplane + copper DMA  


       ' -----------------------------------  
       ' Direct ALL RENDERING To OUR Screen
       ' -----------------------------------  
            AGE_SET_SCREEN[CURRENT_BUFFER]


      ' -----------------------------------  
      ' Load a Font
      ' -----------------------------------  


            FONTS$=APPPATH$+"gfxfiles/fonts/"

            AGE_LOAD_FONT[FONTS$+"Alex8.font",2]

            AGE_SET_FONT[2]



             Degree


            '  CReate a bank to store our queue version


          ' Init the star queue (buffers)

             WIDTH=320
             HEIGHT=256
             PIXEL_SPACING=4

             SIZE=WIDTH*HEIGHT

             AGE_CREATE_BANK[1,(SIZE+2)*6]


             AGE_GET_BANK_PTR[1]
             QUEUE_POINTER=Param


             QUEUE_DOT_LAYER[WIDTH,HEIGHT,PIXEL_SPACING,QUEUE_POINTER]


            REDRAWS=0
            FPS=0


       Do

         ' -------------------------------------------------
         ' Swap Buffers
         ' -------------------------------------------------

             CURRENT_BUFFER=1-CURRENT_BUFFER

             AGE_SET_SCREEN[CURRENT_BUFFER]

             AGE_SET_COPPER[(1-CURRENT_BUFFER)]

             AGE_WAIT_TOP_OF_FRAME


         ' -------------------------------------------------
         ' Copy the temp image to the current render buffer
         ' -------------------------------------------------

            AGE_COPY_RECT[3,0,0,320,256,CURRENT_BUFFER,0,0]


         ' -------------------------------------------------
         ' Draw Layer Of Colour Dots to the 8bit planar screen  
         ' -------------------------------------------------


            XPOS=(XPOS+1) mod PIXEL_SPACING

             If DEMO_MODE=0
                  RENDER_DOT_LAYER[-XPOS,WIDTH,HEIGHT,PIXEL_SPACING]
                  COUNT=Param



            Else

                   AGE_DOT_QUEUE[QUEUE_POINTER,-XPOS,0,COUNT]

             End If


         ' ---------------------------
         ' Render some text on the scene  
         ' ---------------------------

          If DEMO_MODE=0

              AGE_TEXT["8Bit Planar Dot Rendering (Brute Force)",10,10,50]

          End If

          If DEMO_MODE=1
            AGE_TEXT["8Bit Planar Dot Rendering (Queue)",10,10,50]

          End If


            AGE_TEXT["Dot Count:"+Str$(COUNT),10,20,50]
            AGE_TEXT["Fps::"+Str$(FPS),10,30,50]





          ' calc the fps of this demo

            FRAMESPAST=Timer-SECOND_START

            RENDER=RENDER+1
            If FRAMESPAST=>50
                   FPS=RENDER
                   RENDER=0
                   SECOND_START=Timer
            End If



            KEYPRESS$=Inkey$()

            If KEYPRESS$="m"

               DEMO_MODE=1-DEMO_MODE

            End If


             If KEYPRESS$=" " Then Exit
       Loop




        ' -----------------------------------  
        ' Clean Up/Close Down AGE  
        ' -----------------------------------  
           AGE_CLEAN_UP


          End







Procedure RENDER_DOT_LAYER[XPOS,WIDTH,HEIGHT,PAD]

  For YLP=0 To HEIGHT Step PAD

     XS=0+XPOS
     XE=WIDTH+XPOS

     For XLP=XS To XE Step PAD
          AGE_DOTC[XLP,YLP,INDEX]
          Inc INDEX

    Next

     COUNT=COUNT+(XLP/PAD)

  Next

End Proc[COUNT]




Procedure QUEUE_DOT_LAYER[WIDTH,HEIGHT,PAD,PTR]

  For YLP=0 To HEIGHT Step PAD


     For XLP=0 To WIDTH Step PAD
           C=XLP
           AGE_SET_DOT_QUEUE[PTR,STARLP,XLP,YLP,INDEX]
           STARLP=STARLP+1
           Inc INDEX

     Next

     COUNT=COUNT+(XLP/PAD)

  Next

End Proc[COUNT]





 AGE - Remap BOX (Colour Remapping)

    The AGE_REMAP_BOX function allows us to remap a rectangle of chunky pixels against a remap table of our choice.   To make the picture bellow, i'm drawing a bunch of 16 * 16 rects onto the chunky buffer at random positions.   Each rect is using a table that adds 2 to each colour index, where the colours are clamped at 255.    At the end of the frame, i'm subtracting one from every index.    

    So if a pixel is drawn say 5 times, then after this it's value will be 10.   The palette is set up so that colour index 0 is the backdrop coluor, where the entire 256 colour palette fades towards the brighter colour.    Since we're only subtracting one from each pixel each frame, the pixels appear to linger and then slowly fade out or cool down.  



monkeybot

i must ask,why are you doing this age project?

I loved the Amiga but why?...

kevin


   There's  plenty of reasons, but the one's that sparked my interest the most would be the release of Windows packaged version of AMOS.   This installer allows basic programmers run AMOS on Windows PC (via emulation of course) legally.    AGE isn't new,  it's much older than PlayBASIC.   All i'm doing here, is cleaning up the library (to a degree)  in order make it more useful for those intersted in AGA programming under AMOS emulation.     

 
 



   The rather interesting by product of using emulation like this, is that programmers could knock up little games/demos in AMOS then distribute them across various platforms, the same way AMOS is being distributed above..  Which is rather bizarre, but perfectly viable.