mirror of
				https://github.com/ctruLua/ctruLua.git
				synced 2025-10-29 01:09:30 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			171 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			171 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "sfil.h"
 | |
| #include <stdio.h>
 | |
| #include <string.h>
 | |
| #include <stdlib.h>
 | |
| 
 | |
| #define BMP_SIGNATURE (0x4D42)
 | |
| 
 | |
| typedef struct {
 | |
| 	unsigned short	bfType;
 | |
| 	unsigned int	bfSize;
 | |
| 	unsigned short	bfReserved1;
 | |
| 	unsigned short	bfReserved2;
 | |
| 	unsigned int	bfOffBits;
 | |
| }__attribute__((packed)) BITMAPFILEHEADER;
 | |
| 
 | |
| 
 | |
| typedef struct {
 | |
| 	unsigned int	biSize;
 | |
| 	unsigned int	biWidth;
 | |
| 	unsigned int	biHeight;
 | |
| 	unsigned short	biPlanes;
 | |
| 	unsigned short	biBitCount;
 | |
| 	unsigned int	biCompression;
 | |
| 	unsigned int	biSizeImage;
 | |
| 	unsigned int	biXPelsPerMeter;
 | |
| 	unsigned int	biYPelsPerMeter;
 | |
| 	unsigned int	biClrUsed;
 | |
| 	unsigned int	biClrImportant;
 | |
| }__attribute__((packed)) BITMAPINFOHEADER;
 | |
| 
 | |
| 
 | |
| static sf2d_texture *_sfil_load_BMP_generic(
 | |
| 	BITMAPFILEHEADER *bmp_fh,
 | |
| 	BITMAPINFOHEADER *bmp_ih,
 | |
| 	void *user_data,
 | |
| 	void (*seek_fn)(void *user_data, unsigned int offset),
 | |
| 	void (*read_fn)(void *user_data, void *buffer, unsigned int length),
 | |
| 	sf2d_place place)
 | |
| {
 | |
| 	unsigned int row_size = bmp_ih->biWidth * (bmp_ih->biBitCount/8);
 | |
| 	if (row_size%4 != 0) {
 | |
| 		row_size += 4-(row_size%4);
 | |
| 	}
 | |
| 
 | |
| 	sf2d_texture *texture = sf2d_create_texture(bmp_ih->biWidth, bmp_ih->biHeight,
 | |
| 		GPU_RGBA8, place);
 | |
| 
 | |
| 	seek_fn(user_data, bmp_fh->bfOffBits);
 | |
| 
 | |
| 	int stride = texture->pow2_w * 4;
 | |
| 
 | |
| 	void *buffer = malloc(row_size);
 | |
| 	unsigned int *tex_ptr;
 | |
| 	unsigned int color;
 | |
| 	int i, x, y;
 | |
| 
 | |
| 	for (i = 0; i < bmp_ih->biHeight; i++) {
 | |
| 
 | |
| 		read_fn(user_data, buffer, row_size);
 | |
| 
 | |
| 		y = bmp_ih->biHeight - 1 - i;
 | |
| 		tex_ptr = (unsigned int *)(texture->data + y*stride);
 | |
| 
 | |
| 		for (x = 0; x < bmp_ih->biWidth; x++) {
 | |
| 
 | |
| 			if (bmp_ih->biBitCount == 32) {		//ABGR8888
 | |
| 				color = *(unsigned int *)(buffer + x*4);
 | |
| 				*tex_ptr = (color&0xFF)<<24 | ((color>>8)&0xFF)<<16 |
 | |
| 					((color>>16)&0xFF)<<8 | (color>>24);
 | |
| 
 | |
| 			} else if (bmp_ih->biBitCount == 24) {	//BGR888
 | |
| 				unsigned char *address = buffer + x*3;
 | |
| 				*tex_ptr = (*address)<<16 | (*(address+1))<<8 |
 | |
| 					(*(address+2)) | (0xFF<<24);
 | |
| 
 | |
| 			} else if (bmp_ih->biBitCount == 16) {	//BGR565
 | |
| 				color = *(unsigned short *)(buffer + x*2);
 | |
| 				unsigned char r = (color       & 0x1F)  *((float)255/31);
 | |
| 				unsigned char g = ((color>>5)  & 0x3F)  *((float)255/63);
 | |
| 				unsigned char b = ((color>>11) & 0x1F)  *((float)255/31);
 | |
| 				*tex_ptr = ((r<<16) | (g<<8) | b | (0xFF<<24));
 | |
| 			}
 | |
| 
 | |
| 			tex_ptr++;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	free(buffer);
 | |
| 
 | |
| 	sf2d_texture_tile32(texture);
 | |
| 	return texture;
 | |
| }
 | |
| 
 | |
| static void _sfil_read_bmp_file_seek_fn(void *user_data, unsigned int offset)
 | |
| {
 | |
| 	fseek((FILE *)user_data, offset, SEEK_SET);
 | |
| }
 | |
| 
 | |
| static void _sfil_read_bmp_file_read_fn(void *user_data, void *buffer, unsigned int length)
 | |
| {
 | |
| 	fread(buffer, 1, length, (FILE *)user_data);
 | |
| }
 | |
| 
 | |
| static void _sfil_read_bmp_buffer_seek_fn(void *user_data, unsigned int offset)
 | |
| {
 | |
| 	*(unsigned int *)user_data += offset;
 | |
| }
 | |
| 
 | |
| static void _sfil_read_bmp_buffer_read_fn(void *user_data, void *buffer, unsigned int length)
 | |
| {
 | |
| 	memcpy(buffer, (void *)*(unsigned int *)user_data, length);
 | |
| 	*(unsigned int *)user_data += length;
 | |
| }
 | |
| 
 | |
| sf2d_texture *sfil_load_BMP_file(const char *filename, sf2d_place place)
 | |
| {
 | |
| 	FILE *fp;
 | |
| 	if ((fp = fopen(filename, "rb")) == NULL) {
 | |
| 		goto exit_error;
 | |
| 	}
 | |
| 
 | |
| 	BITMAPFILEHEADER bmp_fh;
 | |
| 	fread((void *)&bmp_fh, 1, sizeof(BITMAPFILEHEADER), fp);
 | |
| 	if (bmp_fh.bfType != BMP_SIGNATURE) {
 | |
| 		goto exit_close;
 | |
| 	}
 | |
| 
 | |
| 	BITMAPINFOHEADER bmp_ih;
 | |
| 	fread((void *)&bmp_ih, 1, sizeof(BITMAPINFOHEADER), fp);
 | |
| 
 | |
| 	sf2d_texture *texture = _sfil_load_BMP_generic(&bmp_fh,
 | |
| 		&bmp_ih,
 | |
| 		(void *)&fp,
 | |
| 		_sfil_read_bmp_file_seek_fn,
 | |
| 		_sfil_read_bmp_file_read_fn,
 | |
| 		place);
 | |
| 
 | |
| 	fclose(fp);
 | |
| 	return texture;
 | |
| 
 | |
| exit_close:
 | |
| 	fclose(fp);
 | |
| exit_error:
 | |
| 	return NULL;
 | |
| }
 | |
| 
 | |
| 
 | |
| sf2d_texture *sfil_load_BMP_buffer(const void *buffer, sf2d_place place)
 | |
| {
 | |
| 	BITMAPFILEHEADER bmp_fh;
 | |
| 	memcpy(&bmp_fh, buffer, sizeof(BITMAPFILEHEADER));
 | |
| 	if (bmp_fh.bfType != BMP_SIGNATURE) {
 | |
| 		goto exit_error;
 | |
| 	}
 | |
| 
 | |
| 	BITMAPINFOHEADER bmp_ih;
 | |
| 	memcpy(&bmp_ih, buffer + sizeof(BITMAPFILEHEADER), sizeof(BITMAPINFOHEADER));
 | |
| 
 | |
| 	unsigned int buffer_address = (unsigned int)buffer;
 | |
| 
 | |
| 	sf2d_texture *texture = _sfil_load_BMP_generic(&bmp_fh,
 | |
| 		&bmp_ih,
 | |
| 		(void *)&buffer_address,
 | |
| 		_sfil_read_bmp_buffer_seek_fn,
 | |
| 		_sfil_read_bmp_buffer_read_fn,
 | |
| 		place);
 | |
| 
 | |
| 	return texture;
 | |
| exit_error:
 | |
| 	return NULL;
 | |
| }
 | 
