Prev: New HP 50G Owner
Next: EMU48
From: peti314 on 2 Sep 2006 17:56 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 2 Sep 2006 23:27 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 3 Sep 2006 00:40 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 3 Sep 2006 11:01
> 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 |