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);
}
}
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 ] ;
}
}
}