Spenceboy98 wrote:
KermMartian wrote:
It would be a good idea to avoid memory corruption with big fills, since you have much less space for the stack than you would on a desktop.


I could put a border around the screen so that it doesn't go on forever and ever.
Even for a 382x214-pixel fill, as Tari calculated out in his post, the stack growth would overwrite the entirety of RAM, almost.
It would far exceed the amount of memory available to us (which is about 512 KB). I suppose you could barely fit fullscreen by rendering with doubled pixels, but that's not a general-purpose solution fit for inclusion in a collection of useful routines.
I was thinking. For the floodfill routine I found, would it work better if I used Kerms plot routine instead of SetPoint?
Spenceboy98 wrote:
I was thinking. For the floodfill routine I found, would it work better if I used Kerms plot routine instead of SetPoint?


In terms of optimization, simply writing color data directly to addresses of VRAM would actually be the best method overall.
I didn't make these, but I can't seem to find them anywhere in this thread, so here goes:


Code:
unsigned int random(void);
unsigned int srandom(int seed);

static unsigned int lastrandom=0x12345678;
unsigned int random(void) {
   return srandom(0);
}

unsigned int srandom(int seed){
    if (seed) lastrandom=seed;
    lastrandom = ( 0x41C64E6D*lastrandom ) + 0x3039;
    return ( lastrandom >> 16 );
}
balping wrote:
Here's my full featured menu-system routine...



Am I supposed to be getting these warnings:

Code:
main.c:345:10: warning: passing argument 6 of 'CopySpriteMasked2bitR' discards '
const' qualifier from pointer target type [enabled by default]
main.c:284:6: note: expected 'short unsigned int *' but argument is of type 'con
st color_t *'
main.c:346:10: warning: passing argument 6 of 'CopySpriteMasked2bitR' discards '
const' qualifier from pointer target type [enabled by default]
main.c:284:6: note: expected 'short unsigned int *' but argument is of type 'con
st color_t *'
main.c:379:10: warning: pointer targets in passing argument 3 of 'PrintMini' dif
fer in signedness [-Wpointer-sign]
../..//include/display_syscalls.h:73:6: note: expected 'unsigned char *' but arg
ument is of type 'char *'
main.c:384:7: warning: pointer targets in passing argument 3 of 'PrintMini' diff
er in signedness [-Wpointer-sign]
../..//include/display_syscalls.h:73:6: note: expected 'unsigned char *' but arg
ument is of type 'char *'
main.c:388:7: warning: pointer targets in passing argument 3 of 'PrintMini' diff
er in signedness [-Wpointer-sign]
../..//include/display_syscalls.h:73:6: note: expected 'unsigned char *' but arg
ument is of type 'char *'
main.c:399:13: warning: implicit declaration of function 'sys_memset' [-Wimplici
t-function-declaration]
main.c:402:13: warning: pointer targets in passing argument 3 of 'PrintCXY' diff
er in signedness [-Wpointer-sign]
../..//include/display_syscalls.h:68:6: note: expected 'unsigned char *' but arg
ument is of type 'char *'
main.c:407:13: warning: pointer targets in passing argument 3 of 'PrintCXY' diff
er in signedness [-Wpointer-sign]
../..//include/display_syscalls.h:68:6: note: expected 'unsigned char *' but arg
ument is of type 'char *'
main.c:410:13: warning: pointer targets in passing argument 3 of 'PrintCXY' diff
er in signedness [-Wpointer-sign]
../..//include/display_syscalls.h:68:6: note: expected 'unsigned char *' but arg
ument is of type 'char *'
*BUMP*
Can anyone help with this?^^
It keeps giving me a segfault.
Not sure if already done, but these routines re-implement the pow function without using math.h (since including it didn't work for me).
Edit: fixed

Code:

double exp(double x) {
   int i=2;
   long long fact=2;
   double resC=1, resP=0;
   while (resC!=resP) {
      resP=resC;
      resC+=1./(double)fact;
      fact*=++i;
   }
   return resC;
}

const double EULER=exp(1);

double powInt(double x, int n) {
   if (n<0) return 1./powInt(x,-n);
   double res=1;
   int i=0;
   for (i=0;i<n;i++) res*=x;
   return res;
}

double lnFor0To2(double x) {
   double y=x-1;
   int i=2;
   double resC=y, resP=0;
   while (resC!=resP) {
      resP=resC;
      resC+=(i%2?1:-1)*powInt(x,i)/i;
   }
   return resC;
}

double ln(double x) {
   if (0<x && x<=2) return lnFor0To2(x);
   else return 1+lnFor0To2(x/EULER);
}

double pow(double x, double y) {
   return exp(y*ln(x));
}
Is there a routine for finding individual r, g, and b values of a pixel?
You can use Bdisp_GetPoint_VRAM to get the color of it, and then some bitshifting and masking to get the actual values (it's 565, so the bits are arranged rrrrrggggggbbbbbb).
..as discussed on the general page about the display.
I made a little polygon routine. I tested it and it works well:

Code:
void drawPoly(int xy[], int points, int color){
    for(int i = 0; i < (points*2); i+=2){
        if(i < (points*2)-4){
            drawLine(xy[i], xy[i+1], xy[i+2], xy[i+3], color);
        } else {
            drawLine(xy[i], xy[i+1], xy[0], xy[1], color);
        }
    }
}


xy[] is the array of x and y's(like this: {x,y,x1,y1,etc.}).
points is the number of points in the polygon.
color is the color(duh).
Spenceboy98 wrote:
I made a little polygon routine. I tested it and it works well:

Code:
void drawPoly(int xy[], int points, int color){
    for(int i = 0; i < (points*2); i+=2){
        if(i < (points*2)-4){
            drawLine(xy[i], xy[i+1], xy[i+2], xy[i+3], color);
        } else {
            drawLine(xy[i], xy[i+1], xy[0], xy[1], color);
        }
    }
}


xy[] is the array of x and y's(like this: {x,y,x1,y1,etc.}).
points is the number of points in the polygon.
color is the color(duh).
That's more like a polyline routine, I'd say. Smile You could make it more specifically output regular polygons to the display by specifying a center, radius, and starting angle, and use sine and cosine to compute all of the polygon's points on the fly.
I modified the CopySprite and CoptSpriteMasked to support clipping:

Code:
void CopySprite(const void* datar, int x, int y, int width, int height) {
   color_t*data = (color_t*) datar;
   color_t* VRAM = (color_t*)0xA8000000;
   VRAM += LCD_WIDTH_PX*y + x;
   for(int j=y; j<y+height; j++) {
      for(int i=x; i<x+width; i++) {
        if(i>0 && i<384 && j>0 && j<216){
         *(VRAM++) = *(data++);
        } else { VRAM++; data++; }
     }
     VRAM += LCD_WIDTH_PX-width;
   }
}

void CopySpriteMasked(const void*datar, int x, int y, int width, int height, int maskcolor) {
   color_t*data = (color_t*) datar;
   color_t* VRAM = (color_t*)0xA8000000;
   VRAM += LCD_WIDTH_PX*y + x;
   for(int j=y; j<y+height; j++) {
      for(int i=x; i<x+width;  i++) {
         if (*(data) != maskcolor && i>0 && i<384 && j>0 && j<216) {
            *(VRAM++) = *(data++);
         } else { VRAM++; data++; }
      }
      VRAM += LCD_WIDTH_PX-width;
   }
}


It works with my ZombieGun game. Very Happy
Just kind of "thinking out loud", but those branches probably have a non-trivial effect on performance. I suspect you could precompute the iteration bounds for an appreciable speedup.
I found a ellipse routine here, and I ported it:


Code:

#define ROUND(a) ((int) (a + 0.5))

void ellipsePlotPoints(int xCenter, int yCenter, int x, int y, int color){
    plot(xCenter + x, yCenter + y, color);
    plot(xCenter - x, yCenter + y, color);
    plot(xCenter + x, yCenter - y, color);
    plot(xCenter - x, yCenter - y, color);
}
void drawEllipse(int xCenter, int yCenter, int Rx, int Ry, int color){
    int Rx2 = Rx*Rx;
    int Ry2 = Ry*Ry;
    int twoRx2 = 2 * Rx2;
    int twoRy2 = 2 * Ry2;
    int p;
    int x = 0;
    int y = Ry;
    int px = 0;
    int py = twoRx2 * y;
    ellipsePlotPoints(xCenter, yCenter, x, y, color);
    /* For Region 1 */
    p = ROUND(Ry2 - (Rx2*Ry) + (0.25) * Rx2);
    while(px < py){
        x++;
        px += twoRy2;
        if(p < 0){
            p += Ry2 + px;
        }else{
            y--;
            py -= twoRx2;
            p += Ry2 + px - py;
        }
        ellipsePlotPoints(xCenter, yCenter, x, y, color);
    }
    /* For Region 2*/
    p = ROUND(Ry2 * (x + 0.5)*(x + 0.5) + Rx2 * (y - 1)*(y - 1) - Rx2 * Ry2);
    while(y > 0){
        y--;
        py -= twoRx2;
        if(p > 0){
            p += Rx2 - py;
        }else{
            x++;
            px += twoRy2;
            p += Rx2 - py + px;
        }
        ellipsePlotPoints(xCenter, yCenter, x, y, color);
    }
}


Maybe Kerm could use it for LuaZM?

The problem with it is that when the Ry is <=0, it draws 2 dots instead of an ellipse.

Enjoy!
Ashbad wrote:
CopySpriteMaskedAlpha: takes the same params as CopySpriteMasked, but with an alpha transparency channel between 0-31.


Code:
void CopySpriteMaskedAlpha(const void*datar, int x, int y, int width, int height, int maskcolor, int alpha) {
   color_t*data = (color_t*) datar;
   color_t* VRAM = (color_t*)0xA8000000;
   VRAM += LCD_WIDTH_PX*y + x;
   alpha %= 32;
   for(int j=y; j<y+height; j++) {
      for(int i=x; i<x+width;  i++) {
         if (*(data) != maskcolor) {
         *(VRAM) = (color_t)((((int)(*data & 0xf81f) * alpha + (int)(*VRAM & 0xf81f) * (32-alpha) + 0x8010) >> 5) & 0xf81f) |
                (color_t)((((int)(*data & 0x07e0) * alpha + (int)(*VRAM & 0x07e0) * (32-alpha) + 0x0400) >> 6) & 0x07e0);
           VRAM++; data++;
         } else { VRAM++; data++; }
      }
      VRAM += LCD_WIDTH_PX-width;
   }
}


I'm trying to use this routine for my Cookie Clicker game for golden cookies, but it seems to tint the sprite purple (color #ff00ff). Can this be fixed?
I love how all those CopySprite* functions can be replaced entirely with a single syscall: Bdisp_WriteGraphVRAM
The struct it takes as parameter is a bit complex, sure, but at least you reduce the amount of code and binary size on your add-in, especially if you have many CopySprite* functions, each for its purpose. A few (not scientific) tests I did when developing the new version of my image viewer also show that Bdisp_WriteGraphVRAM is a tiny bit faster than CopySprite (I found this amusing, because I thought the compiler would optimize more efficiently if the code wasn't a syscall, because it could inline and the like).
Here is the Alpha Sprite routine I'm using since Ashbad's doesn't work properly for me. I pretty much just put things together that I found on google:


Code:

int RGBColor(int r, int g, int b)
{
  return ((r / 8) << 11) | ((g / 4) << 5) | (b / 8);
}

int GetR(color_t color){
   return ((color & 0xF800) >> 8);
}

int GetG(color_t color){
   return ((color & 0x07E0) >> 3);
}

int GetB(color_t color){
   return ((color & 0x001F) << 3);
}

int alpha_transparency(float alpha, float value1, float value2)
{
    return alpha * value1 + (1 - alpha) * value2;
}

void CopySpriteMaskedAlpha(const void*datar, int x, int y, int width, int height, int maskcolor, float alpha) {
   color_t*data = (color_t*) datar;
   color_t* VRAM = (color_t*)0xA8000000;
   int red = 0, green = 0, blue = 0, vr = 0, vg = 0, vb = 0;
   VRAM += LCD_WIDTH_PX*y + x;
   for(int j=y; j<y+height; j++) {
      for(int i=x; i<x+width;  i++) {
       red = GetR(*data);
       green = GetG(*data);
       blue = GetB(*data);
       vr = GetR(*VRAM);
       vg = GetG(*VRAM);
       vb = GetB(*VRAM);
         if (*(data) != maskcolor) {
         *(VRAM) = RGBColor(alpha_transparency(alpha, red, vr), alpha_transparency(alpha, green, vg), alpha_transparency(alpha, blue, vb));
           VRAM++; data++;
         } else { VRAM++; data++; }
      }
      VRAM += LCD_WIDTH_PX-width;
   } 
}


(it's probably very unoptimized, and I apologize for that)
Spenceboy98 wrote:
I pretty much just put things together that I found on google:

At-least I know you did not write that abomination.
First of all if when using a function in only one file declare it as static.
Second of all don't use floats when you need high speed. If you are just doing a few simple calculations a frame you may get away with using them but this is not an appropriate time for floats. The casio prizm's cpu has no FPU. This code is much faster.

Code:

/*Note it is up to the caller to ensure that alpha is in range of 1-31
 * For a value of 32 or greater just don't draw the image
 * For a value of 0 use a plain mask function that does not take into account alpha
 * Also make sure width is a multiple of two*/
void CopySpriteMaskedAlpha(unsigned *data,unsigned x,unsigned y,unsigned width,unsigned height,unsigned maskcolor,unsigned alpha){
   unsigned short*v=(unsigned short*)0xA8000000;
   unsigned* VRAM,w,alphai;
   width/=2;
   v += 384*y + x;
   VRAM=v;
   alphai=32-alpha;
   maskcolor|=maskcolor<<16;/*Note I have decided to do a minor tradeoff for speed. Make sure your alpha pixels are multiple of two*/
   while(height--){
      w=width;
      while(w--){
         unsigned color1=*data++;
         if(color1 != maskcolor){
            /*Note this is based on the source code of Fblend's function fblend_rect_trans_16*/
            unsigned rbg_source, grb_source,temp1;
            /* Split up components to allow us to do operations on all of them at the same time */
            rbg_source = *VRAM & 0xF81F07E0,
            grb_source = *VRAM & 0x07E0F81F;

            /* Multiply the source by the factor */
            rbg_source = ((rbg_source >> 5) * alpha) & 0xF81F07E0;
            grb_source = ((grb_source * alpha) >> 5) & 0x07E0F81F;

            /* Split up RGB -> R-B and G */
            temp1 = color1 & 0x7E0F81F;
            color1 &= 0xF81F07E0;

            /* Multiply the source by the factor */
            color1 = ((((color1 >> 5) * alphai) & 0xF81F07E0) + rbg_source) & 0xF81F07E0;
            temp1  = ((((temp1 * alphai) >> 5)  & 0x07E0F81F) + grb_source) & 0x07E0F81F;

            color1 |= temp1;
            *VRAM++=color1;
         }else
            ++VRAM;
      }
      VRAM += (384/2)-width;
   }
}

This code will actully handle a range of 0-32. Even though this function is fast it is faster to not draw the image (value of 32). Or just draw the image using mask function that does not worry about alpha (value of 0).
It admit to getting part of this code off from Fblend an open source project as you can see in the comment I put in the code. One good thing about the code is that it does two pixels at a time. However I decided to remove the checks for non multiples of two to further increase speed given the fact that you can just fix your image if needed. Also make sure that the alpha pixels are multiples of two. Also I found an interesting article talking about a few rgb565 tricks you may want to check out http://www.cprogramdevelop.com/4562354/
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
» Goto page Previous  1, 2, 3 ... , 10, 11, 12  Next
» View previous topic :: View next topic  
Page 11 of 12
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement