[RESOLVED] Take a Screenshot or is there an easier way...?

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
ADePSP
Posts: 58
Joined: Thu Jul 13, 2006 9:07 pm

[RESOLVED] Take a Screenshot or is there an easier way...?

Post by ADePSP »

I'm messing about with popup dialogs in my new app and want them to appear on top of whatever is currently on the screen and when you are done with them flip the screen back to what it was before...

I'm probably being dumb and there is an easy way to blit the dialog onto the current screen and then revert but not sure how...

I was thinking I might need to grab the current screen, blit that and then blit the dialog graphics over it and then flipScreen... Then, when done simply blit the original screen again and flipScreen to put the user back where they were...

Anyone know how to grab the current screen into an Image variable...? Something like the reverse of this,

Code: Select all

void blitImageToScreen(int sx, int sy, int width, int height, Image* source, int dx, int dy)
{
	if (!initialized) return;
	Color* vram = getVramDrawBuffer();
	sceKernelDcacheWritebackInvalidateAll();
	guStart();
	sceGuCopyImage(GU_PSM_8888, sx, sy, width, height, source->textureWidth, source->data, dx, dy, PSP_LINE_SIZE, vram);
	sceGuFinish();
	sceGuSync(0,0);
}
...i.e. blitScreenToImage instead...

Please tell me if there is an easier way but i'd like a function to capture parts of the screen anyway... It might come in handy...

Cheers
ADe
Last edited by ADePSP on Mon Aug 07, 2006 3:22 am, edited 1 time in total.
Kojima
Posts: 275
Joined: Mon Jun 26, 2006 3:49 am

Post by Kojima »

Not sure what you're doing, but I'd just carry on blitting the original screen before blitting the dialog.
ADePSP
Posts: 58
Joined: Thu Jul 13, 2006 9:07 pm

Post by ADePSP »

Kojima wrote:Not sure what you're doing, but I'd just carry on blitting the original screen before blitting the dialog.
I'm trying to encapsulate it so I end up with transportable code for my popup dialogs that don't need to know anything about what is on the current screen they are appearing on top of... The function will capture whatever junk is currently on the screen, display it's own thing on top of it and at the end return the screen to it's original state...

Does that make more sense or am I just confusing myself and everybody else...? :D

Thanks anyway and good work on the 3D Graphics engine I saw on PSPUpdates by the way...

ADe
ADePSP
Posts: 58
Joined: Thu Jul 13, 2006 9:07 pm

Post by ADePSP »

Ok, just wrote this function and it originally just saved a black image 480x272... I then relalized this was because the getPixelScreen function was getting the pixel from the buffer which had been swapped by the flipScreen function that was called before the saveScreen function was called later on in my code...

I added a flipScreen before I take the screenshot and one after to swap them back and it works but for a split second you see the previous screen whilst it swaps the one I want back into the buffer that can be read...

Is there a way to "copy" rather than swap the buffers so that on screen buffer and the "behind the scenes" buffer (that I can read) are the same so this flicker doesn't happen...?

Code: Select all

void saveScreen(char* filename) {

  int posX;
  int posY;
  Color pixel;
  Image* screenShot;

  screenShot = createImage(480,272);

  flipScreen();
  for &#40;posY=0; posY<272; posY++&#41; &#123;

     for&#40;posX=0; posX<480; posX++&#41; &#123;

        pixel = getPixelScreen&#40;posX,posY&#41;;

        putPixelImage&#40;pixel,posX,posY,screenShot&#41;;

     &#125;

  &#125;
  flipScreen&#40;&#41;;

  saveImage&#40;filename,screenShot->data,480,272,PSP_LINE_SIZE,0&#41;;

  freeImage&#40;screenShot&#41;;

&#125;
EDIT: Great, worked it out... I just needed to get the Display Buffer rather than the Draw buffer and now it works perfectly...

Here is a simple screenshot function if anyone wants it... Obviously requires the graphics.c include files...

Code: Select all

void saveScreen&#40;char* filename&#41; &#123;

  int posX;
  int posY;
  Color pixel;
  Color* vram = getVramDisplayBuffer&#40;&#41;;
  Image* screenShot;

  screenShot = createImage&#40;480,272&#41;;

  for &#40;posY=0; posY<272; posY++&#41; &#123;

     for&#40;posX=0; posX<480; posX++&#41; &#123;

        pixel = vram&#91;PSP_LINE_SIZE * posY + posX&#93;;

        putPixelImage&#40;pixel,posX,posY,screenShot&#41;;

     &#125;

  &#125;

  saveImage&#40;filename,screenShot->data,480,272,PSP_LINE_SIZE,0&#41;;

  freeImage&#40;screenShot&#41;;

&#125;
EDIT2: Probably better to split this function into 2 and allow people to grab sections of the screen aswell as save the whole thing...

Code: Select all

Image* grabScreen&#40;int x1, int y1, int x2, int y2&#41; &#123;

  int posX;
  int posY;
  Color pixel;
  Color* vram = getVramDisplayBuffer&#40;&#41;;
  Image* screenShot;

  screenShot = createImage&#40;x2-x1,y2-y1&#41;;

  for &#40;posY=y1; posY<y2; posY++&#41; &#123;

     for&#40;posX=x1; posX<x2; posX++&#41; &#123;

        pixel = vram&#91;PSP_LINE_SIZE * posY + posX&#93;;

        putPixelImage&#40;pixel,posX,posY,screenShot&#41;;

     &#125;

  &#125;

  return screenShot;

&#125;

void saveScreen&#40;char* filename&#41; &#123;

  Image* screenShot;

  screenShot = grabScreen&#40;0,0,480,272&#41;;

  saveImage&#40;filename,screenShot->data,480,272,PSP_LINE_SIZE,0&#41;;

  freeImage&#40;screenShot&#41;;

&#125;
paxux
Posts: 4
Joined: Tue Jul 25, 2006 6:18 pm

Post by paxux »

While that code will work you should be able to do it quicker with pointers and copying the block of memory all in one go and not reading each pixel individually

Pseudo code:

Code: Select all

LineLength = Width * Pixel Size;
for &#40;x=0; x < Height; x ++&#41;
   for  &#40;i=0; i < LineLength; i++&#41;
      Copy&#91;&#40;x * LineLength&#41;+i&#93; = Source&#91;&#40;x * LineLength&#41; + i&#93;;
Now depending on how you handle you’re Rendering queue you want to do overlays at the end of the process. Do you start each rendering loop with a blank screen or do you use the output from the previous loop?

If you want to have animated backgrounds while overlaying you’ll need something like this:

Standard Queue:
- New Frame
- Draw Object to Buffer [loop]
- Flip Buffer to PSP screen

Updated for Overlays:
Example (assumes new blank buffer each loop)
- Blank Buffer
- Draw Object to Buffer [loop]
- {new} if (overlay) DisplayOverlay();
- Flip Buffer to PSP screen

overlay a boolean that’s set while you want to display an overlay

Example (use last frame as input to the next)
- Draw Object to Screen [loop]
- {new} if (overlay) CopyScreen(); DisplayOverlay();
- Flip Buffer to PSP screen
- {new} if (overlay) RestoreScreen();

Don’t know if that made any sense? Hope you see what I’m getting at.
paxux
Posts: 4
Joined: Tue Jul 25, 2006 6:18 pm

Post by paxux »

Also what I just describing is a form (a very simple form) of Finite state machine. They're very handy if you know how to use them when solving problems with enable and disable logic blocks in code.
Post Reply