I don't know very much about C/ASM, but Kerm asked me to post this here:

http://www.top-progcasio.com/programme-216.html

It includes source code for the on-unload routine.

This is the same routine that eActivities uses for the Save dialog.
Oh well. The program fxLock flyingfisch posted includes source code, and I seem to understand how SetQuitHandler(void(*callback)(void)) works (it's described in the fx9860 SDK), the problem is that I'd like to use it on my screen locker (at least just as an experiment) but the PrizmSDK doesn't seem to have that function implemented. Any ideas?
Likely hasn't been exposed yet. You should bug Jonimus.
This is more of a generally-useful C routine or even general algorithm, but it takes a value z between z_min and z_max and converts it to a color. When z=z_max, the output color is dark blue; when z=z_min, it's maroon. The colors pass through bright red #F00) to yellow (#FF0) to bright green (#0F0) to aqua (#0FF) to bright blue (#00F) along the way. Enjoy, and I of course wouldn't mind a little attribution, but not necessary.

Code:

short unsigned int heightcolor(float z, float z_min, float z_max) {
         float frac = ((z-z_min)/(z_max-z_min));
         
         //color!
         float r = (0.25f)-frac;
         float g = (0.5f)-frac;
         float b = (0.75f)-frac;

         //calculate the R/G/B values
         r = (r>0.f)?r:-r; g = (g>0.f)?g:-g; b = (b>0.f)?b:-b;   //absolute value
         r = (0.25f)-r; g = (1.f/3.f)-g; b = (0.25f)-b;   //invert
         r = (r>0.f)?(6.f*r):0.f; g = (g>0.f)?(6.f*g):0.f; b = (b>0.f)?(6.f*b):0.f;   //scale the chromatic triangles
         r = (r>1.f)?1.f:r; g = (g>1.f)?1.f:g; b = (b>1.f)?1.f:b;   //clip the top of the chromatic triangles
         if (frac < 0.25f) r = (r+1.f)/2.f;   //adjust the bottom end of the scale so that z_min is red, not black
         if (frac > 0.75f) b = (b+1.f)/2.f;   //adjust the top end of the scale so that z_max is blue, not black
         return (short unsigned int)(0x0000ffff & (((int)(31.f*r) << 11) | ((int)(63.f*g) << 5) | ((int)(31.f*b))));   //put the bits together
}
Thank you, Kerm! Very Happy It fit into my program really well and I barely had to change anything: https://img.ourl.ca/rfg/mandelbrot-kerm-color.png
Neat! It looks like you might need to be a little more specific with your maximum z value, though?
Indeed, I changed it to a fixed amount, rather than the changing maxIteration value, and it looks a lot more vibrant: https://img.ourl.ca/rfg/mandelbrot-kerm-color-max-changed.png FWIW, here is the only part of the code that I changed (Pretty much just styling and making it use a Java function header):
Code:
  /* Awesome color routine from Kerm!! */
  private Color getColor(float z, float z_min, float z_max) {
    float frac = ((z-z_min)/(z_max-z_min));
   
    //color!
    float r = (0.25f)-frac;
    float g = (0.5f)-frac;
    float b = (0.75f)-frac;
   
    //calculate the R/G/B values
    r = (r>0.f)?r:-r;            g = (g>0.f)?g:-g;          b = (b>0.f)?b:-b;              //absolute value
    r = (0.25f)-r;               g = (1.f/3.f)-g;           b = (0.25f)-b;                 //invert
    r = (r>0.f)?(6.f*r):0.f;     g = (g>0.f)?(6.f*g):0.f;   b = (b>0.f)?(6.f*b):0.f;       //scale the chromatic triangles
    r = (r>1.f)?1.f:r;           g = (g>1.f)?1.f:g;         b = (b>1.f)?1.f:b;             //clip the top of the chromatic triangles
    if (frac < 0.25f) r = (r+1.f)/2.f;   //adjust the bottom end of the scale so that z_min is red, not black
    if (frac > 0.75f) b = (b+1.f)/2.f;   //adjust the top end of the scale so that z_max is blue, not black
    return new Color(r, g, b);
    //return (short unsigned int)(0x0000ffff & (((int)(31.f*r) << 11) | ((int)(63.f*g) << 5) | ((int)(31.f*b))));   //put the bits together
  }
And here's the code that calls it (iteration is a variable for how many iterations it was able to do before it reached infinity):
Code:
return getColor((float)iteration, (float)0, 200.0f);
Great, that looks quite spiffy to me. Smile Thanks for sharing the fruits of my code.
*bump* I recently added the ability for SourceCoder to generate 8-bit, 2-bit, and 1-bit data from images. The following two routines work with the 2-bit versions. Two-bit images are particularly good for two-color or three-color images that also have a mask color.

Sample usages:

Code:
unsigned short int palette[4] = {COLOR_BLACK, COLOR_BLUEVIOLET, COLOR_RED, COLOR_WHITE};
CopySpriteMasked2bit(mysprite, 5, 70, 32, 32, palette);
CopySprite2bit(mysprite, 5, 70, 32, 32, palette);


For the Masked version, the COLOR_RED (aka, color #2 of 0,1,2,3) is the transparent color.


Code:
void CopySpriteMasked2bit(const unsigned char* data, int x, int y, int width, int height, short unsigned int* palette) {
   short unsigned int* VRAM = (short unsigned int*)0xA8000000;
   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;
         }
         char this = ((buf&0xC0)>>6);
         if (this != 0x02)
            *VRAM = palette[(int)this];
         VRAM++;
         buf<<=2;
         availbits-=2;
      }
      VRAM += (LCD_WIDTH_PX-width);
   }
}



Code:
void CopySprite2bit(const unsigned char* data, int x, int y, int width, int height, short unsigned int* palette) {
   short unsigned int* VRAM = (short unsigned int*)0xA8000000;
   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;
         }
         char this = ((buf&0xC0)>>6);
         *VRAM = palette[(int)this];
         VRAM++;
         buf<<=2;
         availbits-=2;
      }
      VRAM += (LCD_WIDTH_PX-width);
   }
}
*bump* Here's a pair of routines that I fixed in gCAS2. They're nothing amazing, but they work.


Code:
int _g_strcmp(char *a, char *b)
{
    const char* p1 = a - 1;
    const char* p2 = b - 1;

    while (*++p2 == *++p1)
        if (!*p2 || !*p1)
            break;

    if (*p2 > *p1)
        return (-1);
    else if (*p1 > *p2)
        return (1);

    return (0);
}
*Quadruple Bump Powerup Combo!*

For Graph3DP, I created an input routine for single-line, scrolling text or number entry. It does strings, ints, positive ints, and floats. I didn't make it do lowercase letters yet, since I didn't want them for my application; I'll probably update that page accordingly soon. You can read all about it here:

http://prizm.cemetech.net/index.php?title=Text_and_Number_Input
KermMartian wrote:
*Quadruple Bump Powerup Combo!*

For Graph3DP, I created an input routine for single-line, scrolling text or number entry. It does strings, ints, positive ints, and floats. I didn't make it do lowercase letters yet, since I didn't want them for my application; I'll probably update that page accordingly soon. You can read all about it here:

http://prizm.cemetech.net/index.php?title=Text_and_Number_Input


Wow, that's one of the finest additions to our useful routines set yet! Very nice work Kerm, this was probably one of our most-needed routines right now.
Thanks very much. Smile It took me quite a while to work up the motivation to write it, but once I started, it actually was surprisingly fast to complete it.
Frequency Changing Routines

Inputs: none
Outputs: none

Notes: PLEASE before handling MENU keypresses in your add-in, use PLL_16x to go back to normal operating speed, at the courtesy of other applications and the OS.

Thanks to Brijohn for the information that helped me make these headways. The routine below is based on his routines, except optimized and condensed to a single, easy-to-use routine, which can be simply plopped into your C file.

Feeding a value not defined below (AKA, an invalid value), will cause a crash.


Code:
#define PLL_24x 0b010111 // 87 MHz
#define PLL_18x 0b010001 // 65.25 MHz
#define PLL_16x 0b001111 // 58 MHz (NORMAL SPEED)
#define PLL_15x 0b001110 // 54.37 MHz
#define PLL_12x 0b001011 // 43.5 MHz
#define PLL_8x  0b000111 // 29 MHz
#define PLL_6x  0b000101 // 21.75 MHz
#define PLL_4x  0b000011 // 14.5 MHz
#define PLL_3x  0b000010 // 10.8 MHz
#define PLL_2x  0b000001 // 7.25 MHz
#define PLL_1x  0b000000 // 3.6 MHz

__attribute__ ((noinline))  void change_freq(int mult) {
   __asm__(
      "mov r4, r0\n\t"
      "and #0x3F, r0\n\t"
      "shll16 r0\n\t"
      "shll8 r0\n\t"
      "mov.l frqcr, r1\n\t" 
      "mov.l pll_mask, r3\n\t" 
      "mov.l @r1, r2\n\t" 
      "and r3, r2\n\t" 
      "or r0, r2\n\t"
      "mov.l r2, @r1\n\t"
      "mov.l frqcr_kick_bit, r0\n\t"
      "mov.l @r1, r2\n\t"
      "or r0, r2\n\t"
      "rts\n\t"
      "mov.l r2, @r1\n\t"
      ".align 4\n\t"
      "frqcr_kick_bit: .long 0x80000000\n\t"
      "pll_mask: .long 0xC0FFFFFF\n\t"
      "frqcr: .long 0xA4150000\n\t"
   );
}



Next thing on my list is finding out how to update the physical LCD memory from VRAM, since I think it can probably be doubly optimized to half speed. Once I have a full lead with working routines, they shall be here.


EDIT: I invite all people here to put their routines on the WikiPrizm page: http://prizm.cemetech.net/index.php?title=Useful_Routines It would be very helpful to everyone else here, to have all of these routines in an organized place as well.
Why do it in assembly when you can integrate more tightly?

Code:
void change_freq(uint8_t mult) {
    volatile uint32_t * const frqcr = 0xA4150000;

    uin32_t cr = *frqcr;
    cr &= ~(0x3F << 24);
    cr |= (mult & 0x3F) << 24;
    frqcr = cr;
    frqcr |= 0x80000000;
}

Usual disclaimer about how I didn't test this goes here, doubly so since I may have mistranslated some of it.
OPTIMIZATION TIEM!


Code:
#define PLL_24x 0b010111 // 87 MHz
#define PLL_18x 0b010001 // 65.25 MHz
#define PLL_16x 0b001111 // 58 MHz (NORMAL SPEED)
#define PLL_15x 0b001110 // 54.37 MHz
#define PLL_12x 0b001011 // 43.5 MHz
#define PLL_8x  0b000111 // 29 MHz
#define PLL_6x  0b000101 // 21.75 MHz
#define PLL_4x  0b000011 // 14.5 MHz
#define PLL_3x  0b000010 // 10.8 MHz
#define PLL_2x  0b000001 // 7.25 MHz
#define PLL_1x  0b000000 // 3.6 MHz

void change_freq(int mult) {
   __asm__(
      "mov #26, r0\n\t"
      "shld r0, r4\n\t" 
      "shlr2 r4\n\t"   
      "mov.l frqcr, r1\n\t" 
      "mov.l pll_mask, r3\n\t" 
      "mov.l @r1, r2\n\t" 
      "and r3, r2\n\t" 
      "or r4, r2\n\t" 
      "mov.l r2, @r1\n\t" 
      "mov #1, r0\n\t"
      "rotr r0\n\t"
      "or r0, r2\n\t"
      "rts\n\t"
      "mov.l r2, @r1\n\t"
      ".align 4\n\t"
      "pll_mask: .long 0xC0FFFFFF\n\t" 
      "frqcr: .long 0xA4150000\n\t"
   );
}
I prefer the C implementation, personally; is the version that GCC creates for that C code really that bad? Sad
KermMartian wrote:
I prefer the C implementation, personally; is the version that GCC creates for that C code really that bad? Sad


It's (almost) purely for the feeling of being 1337, methinks Wink (and in my case, the point of learning SH assembly) The C version should be fine; and of course, this routine in particular doesn't need to be optimized, since you won't be using it in a main game render loop.
I noticed that most routines still use a fix VRAM address (0xA8000000). This is bad, VERY BAD.

Within the past 7 years, Casio changed the VRAM address three times on models like the fx-9860G. This is okay, if you regularly update your add-ins, but most add-ins won't be updated regularly...

So better use syscall 0x01E6:
void *GetVRAMAddress(void);
Ah, I had no idea, thanks for that! Does that exist in the PrizmSDK? If so, would someone mind documenting that on WikiPrizm? I think that programs should only call that at the very beginning and save it in a global variable, however, to avoid lagging down screen-manipulation routines with a syscall.
  
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 ... 6, 7, 8 ... 10, 11, 12  Next
» View previous topic :: View next topic  
Page 7 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