screenshot PRX problem

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

Moderators: cheriff, TyRaNiD

Post Reply
pspflashsystem
Posts: 31
Joined: Mon Mar 24, 2008 12:31 am

screenshot PRX problem

Post by pspflashsystem »

Hello everyone,
I have a problem with my screenshot.prx: when I pressed SQUARE the prx take a screenshot but the recorded bmp weighs 0 byte therefore no previsualization is available when I want to see the screenshot...
Please help me ^^

Here the main.c:

Code: Select all

#include <string.h>
#include <stdio.h>
#include <pspmoduleinfo.h>
#include <kubridge.h>
#include <systemctrl.h>
#include <pspkernel.h>
#include <pspctrl.h>
#include <psppower.h>
#include <pspdisplay.h>
#include <pspdebug.h>
#include "screenshot.h"

/*  Information du programme  */ 
PSP_MODULE_INFO&#40;"screenshot", 0x1000, 1, 1&#41;;
PSP_MAIN_THREAD_ATTR&#40;0&#41;;
PSP_MAIN_THREAD_STACK_SIZE_KB&#40;0&#41;;

SceUID main_thid;

int main_thread&#40;SceSize args, void *argp&#41;
&#123;
SceCtrlData pad;
while&#40;1&#41;   // Boucle qui maintient le prx actif dans le XMB 
&#123;
sceCtrlReadBufferPositive&#40;&pad, 1&#41;;
if&#40;pad.Buttons & PSP_CTRL_SQUARE&#41;			
&#123;
int dossier = sceIoDopen&#40;"ms0&#58;/PICTURE/SCREEN"&#41;;
	
if &#40;dossier >= 0&#41;
&#123;
printf&#40;"Directory already exist\n"&#41;;					
&#125; 
else &#123;
sceIoMkdir&#40;"ms0&#58;/PICTURE/SCREEN", 0777&#41;;
&#125;
screenshot&#40;&#41;;
&#125;	
sceKernelDelayThread&#40;100000&#41;;
&#125;
return 0;
&#125;



int module_start&#40;SceSize args, void *argp&#41;
&#123;

	main_thid = sceKernelCreateThread&#40;"screenshot_main", main_thread, 6, 0x4000, 0, NULL&#41;;
	if&#40;main_thid >= 0&#41; sceKernelStartThread&#40;main_thid, args, argp&#41;;

	return 0;

	sceKernelExitDeleteThread&#40;0&#41;;
&#125;

int module_stop&#40;SceSize args, void *argp&#41;
&#123;
	return 0;
&#125;
Here the screenshot.c:

Code: Select all

#include <pspkernel.h>
#include <pspdebug.h>
#include <pspkdebug.h>
#include <pspctrl_kernel.h>
#include <pspdisplay.h>
#include <pspdisplay_kernel.h>
#include <pspsdk.h>
#include <pspctrl.h>
#include <psppower.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pspthreadman.h>
#include <pspsysmem.h>
#include <pspusb.h>
#include <pspusbstor.h>
#include <pspsyscon.h>
#include <pspiofilemgr.h>

#include "screenshot.h"
//#include "conf.h"

//CONFIGFILE config;

//#define picture "ms0&#58;/PICTURE/SCREEN"

typedef struct THREAD&#123;
	int count;
	SceUID pThread;
&#125; THREAD;

int count_Start;
SceUID Thread_Start&#91;MAX_THREAD&#93;;
THREAD bufNow;


int nkLoad&#40;&#41;&#123;

	count_Start = 0;

	sceKernelGetThreadmanIdList&#40;SCE_KERNEL_TMID_Thread, Thread_Start, MAX_THREAD, &count_Start&#41;;

	bufNow.count = 0;
	bufNow.pThread = 0;

	return 0;
&#125;



int nkThreadSuspend&#40;SceUID thId&#41;&#123;

	int i, j;
	SceUID myThread, *Thread_Now;

	if&#40;bufNow.pThread != 0&#41; return 1;

	bufNow.pThread = sceKernelAllocPartitionMemory&#40;1, "th", 0, MAX_THREAD*sizeof&#40;SceUID&#41;, NULL&#41;;
	if&#40;bufNow.pThread < 0&#41;&#123;
		bufNow.count = 0;
		bufNow.pThread = 0;
		return 1;
	&#125;
	Thread_Now = &#40;SceUID*&#41;sceKernelGetBlockHeadAddr&#40;bufNow.pThread&#41;;

	sceKernelGetThreadmanIdList&#40;SCE_KERNEL_TMID_Thread, Thread_Now, MAX_THREAD, &&#40;bufNow.count&#41;&#41;;
	myThread = sceKernelGetThreadId&#40;&#41;;

	for&#40;i = 0; i < bufNow.count; i++&#41;&#123;
		unsigned char match = 0;
		SceUID tmp_thid = Thread_Now&#91;i&#93;;
		
		for&#40;j = 0; j < count_Start; j++&#41;&#123;
			if&#40;&#40;tmp_thid == Thread_Start&#91;j&#93;&#41; || &#40;tmp_thid == thId&#41; || &#40;tmp_thid == myThread&#41;&#41;&#123;
				match = 1;
				j = count_Start;
			&#125;
		&#125;
		if&#40;match == 0&#41;&#123;
			sceKernelSuspendThread&#40;tmp_thid&#41;;
		&#125;
	&#125;

	return 0;
&#125;

int nkThreadResume&#40;SceUID thId&#41;&#123;

	int i, j;
	SceUID myThread, *Thread_Now;

	if&#40;bufNow.pThread == 0&#41; return 1;

	Thread_Now = &#40;SceUID*&#41;sceKernelGetBlockHeadAddr&#40;bufNow.pThread&#41;;
	myThread = sceKernelGetThreadId&#40;&#41;;
	

	for&#40;i = 0; i < bufNow.count; i++&#41;&#123;
		unsigned char match = 0;
		SceUID tmp_thid = Thread_Now&#91;i&#93;;
		
		for&#40;j = 0; j < count_Start; j++&#41;&#123;
			if&#40;&#40;tmp_thid == Thread_Start&#91;j&#93;&#41; || &#40;tmp_thid == thId&#41; || &#40;tmp_thid == myThread&#41;&#41;&#123;
				match = 1;
				j = count_Start;
			&#125;
		&#125;

		if&#40;match == 0&#41;&#123;
			sceKernelResumeThread&#40;tmp_thid&#41;;
		&#125;
	&#125;
	
	sceKernelFreePartitionMemory&#40;bufNow.pThread&#41;;
	bufNow.count = 0;
	bufNow.pThread = 0;

	return 0;
&#125;

typedef unsigned char   BYTE;
typedef unsigned short  WORD;
typedef unsigned long   DWORD;
typedef long            LONG;

typedef struct tagBITMAPFILEHEADER &#123;
   //    WORD    bfType;
        DWORD   bfSize;
        DWORD   bfReserved;
        DWORD   bfOffBits;
&#125; BITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER&#123;
	DWORD	biSize;
	LONG	biWidth;
	LONG	biHeight;
	WORD	biPlanes;
	WORD	biBitCount;
	DWORD	biCompression;
	DWORD	biSizeImage;
	LONG	biXPelsPerMeter;
	LONG	biYPelsPerMeter;
	DWORD	biClrUsed;
	DWORD	biClrImportant;
&#125; BITMAPINFOHEADER;

void screenshot_BMP&#40;const char* filename, char imageSize&#41;&#123;
	
	int x, y;
	int fd = sceIoOpen&#40;filename, PSP_O_CREAT|PSP_O_WRONLY|PSP_O_TRUNC, 0777&#41;;
	if&#40;fd < 0&#41; return;

	int pwidth, pheight, bufferwidth, pixelformat, unk;
	unsigned int* vram32;
	unsigned short* vram16;

	sceDisplayWaitVblankStart&#40;&#41;;
	sceDisplayGetMode&#40;&unk, &pwidth, &pheight&#41;;
	sceDisplayGetFrameBuf&#40;&#40;void*&#41;&vram32, &bufferwidth, &pixelformat, &unk&#41;;
	vram16 = &#40;unsigned short*&#41; vram32;
		
	unsigned char bm&#91;2&#93;, padding;
	BITMAPFILEHEADER h1;
	BITMAPINFOHEADER h2;

	bm&#91;0&#93; = 0x42;
	bm&#91;1&#93; = 0x4D;
	sceIoWrite&#40;fd, bm, 2&#41;;

	int pw = pwidth, ph = pheight;
	if&#40;imageSize > 0&#41; pw /=2, ph /= 2;
		
	padding = &#40;3*&#40;pw/2&#41; % 4&#41;;
	h1.bfSize	= &#40;&#40;24*pw + padding&#41;*ph&#41;/8 + sizeof&#40;BITMAPFILEHEADER&#41; + sizeof&#40;BITMAPINFOHEADER&#41; + 2;
	h1.bfReserved	= 0;
	h1.bfOffBits	= 2 + sizeof&#40;BITMAPFILEHEADER&#41; + sizeof&#40;BITMAPINFOHEADER&#41;;

	h2.biSize	= sizeof&#40;BITMAPINFOHEADER&#41;;
	h2.biPlanes	= 1;
	h2.biBitCount	= 24;
	h2.biCompression 	= 0;
	h2.biWidth	= pw;
	h2.biHeight	= ph;
	h2.biSizeImage	= &#40;&#40;24*pw + padding&#41;*ph&#41;/8;
	h2.biXPelsPerMeter	= 0xEC4;
	h2.biYPelsPerMeter	= 0xEC4;
	h2.biClrUsed		= 0;
	h2.biClrImportant	= 0;

	sceIoWrite&#40;fd, &h1, sizeof&#40;BITMAPFILEHEADER&#41;&#41;;
	sceIoWrite&#40;fd, &h2, sizeof&#40;BITMAPINFOHEADER&#41;&#41;;
	
	SceUID mem = sceKernelAllocPartitionMemory&#40;1, "block", 0, &#40;3*pw + padding&#41;*sizeof&#40;unsigned char&#41;, NULL&#41;;
	unsigned char *buf = &#40;unsigned char*&#41;sceKernelGetBlockHeadAddr&#40;mem&#41;;

	for&#40;x = 0; x < padding; x++&#41; buf&#91;3*pw + x&#93; = 0;

	for&#40;y = &#40;ph-1&#41;; y >= 0; y--&#41;&#123;
		int i;
		for&#40;i = 0, x = 0; x < pw; x++&#41;&#123;
			unsigned int color, offset = x + y*bufferwidth;
			unsigned char r = 0, g = 0, b = 0;
			if&#40;imageSize&#41; offset *= 2;

			switch &#40;pixelformat&#41; &#123;
				case 0&#58;	// 16-bit RGB 5&#58;6&#58;5
					color = vram16&#91;offset&#93;;
					vram16&#91;offset&#93; ^= 0xFFFF;
					r = &#40;color & 0x1f&#41; << 3; 
					g = &#40;&#40;color >> 5&#41; & 0x3f&#41; << 2 ;
					b = &#40;&#40;color >> 11&#41; & 0x1f&#41; << 3 ;
					break;
				case 1&#58;// 16-bit RGBA 5&#58;5&#58;5&#58;1
					color = vram16&#91;offset&#93;;
					vram16&#91;offset&#93; ^= 0x7FFF;	
					r = &#40;color & 0x1f&#41; << 3; 
					g = &#40;&#40;color >> 5&#41; & 0x1f&#41; << 3 ;
					b = &#40;&#40;color >> 10&#41; & 0x1f&#41; << 3 ;
					break;
				case 2&#58;// 16-bit RGBA 4&#58;4&#58;4&#58;4
					color = vram16&#91;offset&#93;;
					vram16&#91;offset&#93; ^= 0x0FFF;	
					r = &#40;color & 0xf&#41; << 4; 
					g = &#40;&#40;color >> 4&#41; & 0xf&#41; << 4 ;
					b = &#40;&#40;color >> 8&#41; & 0xf&#41; << 4 ;
					break;
				case 3&#58;// 32-bit RGBA 8&#58;8&#58;8&#58;8
					color = vram32&#91;offset&#93;;
					vram32&#91;offset&#93; ^= 0x00FFFFFF;	
					r = color & 0xff; 
					g = &#40;color >> 8&#41; & 0xff;
					b = &#40;color >> 16&#41; & 0xff;
					break;
			&#125;
			buf&#91;i++&#93; = b;
			buf&#91;i++&#93; = g;
			buf&#91;i++&#93; = r;
		&#125;
		sceIoWrite&#40;fd, buf, 3*pw + padding&#41;;
	&#125;
	sceKernelFreePartitionMemory&#40;mem&#41;;
	sceIoClose&#40;fd&#41;;

	for&#40;y = 0; y < ph; y++&#41;&#123;
		int i;
		for&#40;i = 0, x = 0; x < pw; x++&#41;&#123;
			unsigned int offset = x + y*bufferwidth;
			if&#40;imageSize&#41; offset *= 2;

			switch &#40;pixelformat&#41; &#123;
				case 0&#58;	// 16-bit RGB 5&#58;6&#58;5
					vram16&#91;offset&#93; ^= 0xFFFF;	
					break;
				case 1&#58;// 16-bit RGBA 5&#58;5&#58;5&#58;1
					vram16&#91;offset&#93; ^= 0x7FFF;	
					break;
				case 2&#58;// 16-bit RGBA 4&#58;4&#58;4&#58;4
					vram16&#91;offset&#93; ^= 0x0FFF;
					break;
				case 3&#58;// 32-bit RGBA 8&#58;8&#58;8&#58;8
					vram32&#91;offset&#93; ^= 0x00FFFFFF;
					break;
			&#125;
		&#125;
	&#125;
&#125;

void screenshot&#40;void&#41; &#123;

	int fd, compteur = 0, size = 0;

	nkThreadSuspend&#40;sceKernelGetThreadId&#40;&#41;&#41;;

	while&#40;1&#41;&#123;
		sprintf&#40;file, "ms0&#58;/PICTURE/SCREEN/picture%03d.bmp", compteur&#41;;
		fd = sceIoOpen&#40;file, PSP_O_CREAT|PSP_O_WRONLY|PSP_O_TRUNC, 0777&#41;;
		screenshot_BMP&#40;file, size&#41;;
		if&#40;fd < 0&#41;&#123;
		    sceIoClose&#40;fd&#41;; 
			break;
		&#125;
		compteur++;
		sceIoClose&#40;fd&#41;;
	&#125;

	nkThreadResume&#40;sceKernelGetThreadId&#40;&#41;&#41;;
&#125;
here the screenshot.h:

Code: Select all

#ifndef __SCREENSHOT_H__
#define __SCREENSHOT_H__

#define MAX_THREAD	64

int nkLoad&#40;&#41;;
int nkThreadSuspend&#40;SceUID thId&#41;;
int nkThreadResume&#40;SceUID thId&#41;;
void screenshot_BMP&#40;const char* filename, char imageSize&#41;;
void screenshot&#40;void&#41;;

char file&#91;64&#93;;

#endif
And here the makefile:

Code: Select all

TARGET = screenshot
OBJS = main.o screenshot.o


CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $&#40;CFLAGS&#41; -fno-exceptions
ASFLAGS = $&#40;CFLAGS&#41;

LIBS = -lpsppower
INCDIR = 
LIBDIR = 
LDFLAGS =

USE_KERNEL_LIBC = 1
USE_KERNEL_LIBS = 1

BUILD_PRX = 1

PSPSDK=$&#40;shell psp-config --pspsdk-path&#41;
include $&#40;PSPSDK&#41;/lib/build_prx.mak
I'm apologize for my bad English because I am French :)

.::pspflashsystem::.
pspflashsystem
Posts: 31
Joined: Mon Mar 24, 2008 12:31 am

Post by pspflashsystem »

Any idea??
I'm apologize for my bad English because I am French :)

.::pspflashsystem::.
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

You open a file and then close it without ever writing to that fd.
That will truncate at zero. It seems you are missing a basic understanding of how file I/O works.
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

You open the file, then call screenshot_BMP(). However, the screenshot_BMP function tries to open the file which is already open. Instead of passing the name, you should pass the handle you just opened.
Post Reply