⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 graphics.c

📁 header files for programming PSP
💻 C
字号:
#include <stdlib.h>#include <malloc.h>#include <pspdisplay.h>#include <psputils.h>#include <png.h>#include <pspgu.h>#include "graphics.h"#include "framebuffer.h"#define IS_ALPHA(color) (((color)&0xff000000)==0xff000000?0:1)#define FRAMEBUFFER_SIZE (PSP_LINE_SIZE*SCREEN_HEIGHT*4)#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))typedef struct{	unsigned short u, v;	short x, y, z;} Vertex;extern u8 msx[];unsigned int __attribute__((aligned(16))) list[262144];static int dispBufferNumber;static int initialized = 0;static int getNextPower2(int width){	int b = width;	int n;	for (n = 0; b != 0; n++) b >>= 1;	b = 1 << n;	if (b == 2 * width) b >>= 1;	return b;}Color* getVramDrawBuffer(){	Color* vram = (Color*) g_vram_base;	if (dispBufferNumber == 0) vram += FRAMEBUFFER_SIZE / sizeof(Color);	return vram;}Color* getVramDisplayBuffer(){	Color* vram = (Color*) g_vram_base;	if (dispBufferNumber == 1) vram += FRAMEBUFFER_SIZE / sizeof(Color);	return vram;}void user_warning_fn(png_structp png_ptr, png_const_charp warning_msg){}Image* loadImage(const char* filename){	png_structp png_ptr;	png_infop info_ptr;	unsigned int sig_read = 0;	png_uint_32 width, height;	int bit_depth, color_type, interlace_type, x, y;	u32* line;	FILE *fp;	Image* image = (Image*) malloc(sizeof(Image));	if (!image) return NULL;	if ((fp = fopen(filename, "rb")) == NULL) return NULL;	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);	if (png_ptr == NULL) {		free(image);		fclose(fp);		return NULL;;	}	png_set_error_fn(png_ptr, (png_voidp) NULL, (png_error_ptr) NULL, user_warning_fn);	info_ptr = png_create_info_struct(png_ptr);	if (info_ptr == NULL) {		free(image);		fclose(fp);		png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);		return NULL;	}	png_init_io(png_ptr, fp);	png_set_sig_bytes(png_ptr, sig_read);	png_read_info(png_ptr, info_ptr);	png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, int_p_NULL, int_p_NULL);	if (width > 512 || height > 512) {		free(image);		fclose(fp);		png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);		return NULL;	}	image->imageWidth = width;	image->imageHeight = height;	image->textureWidth = getNextPower2(width);	image->textureHeight = getNextPower2(height);	png_set_strip_16(png_ptr);	png_set_packing(png_ptr);	if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr);	if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr);	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr);	png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);	image->data = (Color*) memalign(16, image->textureWidth * image->textureHeight * sizeof(Color));	if (!image->data) {		free(image);		fclose(fp);		png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);		return NULL;	}	line = (u32*) malloc(width * 4);	if (!line) {		free(image->data);		free(image);		fclose(fp);		png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);		return NULL;	}	for (y = 0; y < height; y++) {		png_read_row(png_ptr, (u8*) line, png_bytep_NULL);		for (x = 0; x < width; x++) {			u32 color = line[x];			image->data[x + y * image->textureWidth] =  color;		}	}	free(line);	png_read_end(png_ptr, info_ptr);	png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);	fclose(fp);	return image;}void blitImageToImage(int sx, int sy, int width, int height, Image* source, int dx, int dy, Image* destination){	Color* destinationData = &destination->data[destination->textureWidth * dy + dx];	int destinationSkipX = destination->textureWidth - width;	Color* sourceData = &source->data[source->textureWidth * sy + sx];	int sourceSkipX = source->textureWidth - width;	int x, y;	for (y = 0; y < height; y++, destinationData += destinationSkipX, sourceData += sourceSkipX) {		for (x = 0; x < width; x++, destinationData++, sourceData++) {			*destinationData = *sourceData;		}	}}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);}void blitAlphaImageToImage(int sx, int sy, int width, int height, Image* source, int dx, int dy, Image* destination){	// TODO Blend!	Color* destinationData = &destination->data[destination->textureWidth * dy + dx];	int destinationSkipX = destination->textureWidth - width;	Color* sourceData = &source->data[source->textureWidth * sy + sx];	int sourceSkipX = source->textureWidth - width;	int x, y;	for (y = 0; y < height; y++, destinationData += destinationSkipX, sourceData += sourceSkipX) {		for (x = 0; x < width; x++, destinationData++, sourceData++) {			Color color = *sourceData;			if (!IS_ALPHA(color)) *destinationData = color;		}	}}void blitAlphaImageToScreen(int sx, int sy, int width, int height, Image* source, int dx, int dy){	if (!initialized) return;	sceKernelDcacheWritebackInvalidateAll();	guStart();	sceGuTexImage(0, source->textureWidth, source->textureHeight, source->textureWidth, (void*) source->data);	float u = 1.0f / ((float)source->textureWidth);	float v = 1.0f / ((float)source->textureHeight);	sceGuTexScale(u, v);		int j = 0;	while (j < width) {		Vertex* vertices = (Vertex*) sceGuGetMemory(2 * sizeof(Vertex));		int sliceWidth = 64;		if (j + sliceWidth > width) sliceWidth = width - j;		vertices[0].u = sx + j;		vertices[0].v = sy;		vertices[0].x = dx + j;		vertices[0].y = dy;		vertices[0].z = 0;		vertices[1].u = sx + j + sliceWidth;		vertices[1].v = sy + height;		vertices[1].x = dx + j + sliceWidth;		vertices[1].y = dy + height;		vertices[1].z = 0;		sceGuDrawArray(GU_SPRITES, GU_TEXTURE_16BIT | GU_VERTEX_16BIT | GU_TRANSFORM_2D, 2, 0, vertices);		j += sliceWidth;	}		sceGuFinish();	sceGuSync(0, 0);}Image* createImage(int width, int height){	Image* image = (Image*) malloc(sizeof(Image));	if (!image) return NULL;	image->imageWidth = width;	image->imageHeight = height;	image->textureWidth = getNextPower2(width);	image->textureHeight = getNextPower2(height);	image->data = (Color*) memalign(16, image->textureWidth * image->textureHeight * sizeof(Color));	if (!image->data) return NULL;	memset(image->data, 0, image->textureWidth * image->textureHeight * sizeof(Color));	return image;}void freeImage(Image* image){	free(image->data);	free(image);}void clearImage(Color color, Image* image){	int i;	int size = image->textureWidth * image->textureHeight;	Color* data = image->data;	for (i = 0; i < size; i++, data++) *data = color;}void clearScreen(Color color){	if (!initialized) return;	guStart();	sceGuClearDepth(0);	sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT);	sceGuFinish();	sceGuSync(0, 0);}void fillImageRect(Color color, int x0, int y0, int width, int height, Image* image){	int skipX = image->textureWidth - width;	int x, y;	Color* data = image->data + x0 + y0 * image->textureWidth;	for (y = 0; y < height; y++, data += skipX) {		for (x = 0; x < width; x++, data++) *data = color;	}}void fillScreenRect(Color color, int x0, int y0, int width, int height){	if (!initialized) return;	int skipX = PSP_LINE_SIZE - width;	int x, y;	Color* data = getVramDrawBuffer() + x0 + y0 * PSP_LINE_SIZE;	for (y = 0; y < height; y++, data += skipX) {		for (x = 0; x < width; x++, data++) *data = color;	}}void putPixelScreen(Color color, int x, int y){	Color* vram = getVramDrawBuffer();	vram[PSP_LINE_SIZE * y + x] = color;}void putPixelImage(Color color, int x, int y, Image* image){	image->data[x + y * image->textureWidth] = color;}Color getPixelScreen(int x, int y){	Color* vram = getVramDrawBuffer();	return vram[PSP_LINE_SIZE * y + x];}Color getPixelImage(int x, int y, Image* image){	return image->data[x + y * image->textureWidth];}void printTextScreen(int x, int y, const char* text, u32 color){	int c, i, j, l;	u8 *font;	Color *vram_ptr;	Color *vram;		if (!initialized) return;	for (c = 0; c < strlen(text); c++) {		if (x < 0 || x + 8 > SCREEN_WIDTH || y < 0 || y + 8 > SCREEN_HEIGHT) break;		char ch = text[c];		vram = getVramDrawBuffer() + x + y * PSP_LINE_SIZE;				font = &msx[ (int)ch * 8];		for (i = l = 0; i < 8; i++, l += 8, font++) {			vram_ptr  = vram;			for (j = 0; j < 8; j++) {				if ((*font & (128 >> j))) *vram_ptr = color;				vram_ptr++;			}			vram += PSP_LINE_SIZE;		}		x += 8;	}}void printTextImage(int x, int y, const char* text, u32 color, Image* image){	int c, i, j, l;	u8 *font;	Color *data_ptr;	Color *data;		if (!initialized) return;	for (c = 0; c < strlen(text); c++) {		if (x < 0 || x + 8 > image->imageWidth || y < 0 || y + 8 > image->imageHeight) break;		char ch = text[c];		data = image->data + x + y * image->textureWidth;				font = &msx[ (int)ch * 8];		for (i = l = 0; i < 8; i++, l += 8, font++) {			data_ptr  = data;			for (j = 0; j < 8; j++) {				if ((*font & (128 >> j))) *data_ptr = color;				data_ptr++;			}			data += image->textureWidth;		}		x += 8;	}}void saveImage(const char* filename, Color* data, int width, int height, int lineSize, int saveAlpha){	png_structp png_ptr;	png_infop info_ptr;	FILE* fp;	int i, x, y;	u8* line;		if ((fp = fopen(filename, "wb")) == NULL) return;	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);	if (!png_ptr) return;	info_ptr = png_create_info_struct(png_ptr);	if (!info_ptr) {		png_destroy_write_struct(&png_ptr, (png_infopp)NULL);		return;	}	png_init_io(png_ptr, fp);	png_set_IHDR(png_ptr, info_ptr, width, height, 8,		saveAlpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB,		PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);	png_write_info(png_ptr, info_ptr);	line = (u8*) malloc(width * (saveAlpha ? 4 : 3));	for (y = 0; y < height; y++) {		for (i = 0, x = 0; x < width; x++) {			Color color = data[x + y * lineSize];			u8 r = color & 0xff; 			u8 g = (color >> 8) & 0xff;			u8 b = (color >> 16) & 0xff;			u8 a = saveAlpha ? (color >> 24) & 0xff : 0xff;			line[i++] = r;			line[i++] = g;			line[i++] = b;			if (saveAlpha) line[i++] = a;		}		png_write_row(png_ptr, line);	}	free(line);	png_write_end(png_ptr, info_ptr);	png_destroy_write_struct(&png_ptr, (png_infopp)NULL);	fclose(fp);}void flipScreen(){	if (!initialized) return;	sceGuSwapBuffers();	dispBufferNumber ^= 1;}static void drawLine(int x0, int y0, int x1, int y1, int color, Color* destination, int width){	int dy = y1 - y0;	int dx = x1 - x0;	int stepx, stepy;		if (dy < 0) { dy = -dy;  stepy = -width; } else { stepy = width; }	if (dx < 0) { dx = -dx;  stepx = -1; } else { stepx = 1; }	dy <<= 1;	dx <<= 1;		y0 *= width;	y1 *= width;	destination[x0+y0] = color;	if (dx > dy) {		int fraction = dy - (dx >> 1);		while (x0 != x1) {			if (fraction >= 0) {				y0 += stepy;				fraction -= dx;			}			x0 += stepx;			fraction += dy;			destination[x0+y0] = color;		}	} else {		int fraction = dx - (dy >> 1);		while (y0 != y1) {			if (fraction >= 0) {				x0 += stepx;				fraction -= dy;			}			y0 += stepy;			fraction += dx;			destination[x0+y0] = color;		}	}}void drawLineScreen(int x0, int y0, int x1, int y1, Color color){	drawLine(x0, y0, x1, y1, color, getVramDrawBuffer(), PSP_LINE_SIZE);}void drawLineImage(int x0, int y0, int x1, int y1, Color color, Image* image){	drawLine(x0, y0, x1, y1, color, image->data, image->textureWidth);}#define BUF_WIDTH (512)#define SCR_WIDTH (480)#define SCR_HEIGHT (272)#define PIXEL_SIZE (4) /* change this if you change to another screenmode */#define FRAME_SIZE (BUF_WIDTH * SCR_HEIGHT * PIXEL_SIZE)#define ZBUF_SIZE (BUF_WIDTH SCR_HEIGHT * 2) /* zbuffer seems to be 16-bit? */void initGraphics(){	dispBufferNumber = 0;	sceGuInit();	guStart();	sceGuDrawBuffer(GU_PSM_8888, (void*)FRAMEBUFFER_SIZE, PSP_LINE_SIZE);	sceGuDispBuffer(SCREEN_WIDTH, SCREEN_HEIGHT, (void*)0, PSP_LINE_SIZE);	sceGuClear(GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT);	sceGuDepthBuffer((void*) (FRAMEBUFFER_SIZE*2), PSP_LINE_SIZE);	sceGuOffset(2048 - (SCREEN_WIDTH / 2), 2048 - (SCREEN_HEIGHT / 2));	sceGuViewport(2048, 2048, SCREEN_WIDTH, SCREEN_HEIGHT);	sceGuDepthRange(0xc350, 0x2710);	sceGuScissor(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);	sceGuEnable(GU_SCISSOR_TEST);	sceGuAlphaFunc(GU_GREATER, 0, 0xff);	sceGuEnable(GU_ALPHA_TEST);	sceGuDepthFunc(GU_GEQUAL);	sceGuEnable(GU_DEPTH_TEST);	sceGuFrontFace(GU_CW);	sceGuShadeModel(GU_SMOOTH);	sceGuEnable(GU_CULL_FACE);	sceGuEnable(GU_TEXTURE_2D);	sceGuEnable(GU_CLIP_PLANES);	sceGuTexMode(GU_PSM_8888, 0, 0, 0);	sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);	sceGuTexFilter(GU_NEAREST, GU_NEAREST);	sceGuAmbientColor(0xffffffff);	sceGuEnable(GU_BLEND);	sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0);	sceGuFinish();	sceGuSync(0, 0);	sceDisplayWaitVblankStart();	sceGuDisplay(GU_TRUE);	initialized = 1;}void disableGraphics(){	initialized = 0;}void guStart(){	sceGuStart(GU_DIRECT, list);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -