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 113 users online: 2 members, 85 guests and 26 bots.
Members: None.
Bots: VoilaBot (1), Spinn3r (1), Magpie Crawler (3), VoilaBot (1), Googlebot (18), MSN/Bing (2).
RSS & Social Media
SAX
You must log in to view the SAX chat widget
Author Message
KermMartian


Site Admin


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

Posted: 17 Apr 2011 11:18:10 am    Post subject: Useful Prizm Routines

I'll start us off.

XORSprite and CopySprite
The former XORs a sprite of specified width and height to the screen. Do it twice, and the screen will return to its original state. The latter routine overwrites the data on the screen, but is (potentially) faster because it memcpys each row. Note that these routines expect the sort of data that SourceCoder outputs.


Code:
#define LCD_WIDTH_PX 384
#define LCD_HEIGHT_PX 216
void XORSprite(char* data, int x, int y, int width, int height) {
   char* VRAM = (char*)0xA8000000;
   VRAM += 2*(LCD_WIDTH_PX*y + x);
   for(int j=y; j<y+height; j++) {
      for(int i=x; i<x+width;  i++) {
         *(VRAM++) ^= *(data++);
         *(VRAM++) ^= *(data++);
      }
      VRAM += 2*(LCD_WIDTH_PX-width);
   }
}
void CopySprite(char* data, int x, int y, int width, int height) {
   char* VRAM = (char*)0xA8000000;
   VRAM += 2*(LCD_WIDTH_PX*y + x);
   for(int j=y; j<y+height; j++) {
      memcpy(VRAM,data,2*width);
      VRAM += 2*LCD_WIDTH_PX;
      data += 2*width;
   }
}

_________________




Last edited by KermMartian on 13 May 2011 03:32:56 pm; edited 2 times in total
Back to top
_player1537


Guru-in-Training


Joined: 25 Nov 2009
Posts: 2957

Posted: 17 Apr 2011 11:45:27 am    Post subject:

How would we copy the data to the screen? What method, I mean.
_________________
http://tanner.myserverathome.com
Back to top
KermMartian


Site Admin


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

Posted: 17 Apr 2011 11:46:32 am    Post subject:

Once you have data written to the Video RAM (VRAM), the equivalent to iFastCopy is
Code:
      Bdisp_PutDisp_DD();

_________________


Back to top
merthsoft


File Archiver


Joined: 09 May 2010
Posts: 2735

Posted: 17 Apr 2011 02:01:42 pm    Post subject:

Until I find a better way to do it, this is how I do non-blocking key input:

Code:
if (PRGM_GetKey()) {
   GetKey(&key);
} else {
   key = 0;
}

It only kind of works, though.
_________________
Shaun
Back to top
KermMartian


Site Admin


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

Posted: 17 Apr 2011 02:26:18 pm    Post subject:

Here's a suggestion from the miniSDK:


Code:
To yield the same function result as PRGM-GETKEY one could use this:

int PRGM_GetKey(){
unsigned char buffer[12];
        KBD_PRGM_GetKey( buffer );
        return ( buffer[1] & 0x0F ) * 10 + ( ( buffer[2]  & 0xF0 )  >> 4 );

}


Edit: On investigation, this is better:


Code:
int GetKey_NonBlock() {
    int key;
    key = PRGM_GetKey();
    if (key == KEY_PRGM_MENU)
        GetKey(&key);
    return key;
}

_________________


Back to top
merthsoft


File Archiver


Joined: 09 May 2010
Posts: 2735

Posted: 17 Apr 2011 02:40:28 pm    Post subject:

I assume that's what PRGM_GetKey() is in keyboard.hpp. Here's what I'm doing:

Code:

int lastKey, key;
while(1) {
   lastKey = key;
   key = PRGM_GetKey();
   switch (key) {
      /* ... */
      case KEY_PRGM_MENU:
         GetKey(&key);
         break;
   }
}

Last key is for stuff like my function keys, which shouldn't repeat if you hold down the button.
_________________
Shaun
Back to top
ephan


Super-Expert


Joined: 12 Nov 2010
Posts: 819

Posted: 17 Apr 2011 02:41:51 pm    Post subject:

Based on the first post I think a routine to flip the screen horizontally and vertically would be possible. Am I right?
Back to top
merthsoft


File Archiver


Joined: 09 May 2010
Posts: 2735

Posted: 17 Apr 2011 03:26:40 pm    Post subject:

String concatenation:

Code:
char* concat(char* str1, char* str2) {
   int len1 = 0;
   int len2 = 0;
   for (;str1[len1] != '\0'; len1++);
   for (;str2[len2] != '\0'; len2++);

   char* str3 = (char*)malloc(len1 + len2 + 1);
   int i;
   for (i = 0; i < len1; str3[i] = str1[i], i++);
   for (i = 0; i < len2; str3[len1+i] = str2[i], i++);
   str3[len1 + len2] = 0;
   
   return str3;
}

_________________
Shaun
Back to top
KermMartian


Site Admin


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

Posted: 17 Apr 2011 03:43:29 pm    Post subject:

Depending on the size of the strings, a pair of memcpy()s instead of those two for() loops at the end might be faster, but it's almost definitely a trivial difference. Therefore, I'd call that good enough.
_________________


Back to top
KermMartian


Site Admin


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

Posted: 18 Apr 2011 12:04:28 am    Post subject:

ScoutDavid wrote:
Based on the first post I think a routine to flip the screen horizontally and vertically would be possible. Am I right?
Not only possible, but trivial. If someone wants it, I would be happy to write such a routine. Anywhere, here's a few useful routines:

DrawDialog

Code:
//Draws a DCS SmallWindow-style dialog box.  Can fit in
//text from (x,y)=(4,3) through (x,y)=(8,17)
void drawDialog(char* title) {
   #define DIALOG_WIDTH 256
   #define DIALOG_HEIGHT 152
   #define DIALOG_X 50
   #define DIALOG_Y 39
   fillArea(DIALOG_X,DIALOG_Y,DIALOG_WIDTH,DIALOG_HEIGHT,0x0000FFFF);      //fill with white
   drawLine(DIALOG_X,DIALOG_Y,DIALOG_X+DIALOG_WIDTH,DIALOG_Y,0x00000000);
   drawLine(DIALOG_X,DIALOG_Y,DIALOG_X,DIALOG_Y+DIALOG_HEIGHT,0x00000000);
   drawLine(DIALOG_X+DIALOG_WIDTH,DIALOG_Y+DIALOG_HEIGHT,DIALOG_X+DIALOG_WIDTH,DIALOG_Y,0x00000000);
   drawLine(DIALOG_X+DIALOG_WIDTH,DIALOG_Y+DIALOG_HEIGHT,DIALOG_X,DIALOG_Y+DIALOG_HEIGHT,0x00000000);
   for(int i=DIALOG_Y+1;i<DIALOG_Y+32;i++) {
      drawLine(DIALOG_X+1, i, DIALOG_X+DIALOG_WIDTH-1, i, makeGray((i-DIALOG_Y)/2));
   }
   PrintXY(4, 2, title, 0x20, 7);
   CopySprite(closebutton,DIALOG_X+DIALOG_WIDTH-30,DIALOG_Y+3,27,26);
}


MakeGray

Code:
//shade can be between 0 (black) and 31 (white)
//creates a two-byte 5/6/5 color code
int makeGray(int shade) {
   return (((shade<<11)&0x0000F800) | ((shade << 6)&0x000007C0) | ((shade)&0x0000001F));
}


DrawLine

Code:
//Uses the Bresenham line algorithm
void drawLine(int x1, int y1, int x2, int y2, int color) {
    signed char ix;
    signed char iy;
 
    // if x1 == x2 or y1 == y2, then it does not matter what we set here
    int delta_x = (x2 > x1?(ix = 1, x2 - x1):(ix = -1, x1 - x2)) << 1;
    int delta_y = (y2 > y1?(iy = 1, y2 - y1):(iy = -1, y1 - y2)) << 1;
 
   plot(x1, y1, color);
    if (delta_x >= delta_y) {
        int error = delta_y - (delta_x >> 1);        // error may go below zero
        while (x1 != x2) {
            if (error >= 0) {
                if (error || (ix > 0)) {
                    y1 += iy;
                    error -= delta_x;
                }                           // else do nothing
         }                              // else do nothing
            x1 += ix;
            error += delta_y;
            plot(x1, y1, color);
        }
    } else {
        int error = delta_x - (delta_y >> 1);      // error may go below zero
        while (y1 != y2) {
            if (error >= 0) {
                if (error || (iy > 0)) {
                    x1 += ix;
                    error -= delta_y;
                }                           // else do nothing
            }                              // else do nothing
            y1 += iy;
            error += delta_x;
            plot(x1, y1, color);
        }
    }
}


Plot

Code:
//draws a point of color color at (x0, y0)
void plot(int x0, int y0, int color) {
   char* VRAM = (char*)0xA8000000;
   VRAM += 2*(y0*LCD_WIDTH_PX + x0);
   *(VRAM++) = (color&0x0000FF00)>>8;
   *(VRAM++) = (color&0x000000FF);
   return;
}


FillArea

Code:
//fills a rectangular area of (width,height) with upper-left
//corner at (x,y) with color color
void fillArea(int x, int y, int width, int height, int color) {
   //only use lower two bytes of color
   char* VRAM = (char*)0xA8000000;
   VRAM += 2*(LCD_WIDTH_PX*y + x);
   for(int j=y; j<y+height; j++) {
      for(int i=x; i<x+width;  i++) {
         *(VRAM++) = (color&0x0000FF00)>>8;
         *(VRAM++) = (color&0x000000FF);
      }
      VRAM += 2*(LCD_WIDTH_PX-width);
   }
}

_________________


Back to top
TheStorm


NOU!


Joined: 26 Mar 2007
Posts: 2375

Posted: 18 Apr 2011 12:07:49 am    Post subject:

We could really put a lot of these into a libfxgc or sorts so that users can easily compile them into the main program. In fact I'd suggest we start just that. My thought would be have sets of statically linkable libs with related routines. One main one for syscalls and helper functions, another for a GUI library, maybe another with Floating point stuff etc. Thoughts?
_________________

"Always code as if the person who will maintain your code is a maniac serial killer that knows where you live" -Unknown

"If you've done something right no one will know that you've done anything at all" -Futurama

"Have a nice day, or not, the choice is yours." Tom Steiner

<Michael_V> or create a Borg collective and call it The 83+
<Michael_V> Lower your slide cases and prepare to be silent linked. Memory clears are futile.
Back to top
KermMartian


Site Admin


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

Posted: 18 Apr 2011 10:25:53 am    Post subject:

I think that's an awesome idea. I'm also thinking strongly that if I do indeed make some kind of Doors CS port, that it will have a version of the DCS GUI system, because it would be much much easier on this. Is there a such library that will only link in the routines that the user uses?
_________________


Back to top
TheStorm


NOU!


Joined: 26 Mar 2007
Posts: 2375

Posted: 18 Apr 2011 10:33:03 am    Post subject:

I would think GCC would be smart enough to figure that out but I'm not sure one that.
_________________

"Always code as if the person who will maintain your code is a maniac serial killer that knows where you live" -Unknown

"If you've done something right no one will know that you've done anything at all" -Futurama

"Have a nice day, or not, the choice is yours." Tom Steiner

<Michael_V> or create a Borg collective and call it The 83+
<Michael_V> Lower your slide cases and prepare to be silent linked. Memory clears are futile.
Back to top
KermMartian


Site Admin


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

Posted: 18 Apr 2011 10:37:04 am    Post subject:

TheStorm wrote:
I would think GCC would be smart enough to figure that out but I'm not sure one that.
To optimize out routines that aren't called from anywhere, you mean? That's a good point, I didn't even think of that. Very Happy I'm so used to working with z80 assembly where you'd have to come up with some sort of mechanism to only include the routines in a linked library that you need.
_________________


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 May 2011 06:50:19 pm    Post subject:

Does anyone know a routine to copy the contents of VRAM to the actual LCD?
_________________
-Ashbad
Back to top
KermMartian


Site Admin


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

Posted: 01 May 2011 06:54:49 pm    Post subject:

Ashbad wrote:
Does anyone know a routine to copy the contents of VRAM to the actual LCD?
Just call Bdisp_PutDisp_DD();. For example, the code below clears the screen, copies on the Obliterate titlescreen, draws the select-item menu sprite, and copies everything to the screen. The z80 analog is iPutSprite.


Code:
      Bdisp_AllCr_VRAM();
      memcpy(VRAM,oblit_prizm_title,(384*216*2));
      CopySprite(menubullet,264,131+21*menuitem,16,16);
      Bdisp_PutDisp_DD();

_________________


Back to top
calc84maniac


Epic z80 roflpwner


Joined: 01 Aug 2006
Posts: 1503
Location: The ex-planet Pluto

Posted: 01 May 2011 07:05:54 pm    Post subject:

This might actually be a better way to do the MakeGray routine:

Code:
//shade can be between 0 (black) and 31 (white)
//creates a two-byte 5/6/5 color code
int makeGray(int shade) {
   return shade * 0x0841;
}

since a multiplication is probably more optimized than a bunch of shifting and masking on the SuperH. If there was a way to optimize this to a 16-bit x 16-bit multiplication, that would be even better (inline assembly?)
_________________
~calc84maniac has spoken.

Projects:
TI-Boy SE
F-Zero
Super Mario (aka Project M)
Back to top
KermMartian


Site Admin


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

Posted: 01 May 2011 07:19:13 pm    Post subject:

Close, but not quite. 31 yields FFDF, for instance, rather than FFFF. Using 0x0842 instead of 0x0841 yields FFFF, which is closer, but of course it doesn't do the intermediate values properly. I suppose that's not bad if it gets decent speed, and I suppose getting the least significant bit of the green wrong is not the total end of the world.
_________________


Back to top
calc84maniac


Epic z80 roflpwner


Joined: 01 Aug 2006
Posts: 1503
Location: The ex-planet Pluto

Posted: 01 May 2011 07:22:59 pm    Post subject:

KermMartian wrote:
Close, but not quite. 31 yields FFDF, for instance, rather than FFFF. Using 0x0842 instead of 0x0841 yields FFFF, which is closer, but of course it doesn't do the intermediate values properly. I suppose that's not bad if it gets decent speed, and I suppose getting the least significant bit of the green wrong is not the total end of the world.

I just did exactly what your routine did, so... Razz
_________________
~calc84maniac has spoken.

Projects:
TI-Boy SE
F-Zero
Super Mario (aka Project M)
Back to top
KermMartian


Site Admin


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

Posted: 01 May 2011 07:25:20 pm    Post subject:

calc84maniac wrote:
I just did exactly what your routine did, so... Razz
So you did, and I now see why that wasn't looking right to me, and also why I'm stupid. Of course the LSB of green will always be zero for gray values 0-31. :S
_________________


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 1, 2, 3 ... 9, 10, 11  Next
» View previous topic :: View next topic  
Page 1 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.049689 seconds.