Prev: New HP 50G Owner
Next: EMU48
From: peti314 on
In article <1157220819.092069.282580(a)e3g2000cwe.googlegroups.com>,
"am" <andreamolteni(a)yahoo.it> writes:
> Claudio Lapilli wrote:
>> We have HPG, a full featured graphics library that can work with
>> monochrome, 4-grays or 16-grays bitmaps. You can write a much better
>> (faster) program if you use our library instead of working with grobs
>> directly.
>> [...]
>> Good luck w/your program, you should be able to achieve much more than
>> just 8 fps in slow mode, the ARM processor can do better than that!
>
> Well, I must confess that my first attempt used hpg_t* images, but I
> couldn't get more than 3 fps (in slow mode). Switching to a simple
> array for intermediate images and using HPG only for drawing to the
> screen, the speed becomes 8-10 fps (in slow mode). I guess this is
> because Life has to use a function call to set each and every pixel,
> and for each of them HPG does more than a function call and has to
> calculate offset (hpg_t images may have generic size, so I guess this
> is relatively slow). Am I missing something? Any tip?
> Thanks
> ---am
>

What I first tried to do was to look at the HPG sources and use the actual
getpixel and putpixel function that eventually gets called by the general
hpg_[gs]et_pixel function. I figured I could spare at least two function calls
per lookup operation, but it seems that I messed up something.
(For a description of the problem, see
http://groups.google.co.hu/group/comp.sys.hp48/browse_thread/
thread/2a429b06eb4cc02/efab50e75f7356e7?lnk=gst&q=life&rnum=11#efab50e75f7356e7
(long link!))

But trivial optimizations like this won't get you far.
For speeds well over 100 fps you need an advanced algorithm to calculate each
iteration of the Life universe, one that keeps track of the living cells only.
If you use a naive approach that simply scans the entire universe linearly
(with a nested loop like
for (x = 0; x > XMAX; x++)
for (y = 0; y > YMAX; y++)
)
you end up wasting a lot of time on calculating cells which remain dead all the
time.
This "calculate the living cells only" method has an additional advantage:
you can have an arbitrarly large universe, in which you can map the actual
viewing window, and you can allow your pattern to grow as long as available
memory permits. (You have to implement scrolling in this case, though.)

Good luck: Peter Juhasz

From: Jean-Yves Avenard on
am wrote:
> You're right, initialization might be needed. But it would be more
> consistent writing it in C.
It will take far less space if you used RPL here. All memory allocations
and copy of memory on the 49G+/50G is in pure C. So you won't have
much speed gain there.
But allocating memory isn't a trivial task ... White reinvent the wheel ?

> Does anyone know how to do it? Evidently just writing a grob header at
> GDISP's address is not the right way, I guess some allocation in Saturn
> memory is needed.

You will have to shift a lot of different memory area, update all user
pointers, etc

> I have two other questions: does the address at GDISP ever change, and
> why? (Do I have to be worried about it?) And, if the grob prologue is
> #02B1Eh, why does my PICT start with #F2B1Eh ?

Hum, PICT is just a GROB object, will use the same prologue as any other
graphic.

GDISP may move is you're resizing some objects, but is less likely to
move as opposed to a user object in temporary memory.

JY
From: Claudio Lapilli on
Hello,

am wrote:
> Claudio Lapilli wrote:
> > We have HPG, a full featured graphics library that can work with
> > monochrome, 4-grays or 16-grays bitmaps. You can write a much better
> > (faster) program if you use our library instead of working with grobs
> > directly.
> > [...]
> > Good luck w/your program, you should be able to achieve much more than
> > just 8 fps in slow mode, the ARM processor can do better than that!
>
> Well, I must confess that my first attempt used hpg_t* images, but I
> couldn't get more than 3 fps (in slow mode). Switching to a simple
> array for intermediate images and using HPG only for drawing to the
> screen, the speed becomes 8-10 fps (in slow mode). I guess this is
> because Life has to use a function call to set each and every pixel,
> and for each of them HPG does more than a function call and has to
> calculate offset (hpg_t images may have generic size, so I guess this
> is relatively slow). Am I missing something? Any tip?

Just out of curiosity, I coded a minimalist Conway's life using HPG.
Yes, HPG has a small overhead because it's a generic lib but that
shouldn't affect you much.
My first try (it can be further optimized by writing to the bitmap
directly, of course) gave me about 20 fps in slow mode and 150 fps in
fast mode.

It's also works as a nice hpg tutorial, I'll probably include it as a
permanent hpgcc example.

Claudio

Here's the commented code:

#include <hpgcc49.h>
#include <hpgraphics.h>

#define HEIGHT 80
#define WIDTH 128


char count[HEIGHT*WIDTH];
char state[HEIGHT*WIDTH];
char newcount[HEIGHT*WIDTH];


// UPDATE LIFE COUNT FOR NEIGHBORS

void add_neighbors(int j,int i,int value)
{
int offset0;
int leftadd,rightadd,topadd,botadd;

if(i==0) leftadd=WIDTH-1; else leftadd=-1;
if(i==WIDTH-1) rightadd=-WIDTH+1; else rightadd=1;
if(j==0) topadd=(HEIGHT-1)*WIDTH; else topadd=-WIDTH;
if(j==HEIGHT-1) botadd=-(HEIGHT-1)*WIDTH; else botadd=WIDTH;


offset0=j*WIDTH+i;

// TOP-LEFT
newcount[offset0+topadd+leftadd]+=value;
// TOP
newcount[offset0+topadd]+=value;
// TOP-RIGHT
newcount[offset0+topadd+rightadd]+=value;
// LEFT
newcount[offset0+leftadd]+=value;
// RIGHT
newcount[offset0+rightadd]+=value;
// BOT-LEFT
newcount[offset0+botadd+leftadd]+=value;
// BOT
newcount[offset0+botadd]+=value;
// BOT-RIGHT
newcount[offset0+botadd+rightadd]+=value;


}


// DETERMINE NEW STATE AFTER ONE TICK

void play_tick()
{
int i,j;
int offset;
// COPY COUNT TO TEMPORARY STORAGE
memmove(newcount,count,sizeof(char)*HEIGHT*WIDTH);

offset=0;

for(j=0;j<HEIGHT;++j)
{
for(i=0;i<WIDTH;++i)
{
if(state[offset]) {
// IF ALIVE, CHECK IF IT SHOULD DIE
if( (count[offset]|1)!=3 ) {
// KILL IT
state[offset]=0;
hpg_set_color(hpg_stdscreen,HPG_COLOR_WHITE);
hpg_draw_pixel(i,j);
// UPDATE COUNT FOR ALL NEIGHBORS
add_neighbors(j,i,-1);

}

}
else {
// IF DEAD, CHECK IF IT SHOULD COME TO LIFE
if(count[offset]==3) {
state[offset]=1;
hpg_set_color(hpg_stdscreen,HPG_COLOR_BLACK);
hpg_draw_pixel(i,j);
// UPDATE NEIGHBORS COUNT
add_neighbors(j,i,1);
}
}
++offset;
}
}

// MOVE BACK TO PERMANENT STORAGE
memmove(count,newcount,sizeof(char)*WIDTH*HEIGHT);

}

// SET INITIAL STATE
void calc_count()
{
int i,j;
int offset;
// COPY COUNT TO TEMPORARY STORAGE
memset((void *)newcount,0,sizeof(char)*HEIGHT*WIDTH);

offset=0;

for(j=0;j<HEIGHT;++j)
{
for(i=0;i<WIDTH;++i)
{
if(state[offset]) { add_neighbors(j,i,1);
hpg_set_color(hpg_stdscreen,HPG_COLOR_BLACK); hpg_draw_pixel(i,j); }
else { hpg_set_color(hpg_stdscreen,HPG_COLOR_WHITE);
hpg_draw_pixel(i,j); }
++offset;
}
}

// MOVE BACK TO PERMANENT STORAGE
memmove(count,newcount,sizeof(char)*WIDTH*HEIGHT);

}



int main()
{

hpg_clear();

// SET TO RANDOM STATE
hpg_draw_text("Hello Conway",20,30);

// GET STATE MATRIX

int i,j,offset;
offset=0;
for(j=0;j<HEIGHT;++j)
{
for(i=0;i<WIDTH;++i)
{
if(hpg_get_pixel(hpg_stdscreen,i,j)) state[offset]=1;
else state[offset]=0;
++offset;
}
}


// INITIATE CONWAY'S ITERATOR
calc_count();

while(!keyb_isON())
{
play_tick();
}
return 0;
}

From: am on
> It's also works as a nice hpg tutorial, I'll probably include it as a
> permanent hpgcc example.

Very nice job indeed! Your approach is definitely better than the one I
was using.
Still it seems I was right thinking that using hpg images would be too
slow! Ok, ok, now I'll correct my program and add some useful feature
as suggested by Peter. I've already managed to get stack operations on
grobs to work, so now I'm quite optimist. Naturally when done the code
will be freely available.

Thanks again for your great help
---am

First  |  Prev  | 
Pages: 1 2 3 4
Prev: New HP 50G Owner
Next: EMU48