Sunday, April 14, 2013

AGA/OCS (planar) vs 8BIT CLUT (chunky)

Friday after work, and yester day I did some experimentation, people keep on saying how great AGA and OCS are for demos, is this really true? Does planar really have a advantage over 8bit CLUT chunky graphics. I think it does not, its just that planar modes, makes easier to do layering, and graphic card does the rest, so my experiment was simple implement some sort of layering in 8bit CLUT, should not be too hard.

So here is my main code, not so complicated.

#include <stdlib.h>
#include <stdio.h>

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/Picasso96API.h>
#include "chunky_plains.h"

int main()
{
    struct chunky_plains *cp;
    struct Screen *src = NULL;
    struct Window *win;
    struct RenderInfo ri;
    int err;
    void *tmp;
    PLANEPTR ptr;
    BPTR bmlock;
    int x,y;
    int n,anim;
    ULONG bpr;

    src = p96OpenScreenTags(
        P96SA_DisplayID, 0x50051000,
        P96SA_Title, (ULONG) "666",
        P96SA_Quiet, TRUE,
        P96SA_NoMemory, TRUE,
        P96SA_NoSprite, TRUE,
        P96SA_Exclusive, TRUE,
        TAG_END    );

    if ( src )
    {
        win = OpenWindowTags(NULL,
            WA_Left, 0, WA_Top, 0,
            WA_Width, 640, WA_Height, 480,
            WA_NoCareRefresh, TRUE,
            WA_Borderless, TRUE,
            WA_Activate, TRUE,
            WA_RMBTrap, TRUE,
            WA_ReportMouse, TRUE,
            WA_CustomScreen, (ULONG) src,
            TAG_END
        );

        if (src)
        {
            SetRGB32( &src -> ViewPort ,0,0xFFFFFFFF,0,0);

            for (y=0;y<255;y++)
            {
                SetRGB32( &src -> ViewPort ,1,y * 0x01010101, (255-y)* 0x01010101,y*0x01010101);
            }

            printf("Bitmap %x\n",src -> BitMap);
            printf("BytesPerRow %d\n", src -> BitMap.BytesPerRow);
            printf("Rows %d\n", src -> BitMap.Rows);

        }
 
        Delay(20);

        if (err = alloc_cunky_plains(win -> RPort -> BitMap, 4,4,0,0,0,0,0,0, 320,200,&cp))
        {
            printf("error code: %d\n",err);
        }
        else
        {

            for (y=0;y<255;y++)
            {
                for (x=0;x<255;x++)
                {
                    set_color(cp,0, (y^x) & 8 ? (x & 3) : (y & 3) , x ,y );
                }
            }
            Delay(100);
            for (anim = 0; anim < 5; anim++)
            for (n=0;n<32;n++)
            {
                for (y=0;y<255;y++)
                {
                    for (x=0;x<255;x++)
                    {
                        set_color(cp,1, (y^(x+n)) & 16 ? 2 : 0 , x ,y );
                    }
                }
                Delay(1);
            }
            Delay(100);

            for (anim = 0; anim < 100; anim++)
            {
                scroll(cp,0,50,50,100,100,0,1);
                scroll(cp,1,50,50,100,100,1,0);
                Delay(2);
            }
            Delay(100);

            free_chunky_plains(cp);
        }
      
        Delay(100);

        CloseWindow(win);
        p96CloseScreen(src);
    }
}


As it turns out its easy to do, I think Intel/AMD PC moved to 16bit/32bit so quickly they forgot about 8Bit/6bit graphics, there are lots of cool things you can do whit 8bit graphics like layering, fadein between layers, scroll texts that go top of some image, or having some kind of vector cube in background and some logo on top of it.

People love this tricks and there are people that do make demos whit this effects even today.

Does it make sens today? Retro is in, but it probably look a lot better in OpenGL, using the Z axes, the things you don't have so great control over in OpenGL is things you can do whit the color palette.

To test you need your own "chunky_plains.h" file, so here is the rest of the code.




struct chunky_plains {
    char bits[8];                    // bits on plain
    char index[8];                    // index bit for color
    char mask[8];                    // mask for color value
    char palette[3][8][256];            // hemm...
    int bytes_per_row;                // copy of bitmap bytes per row
    char *data;                    // ptr to the Bitmap memory
    char *f_buffer;                    // buffer so we can do filtering.
    char *n_buffer;                    // buffer so we can do filtering.
};

enum {
    cp_error_no_mem = 0,
    cp_error_too_many_bits
};

void free_chunky_plains(struct chunky_plains *p)
{
    if (p)
    {
        if (p -> f_buffer) FreeVec(p -> f_buffer);
        if (p -> n_buffer) FreeVec(p -> n_buffer);
        FreeVec(p);
    }
}

int alloc_cunky_plains(struct BitMap *bm, char n0,char n1,char n2,char n3,char n4,char n5, char n6,char n7, int w,int h,struct chunky_plains **new_cp)
{
    struct chunky_plains *p;
    int n;
    int cnt;
    int bpr;
    int error_code = 0;

    p = (struct chunky_plains *) AllocVec( sizeof(struct chunky_plains) , MEMF_ANY );

    if (p)
    {
        bpr = p96GetBitMapAttr(  bm, P96BMA_BYTESPERROW);   

        p -> data =  (char *) p96GetBitMapAttr( bm , P96BMA_MEMORY);
        p -> f_buffer = (char *)  AllocVec( bpr * h , MEMF_ANY | MEMF_CLEAR);
        p -> n_buffer = (char *)  AllocVec( bpr * h , MEMF_ANY | MEMF_CLEAR);
        p -> bytes_per_row = bpr;

        p -> bits[0]=n0;
        p -> bits[1]=n1;
        p -> bits[2]=n2;
        p -> bits[3]=n3;
        p -> bits[4]=n4;
        p -> bits[5]=n5;
        p -> bits[6]=n6;
        p -> bits[7]=n7;

        p -> index[0] = 0;

        cnt = 0;
        for (n=1;n<8;n++)
        {
            p -> index[n] = p -> index[n-1] + p -> bits[n-1];

            cnt += p -> bits[n];
        }

        for (n=0;n<8;n++)
        {
            p -> mask[n] = ((1 << p -> bits[n]) -1) << p -> index[n];

            printf("bits %02x mask %02x index %d\n",p -> bits[n] ,p->mask[n], p -> index[n]);
        }

        if (cnt > 8) error_code = cp_error_too_many_bits;
       
        if (!p -> data)    error_code = cp_error_no_mem;
        if (!p -> f_buffer) error_code = cp_error_no_mem;
        if (!p -> n_buffer) error_code = cp_error_no_mem;

    } else {
        error_code = cp_error_no_mem;
    }

    if (error_code)
    {
        free_chunky_plains(p);
        p = NULL;
    }

    *new_cp = p;

    return error_code;
}


void set_color(struct chunky_plains *cp, char number, char color, int x,int y)
{
    char *pixel = &cp -> data[ x + (cp -> bytes_per_row * y)];
    *pixel = (~cp -> mask[number]) &  *pixel | (color << cp -> index[number] );
}

int get_color(struct chunky_plains *cp, char number, char color, int x,int y)
{
    return (cp -> mask[number] &  cp -> data[ x + (cp -> bytes_per_row * y)]) >> cp -> index[number] ;
}

void scroll(struct chunky_plains *cp, int number, int x1,int y1,int x2,int y2, int offset_x, int offset_y )
{
    int fmask = ~ cp -> mask[number];
    int mask = cp -> mask[number];
    int bytes_per_row = cp -> bytes_per_row;
    register int x = 0;
    register int y;
    register int line_offset;
    register int offset;
    register int doffset;

    // we filter out the other plains into the buffer, so we can put it back in.

    for (y =y1;y<=y2;y++)
    {
        line_offset = y *  bytes_per_row;
        for (x=x1;x<=x2;x++)
        {
            offset = line_offset +x;
            cp -> f_buffer[offset] = cp -> data[ offset ] & fmask;
            cp ->n_buffer[offset] = cp -> data[ offset ] & mask;
        }
    }

    for (y =y1;y<=y2;y++)
    {
        line_offset = y * bytes_per_row;
        for (x=x1;x<=x2;x++)
        {
            offset = line_offset +x;

            doffset = (y + offset_y) * bytes_per_row + (x + offset_x);

            cp -> data[ offset ] = cp -> f_buffer[offset] | cp ->n_buffer[ doffset ] ;
        }
    }
}

Friday, April 5, 2013

The release of excalibur is eminent

The release of Excalibur is eminent


There are only a few features, that I can think of that want, but they going to break some thing maybe, it's time think about uploading a new version, there is 30 changes in this update, so this big update compared to few of the older updates, I lost a lot changes, and head to do most of this twice, nothing makes me more annoyed, well its done.

V1.2.5


* Alpha blended Logo
* Menu divider texture is tiled and scaled up or down to fit.
* Added border to toolbar
* save and load of font settings
* save and load of RGB color options for clock and screens
* some settings has changed name
* toolbar icons, screens and clock is now relative to border
* smarter positioning of toolbar icons
* prefs: added fonts to save routine and gui.
* prefs: added border textures for toolbar.
* prefs: RGB color option for clock and screens.
* Fixed black border texture in GIMP.
* Bjornar made a new logo for me.
* Svenn Ove Hansen, created some experimental textures.
* Fixed bug: droping icons resulted in menu being saved to env, menu divider lost bug.
* Fixed best_height calculation in menu, assumed toolbar to be 60 pixels, that was wrong.
* logo is now sacled down if menu is too small.
* ASync memory bar redraw bug when drooping icons fixed.
* Clip background from window instead of background bitmap bug, fixed.
* Background texture in menu is now aligned whit border top texture, to support DjNick theme.
* DjNick designed a theme
* Fixed DjNick theme, created a icon from textures, and left menu texture, cut of some transparent empty space of right and bottom side of theme,
cropped down menu border textures so it worked on toolbar.
* Fixed up black theme, and bloody theme.
* Fixed check_ext() function checked .info instead of .ext (no major problem unless I like to use it for some thing else)
* disk.info is now ignored.
* font shadow option changed to menu and toolbar instead of global
* max icon size option changed to menu and toolbar instead of global
* prefs program: default setings are now set, before config is loaded.
* GFXMEM can't be 64bit int, due to only 32bit api for memory in OS4, changed to unsigned int32, max 4Gbytes.
* Membar drawen too often, due to refresh bug, added draw_gfx option to membar::Memory() function.


DJNick theme, what happened, well some of changes you see in Mokup are implemented, for example the different size of fonts in menu and toolbar, different icon sizes in menu and toolbar, this things might have not been there if was not for the mockup, what is not implemented is logo on border, and the shadow effect.

What you might not know, is that Excalibur allows for more then one menu, so you can have your music menu, and your games menu, and what ever, just drop your volume or folder on the app/toolbar.


So lets hope I have some time to upload it tomorrow, so you all can enjoy it.

This is Kjetil signing out.