CEMETECH
Leading The Way To The Future
Login [Register]
Username:
Password:
Autologin:

Don't have an account? Register now to chat, post, use our tools, and much more.
Latest Headlines
Online Users
There are 95 users online: 13 members, 56 guests and 26 bots.
Members: 16aroth6, blue_bear_94, Deep Thought, gbl08ma, HOMER-16, JosJuice, Piguy-3.14, Spyro543, willwac, zeldaking.
Bots: VoilaBot (2), Spinn3r (1), Magpie Crawler (3), Googlebot (19), MSN/Bing (1).
RSS & Social Media
SAX
You must log in to view the SAX chat widget
Author Message
m1ac4


Advanced Newbie


Joined: 16 Sep 2010
Posts: 43

Posted: 01 Jun 2012 04:12:32 pm    Post subject:

Smashmaster wrote:
Good afternoon everyone. I have a question:

...

How to draw 8-bit sprites with an alpha channel?


This should work:

Code:
void CopySpriteNbitMasked(const unsigned char* data, int x, int y, int width, int height, const color_t* palette, color_t maskColor, unsigned int bitwidth)
{
   color_t* VRAM = (color_t*)VRAM_LOC;
   VRAM += (LCD_WIDTH_PX*y + x);
   int offset = 0;
   unsigned char buf;
   for(int j=y; j<y+height; j++)
   {
      int availbits = 0;
      for(int i=x; i<x+width;  i++)
      {
         if (!availbits)
         {
            buf = data[offset++];
            availbits = 8;
         }
         color_t this = ((color_t)buf>>(8-bitwidth));
         color_t color = palette[this];
         if(color != maskColor)
         {
            *VRAM = color;
         }
         VRAM++;
         buf<<=bitwidth;
         availbits-=bitwidth;
      }
      VRAM += (LCD_WIDTH_PX-width);
   }
}
It's just Kerm's routine with some small modifications. I tested it with 8-bit sprites but the routine should still work with 4 and 2-bit sprites as well. Just make sure that your palette has the desired mask color in it.
_________________
Switched RPG (SwtchRPG ported to C) has a demo now!
Back to top
Ashbad


... I think redheaded girls are kind of cool


Joined: 01 Dec 2010
Posts: 2417
Location: Stomp Stomp Stomp, The Idiot Convention

Posted: 01 Jun 2012 04:33:27 pm    Post subject:

Well, the terminology of "Alpha Channel" makes me think he wants different levels of transparency that can be applied to the sprite as it in turn is applied to the destination surface buffer. In which case, you're also going to have to meld what you have with a quick routine I wrote a while ago for dealing with transparency with a given alpha value: http://cemetech.net/forum/viewtopic.php?t=6114&postdays=0&postorder=asc&start=124
_________________
-Ashbad
Back to top
seana11


Super-Expert


Joined: 23 May 2011
Posts: 833
Location: Well, the sign says "You are here"...

Posted: 01 Jun 2012 04:36:20 pm    Post subject:

Suggestion: Since digging through an 8-page-long thread for a routine is not my idea of fun (nor anyone else's, I presume), why doesn't someone collect the procedures and stick them near the beginning of the thread, thus forming a good reference.
_________________

Code:
-----BEGIN GEEK CODE BLOCK-----
GCS d- s+: a---@ C+++ UL++ P L+++ E- W++ N o? K? w--- O? M--
V- PS++(--) PE- Y+ PGP t 5? X(+) R tv-- b++(+++) DI+(++)
D(+) G e-(*)>++@ h! r!>+++ y?
------END GEEK CODE BLOCK------
decoded
Back to top
Ashbad


... I think redheaded girls are kind of cool


Joined: 01 Dec 2010
Posts: 2417
Location: Stomp Stomp Stomp, The Idiot Convention

Posted: 01 Jun 2012 04:37:12 pm    Post subject:

seana11 wrote:
Suggestion: Since digging through an 8-page-long thread for a routine is not my idea of fun (nor anyone else's, I presume), why doesn't someone collect the procedures and stick them near the beginning of the thread, thus forming a good reference.


We're actually in the effort of doing something even better: putting them on an organized wiki Smile Still a decent amount of work needs to be done to get these all on there, though.
_________________
-Ashbad
Back to top
seana11


Super-Expert


Joined: 23 May 2011
Posts: 833
Location: Well, the sign says "You are here"...

Posted: 01 Jun 2012 04:39:11 pm    Post subject:

Ashbad wrote:
seana11 wrote:
Suggestion: Since digging through an 8-page-long thread for a routine is not my idea of fun (nor anyone else's, I presume), why doesn't someone collect the procedures and stick them near the beginning of the thread, thus forming a good reference.


We're actually in the effort of doing something even better: putting them on an organized wiki :) Still a decent amount of work needs to be done to get these all on there, though.


But the thread is named "Useful Prizm Routines," so it should have routines accessible in a non-esoteric way.
_________________

Code:
-----BEGIN GEEK CODE BLOCK-----
GCS d- s+: a---@ C+++ UL++ P L+++ E- W++ N o? K? w--- O? M--
V- PS++(--) PE- Y+ PGP t 5? X(+) R tv-- b++(+++) DI+(++)
D(+) G e-(*)>++@ h! r!>+++ y?
------END GEEK CODE BLOCK------
decoded
Back to top
Ashbad


... I think redheaded girls are kind of cool


Joined: 01 Dec 2010
Posts: 2417
Location: Stomp Stomp Stomp, The Idiot Convention

Posted: 01 Jun 2012 05:16:47 pm    Post subject:

seana11 wrote:
Ashbad wrote:
seana11 wrote:
Suggestion: Since digging through an 8-page-long thread for a routine is not my idea of fun (nor anyone else's, I presume), why doesn't someone collect the procedures and stick them near the beginning of the thread, thus forming a good reference.


We're actually in the effort of doing something even better: putting them on an organized wiki Smile Still a decent amount of work needs to be done to get these all on there, though.


But the thread is named "Useful Prizm Routines," so it should have routines accessible in a non-esoteric way.


Then if you have time, feel free to contribute some links to all of the routines with names, and someone can add it to the first post Wink I'm not one who cares too much about an in-thread directory of routines, so I'm not going to contribute to that effort at all.
_________________
-Ashbad
Back to top
Smashmaster


Newbie


Joined: 16 Apr 2012
Posts: 3

Posted: 01 Jun 2012 06:59:19 pm    Post subject:

Hello.

Thank you very much for your routine, it works great Smile !
Back to top
KermMartian


Site Admin


Joined: 14 Mar 2005
Posts: 55732
Location: Earth, Sol, Milky Way

Posted: 01 Jun 2012 07:07:27 pm    Post subject:

Smashmaster wrote:
Hello.

Thank you very much for your routine, it works great Smile !
Great, glad to hear. Smile But yes, Seana, we're organizing them all onto WikiPrizm.
_________________


Back to top
KermMartian


Site Admin


Joined: 14 Mar 2005
Posts: 55732
Location: Earth, Sol, Milky Way

Posted: 17 Jun 2012 10:32:57 pm    Post subject:

Apparently I never posted my sin/cos/tan implementations.


Code:
extern  float  __sinf(float);
extern  float  __tanf(float);
#define __cosf(x) __sinf((PIOVERTWO)+(x))

#define PIOVERTWO 1.570796327f
#define PI 3.141592654f
#define PISQUARED 9.869604401f
#define EXTRA_PRECISION

float __sinf(float x)
{
   while (x > PI) x-=(2.f*PI);
   while (x < -PI) x+=(2.f*PI);
    const float B = 4/PI;
    const float C = -4/(PISQUARED);

    float y = B * x + C * x * fabsf(x);

    #ifdef EXTRA_PRECISION
    //  const float Q = 0.7775;
        const float P = 0.224008178776;

        y = P * (y * fabsf(y) - y) + y;   // Q * y + P * y * abs(y)
    #endif
   
   return y;
}

float __tanf(float x) {
   float y = __sinf(x);
   return y/((PIOVERTWO)-y);
}

_________________


Back to top
Ashbad


... I think redheaded girls are kind of cool


Joined: 01 Dec 2010
Posts: 2417
Location: Stomp Stomp Stomp, The Idiot Convention

Posted: 26 Jun 2012 09:17:31 am    Post subject:

Been studying more of the mathematical sides of color theory lately, so I can understand how HSL/HSV, RGB, L*ab, etc. all relate between each other. I've found that HSL is a lot easier to use than RGB for quickly coming up for numbers that relate to a color you're thinking of, so in case anyone wants to use HSL on-prizm, here's something I just wrote up that takes H/S/L values and returns a standard color_t in R/G/B. Comments make it pretty self-explanitory.


Code:
float fabs(float f) { return f>=0?f:-f; }
int abs(int i) { return i>=0?i:-i; }

/*
h = hue degree, range [0,360)
s = saturation, range [0,1]
l = luminosity, range [0,1]
*/

color_t HSL_to_RGB(int h, float s, float l) {
   float r = 0.0f; float g = 0.0f; float b = 0.0f;
   float c = (1-fabs(2*l-1))*s;
   float tc = c*(1-abs(h%2-1));
   switch(h/60) {
      case 0: r = c; g = tc; break;
      case 1: g = c; r = tc; break;
      case 2: g = c; b = tc; break;
      case 3: b = c; g = tc; break;
      case 4: b = c; r = tc; break;
      case 5: r = c; b = tc; break;
      default: break;
   }
   float m = l-c/2;
   r += m; g += m; b += m;
   return (color_t)(((int)(r*32)<<11)|((int)(g*64)<<5)|((int)(b*32)));
}

_________________
-Ashbad
Back to top
flyingfisch


Super-Expert


Joined: 02 Feb 2012
Posts: 893
Location: Akron, OH

Posted: 30 Jun 2012 11:35:07 am    Post subject:

I didnt make this, I got it from here.

Any way, its a C function that will make 5-6-5 colors.


Code:

uint16_t drawRGB24toRGB565(uint8_t r, uint8_t g, uint8_t b)
{
  return ((r / 8) << 11) | ((g / 4) << 5) | (b / 8);
}

_________________



Back to top
souvik1997


Guru-in-Training


Joined: 19 Apr 2010
Posts: 2870

Posted: 16 Aug 2012 07:45:17 am    Post subject:

Scrollable Menu
This displays a scrollable menu and returns the choice picked by the user.

Code:
#define MENU_WIDTH 180
#define TEXT_HEIGHT 18
#define MENU_Y_GAP 17
#define MAX_CHOICES_DISPLAYED (LCD_HEIGHT_PX - 2*MENU_Y_GAP)/(TEXT_HEIGHT+1)
int ShowMenuList(char** menuchoices, int numofitems, char* title, color_t fg, color_t bg, color_t titlecolor) //returns the choice picked by the user
{   
   int curchoice = 0;
   int curchoicex = 0;
   int startchoice = 0;
   int update = 1;
   while (!(keydownlast(KEY_PRGM_RETURN) && !keydownhold(KEY_PRGM_RETURN)))
   {
      keyupdate();
      if (update)
      {
         fillArea((LCD_WIDTH_PX-MENU_WIDTH)/2, MENU_Y_GAP, MENU_WIDTH, LCD_HEIGHT_PX-2*MENU_Y_GAP, bg);
         drawLine((LCD_WIDTH_PX-MENU_WIDTH)/2,MENU_Y_GAP,(LCD_WIDTH_PX+MENU_WIDTH)/2,MENU_Y_GAP,fg); //draw a rectangle
         drawLine((LCD_WIDTH_PX-MENU_WIDTH)/2,MENU_Y_GAP,(LCD_WIDTH_PX-MENU_WIDTH)/2,LCD_HEIGHT_PX-MENU_Y_GAP,fg);
         drawLine((LCD_WIDTH_PX-MENU_WIDTH)/2,LCD_HEIGHT_PX-MENU_Y_GAP,(LCD_WIDTH_PX+MENU_WIDTH)/2,LCD_HEIGHT_PX-MENU_Y_GAP,fg);
         drawLine((LCD_WIDTH_PX+MENU_WIDTH)/2,MENU_Y_GAP,(LCD_WIDTH_PX+MENU_WIDTH)/2,LCD_HEIGHT_PX-MENU_Y_GAP,fg);         
         drawLine((LCD_WIDTH_PX-MENU_WIDTH)/2,MENU_Y_GAP+TEXT_HEIGHT+1,(LCD_WIDTH_PX+MENU_WIDTH)/2,MENU_Y_GAP+TEXT_HEIGHT+1,fg);
         PrintMiniFix((LCD_WIDTH_PX-MENU_WIDTH)/2+1,MENU_Y_GAP+1,title,PMF_ALLOW_STATUSAREA,titlecolor,bg);      
         for (int x = 0; x < MAX_CHOICES_DISPLAYED && x < numofitems; x++)
         {
            PrintMiniFix((LCD_WIDTH_PX-MENU_WIDTH)/2+12,(x+1)*TEXT_HEIGHT+MENU_Y_GAP+2,menuchoices[startchoice+x],PMF_ALLOW_STATUSAREA,fg,bg);            
            if ((startchoice+x) == curchoice)
            {
               PrintMiniFix((LCD_WIDTH_PX-MENU_WIDTH)/2+2,(x+1)*TEXT_HEIGHT+MENU_Y_GAP+2,">",PMF_ALLOW_STATUSAREA,fg,bg);
            }      
         }                  
         Bdisp_PutDisp_DD();
         update = 0;
      }
      if (keydownlast(KEY_PRGM_DOWN) && !keydownhold(KEY_PRGM_DOWN))
      {
         if (curchoice < numofitems-1)
         {
            curchoice++;
            curchoicex++;
            if (curchoicex >= MAX_CHOICES_DISPLAYED)
            {
               curchoicex = MAX_CHOICES_DISPLAYED;
               startchoice++;
            }
            update = 1;
         }
      }
      if (keydownlast(KEY_PRGM_UP) && !keydownhold(KEY_PRGM_UP))
      {
         if (curchoice > 0)
         {
            curchoice--;
            curchoicex--;
            if (curchoicex <= 0)
            {
               curchoicex = 0;
               startchoice--;
            }
            update = 1;
         }
      }      
   }
   return curchoice;      
}

Example usage

Code:
const char* list[] = {"menuchoice1","menuchoice2","menuchoice3","menuchoice4","menuchoice5"};
ShowMenuList(list,5,"Title",COLOR_BLACK,COLOR_WHITE,COLOR_RED));

_________________
CALCnet Tournament-38%


deviantArt
Back to top
gbl08ma


Power User


Joined: 26 Nov 2011
Posts: 475
Location: Portugal

Posted: 16 Aug 2012 08:14:29 am    Post subject:

That's really useful, souvik1997, but what about the same thing but using PrintXY and a scrollbar, so it mimics the OS style?
_________________
My blog, where I write about random things... | tiny URL shortener
View JPEG images on your Prizm | Utilities for the Casio Prizm - clock, stopwatch, calendar/agenda, add-in manager and more!
Back to top
flyingfisch


Super-Expert


Joined: 02 Feb 2012
Posts: 893
Location: Akron, OH

Posted: 16 Aug 2012 08:56:22 am    Post subject:

gbl08ma wrote:
That's really useful, souvik1997, but what about the same thing but using PrintXY and a scrollbar, so it mimics the OS style?


Yeah, a scroolbar would be good, also, doesn't it use PrintXY already?
_________________



Back to top
gbl08ma


Power User


Joined: 26 Nov 2011
Posts: 475
Location: Portugal

Posted: 16 Aug 2012 09:01:28 am    Post subject:

No, it uses PrintMiniFix. By the way, if we're going to use the Mini font type, I recommend you use PrintMini instead of the fixed-length PrintMiniFix.

(just don't forget PrintMini requires pointers instead of absolute values for x and y)
_________________
My blog, where I write about random things... | tiny URL shortener
View JPEG images on your Prizm | Utilities for the Casio Prizm - clock, stopwatch, calendar/agenda, add-in manager and more!
Back to top
souvik1997


Guru-in-Training


Joined: 19 Apr 2010
Posts: 2870

Posted: 16 Aug 2012 10:46:20 am    Post subject:

Here's a version with a scrollbar. It also fixes a bug with the scrolling.

Code:
#define MENU_WIDTH 180
#define TEXT_HEIGHT 18
#define MENU_Y_GAP 17
#define MAX_CHOICES_DISPLAYED (LCD_HEIGHT_PX - 2*MENU_Y_GAP)/(TEXT_HEIGHT+1)
int ShowMenuList(char** menuchoices, int numofitems, char* title, color_t fg, color_t bg, color_t titlecolor, int showscrollbar) //returns the choice picked by the user
{   
   int curchoice = 0;
   int curchoicex = 0;
   int startchoice = 0;
   int update = 1;
   int scrollbarheight = (LCD_HEIGHT_PX-2*MENU_Y_GAP-TEXT_HEIGHT)/(numofitems-MAX_CHOICES_DISPLAYED+1);
   while (!(keydownlast(KEY_PRGM_RETURN) && !keydownhold(KEY_PRGM_RETURN)))
   {
      keyupdate();
      if (update)
      {
         if (showscrollbar)
         {            
            fillArea((LCD_WIDTH_PX-MENU_WIDTH)/2, MENU_Y_GAP, MENU_WIDTH+1, LCD_HEIGHT_PX-2*MENU_Y_GAP, bg);
            drawLine((LCD_WIDTH_PX-MENU_WIDTH)/2,MENU_Y_GAP,(LCD_WIDTH_PX+MENU_WIDTH)/2+1,MENU_Y_GAP,fg); //draw a rectangle
            drawLine((LCD_WIDTH_PX-MENU_WIDTH)/2,MENU_Y_GAP,(LCD_WIDTH_PX-MENU_WIDTH)/2,LCD_HEIGHT_PX-MENU_Y_GAP,fg);
            drawLine((LCD_WIDTH_PX-MENU_WIDTH)/2,LCD_HEIGHT_PX-MENU_Y_GAP,(LCD_WIDTH_PX+MENU_WIDTH)/2+1,LCD_HEIGHT_PX-MENU_Y_GAP,fg);
            drawLine((LCD_WIDTH_PX+MENU_WIDTH)/2+1,MENU_Y_GAP,(LCD_WIDTH_PX+MENU_WIDTH)/2+1,LCD_HEIGHT_PX-MENU_Y_GAP,fg);   
            drawLine((LCD_WIDTH_PX-MENU_WIDTH)/2,MENU_Y_GAP+TEXT_HEIGHT+1,(LCD_WIDTH_PX+MENU_WIDTH)/2+1,MENU_Y_GAP+TEXT_HEIGHT+1,fg);
            if (startchoice < (numofitems-MAX_CHOICES_DISPLAYED))
               drawLine((LCD_WIDTH_PX+MENU_WIDTH)/2,MENU_Y_GAP+TEXT_HEIGHT+1+(startchoice)*scrollbarheight+1,(LCD_WIDTH_PX+MENU_WIDTH)/2,MENU_Y_GAP+TEXT_HEIGHT+1+(startchoice+1)*scrollbarheight+1,titlecolor);
            else
               drawLine((LCD_WIDTH_PX+MENU_WIDTH)/2,LCD_HEIGHT_PX-MENU_Y_GAP-scrollbarheight,(LCD_WIDTH_PX+MENU_WIDTH)/2,LCD_HEIGHT_PX-MENU_Y_GAP-1,titlecolor);

         }         
         else
         {
            fillArea((LCD_WIDTH_PX-MENU_WIDTH)/2, MENU_Y_GAP, MENU_WIDTH, LCD_HEIGHT_PX-2*MENU_Y_GAP, bg);
            drawLine((LCD_WIDTH_PX-MENU_WIDTH)/2,MENU_Y_GAP,(LCD_WIDTH_PX+MENU_WIDTH)/2,MENU_Y_GAP,fg); //draw a rectangle
            drawLine((LCD_WIDTH_PX-MENU_WIDTH)/2,MENU_Y_GAP,(LCD_WIDTH_PX-MENU_WIDTH)/2,LCD_HEIGHT_PX-MENU_Y_GAP,fg);
            drawLine((LCD_WIDTH_PX-MENU_WIDTH)/2,LCD_HEIGHT_PX-MENU_Y_GAP,(LCD_WIDTH_PX+MENU_WIDTH)/2,LCD_HEIGHT_PX-MENU_Y_GAP,fg);
            drawLine((LCD_WIDTH_PX+MENU_WIDTH)/2,MENU_Y_GAP,(LCD_WIDTH_PX+MENU_WIDTH)/2,LCD_HEIGHT_PX-MENU_Y_GAP,fg);
            drawLine((LCD_WIDTH_PX-MENU_WIDTH)/2,MENU_Y_GAP+TEXT_HEIGHT+1,(LCD_WIDTH_PX+MENU_WIDTH)/2,MENU_Y_GAP+TEXT_HEIGHT+1,fg);
         }         
         PrintMiniFix((LCD_WIDTH_PX-MENU_WIDTH)/2+1,MENU_Y_GAP+1,title,PMF_ALLOW_STATUSAREA,titlecolor,bg);               
         for (int x = 0; x < MAX_CHOICES_DISPLAYED && x < numofitems; x++)
         {
            PrintMiniFix((LCD_WIDTH_PX-MENU_WIDTH)/2+14,(x+1)*TEXT_HEIGHT+MENU_Y_GAP+2,menuchoices[startchoice+x],PMF_ALLOW_STATUSAREA,fg,bg);            
            if ((startchoice+x) == curchoice)
            {
               PrintMiniFix((LCD_WIDTH_PX-MENU_WIDTH)/2+2,(x+1)*TEXT_HEIGHT+MENU_Y_GAP+2,">",PMF_ALLOW_STATUSAREA,fg,bg);
            }      
         }                  
         Bdisp_PutDisp_DD();
         update = 0;
      }
      if (keydownlast(KEY_PRGM_DOWN) && !keydownhold(KEY_PRGM_DOWN))
      {
         if (curchoice < numofitems-1)
         {
            curchoice++;
            curchoicex++;
            if (curchoicex >= MAX_CHOICES_DISPLAYED)
            {
               curchoicex = MAX_CHOICES_DISPLAYED;
               if (startchoice < (numofitems-MAX_CHOICES_DISPLAYED)) startchoice++;
            }
            update = 1;
         }
      }
      if (keydownlast(KEY_PRGM_UP) && !keydownhold(KEY_PRGM_UP))
      {
         if (curchoice > 0)
         {
            curchoice--;
            curchoicex--;
            if (curchoicex <= 0)
            {
               curchoicex = 0;
               if (startchoice > 0) startchoice--;
            }
            update = 1;
         }
      }      
   }
   return curchoice;      
}

_________________
CALCnet Tournament-38%


deviantArt
Back to top
Tari


Systems Integrator


Joined: 03 Jul 2006
Posts: 2106
Location: Always-winter, Michigan

Posted: 16 Aug 2012 11:02:23 am    Post subject:

Kerm asked for my input on an efficient implementation of floor() yesterday, and pasted this (which appears to work, but annoyed me with its complexity).
Code:
float floor(float x) {
   return (((x)<0 && (x)!=(float)(int)(x))?(((float)(int)(x))-1):((float)(int)(x)));
}

I came up with this earlier this morning, instead (which should be both smaller and faster).

Code:
float floor(x) {
    return ((int)x) - (x < 0);
}

_________________


Ask questions the smart way · タリ
Back to top
merthsoft


File Archiver


Joined: 09 May 2010
Posts: 2735

Posted: 16 Aug 2012 11:20:31 am    Post subject:

Is this faster than using the floor provided in math.h? I assume that floor does all sorts of checking against for NaN and stuff, whereas yours doesn't.
_________________
Shaun
Back to top
Tari


Systems Integrator


Joined: 03 Jul 2006
Posts: 2106
Location: Always-winter, Michigan

Posted: 16 Aug 2012 11:36:58 am    Post subject:

There's no existing implementation. As is the case with many other functions, I added it to the header as a sort of note that it needs to be implemented.
_________________


Ask questions the smart way · タリ
Back to top
merthsoft


File Archiver


Joined: 09 May 2010
Posts: 2735

Posted: 16 Aug 2012 11:40:59 am    Post subject:

I thought math.h was builtin?
_________________
Shaun
Back to top
Display posts from previous:   
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 ... 8, 9, 10, 11  Next
» View previous topic :: View next topic  
Page 9 of 11 » All times are GMT - 5 Hours

 
Jump to:  
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

© Copyright 2000-2013 Cemetech & Kerm Martian :: Page Execution Time: 0.053914 seconds.