aboutsummaryrefslogtreecommitdiff
path: root/sources/TZR_DirectResourceLoad.c
blob: 6bbbc5cbba761c0e1bedc409f8a6b3dbddb71200 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include "TZR_resource.h"
#include "TZR_globals.h"
#include "sdl_error.h"
#include <SDL2/SDL_mixer.h>
#include <SDL2/SDL_render.h>
#include <SDL2/SDL_rwops.h>
#include <string.h>

#ifdef TZR_STB_IMAGE
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

SDL_Surface *
stbi_load_surface(void *src, int size)
{
	int width, height, chans;
	void *const data = stbi_load_from_memory(src, size, &width, &height,
	                                         &chans, 4);
	const int pitch = (width * 4 + 3) & ~3;

	if (data == NULL) {
		fprintf(stderr, "stbi: %s\n", stbi_failure_reason());
		return NULL;
	}

	if (chans != 4) {
		fprintf(stderr, "TZR only supports RGBA images\n");
		free(data);
		return NULL;
	}

#if SDL_BYTEORDER == SDL_LIL_ENDIAN
	const int rmask = 0x000000ff;
	const int gmask = 0x0000ff00;
	const int bmask = 0x00ff0000;
	const int amask = 0xff000000 * (chans == 4);
#else
	const int s = 8 * (chans != 4);
	const int rmask = 0xff000000 >> s;
	const int gmask = 0x00ff0000 >> s;
	const int bmask = 0x0000ff00 >> s;
	const int amask = 0x000000ff >> s;
#endif

	SDL_Surface *const surf = SDL_CreateRGBSurfaceFrom(data, width, height, chans * 8, pitch, rmask, gmask, bmask, amask);
	if (surf == NULL) {
		sdl_error(0);
		free(data);
		return NULL;
	}

	return surf;
}
#endif

int
TZR_DirectResourceLoad(TZR_Resource *res, const void *data, int size)
{
	switch (res->type) {
	case TZR_RES_RAW:
		res->raw.size = size;
		res->raw.data = malloc(size);
		if (res->raw.data == NULL) {
			perror("TZR_DirectResourceLoad");
			return -1;
		}
		memcpy(res->raw.data, data, size);
		break;
	case TZR_RES_IMAGE: {
#ifdef TZR_STB_IMAGE
		SDL_Surface *const surf = stbi_load_surface((void*)data, size);
		if (surf == NULL)
			return -1;
#else
		SDL_RWops *const rw = SDL_RWFromConstMem(data, size);
		if (rw == NULL)
			return sdl_error(-1);
		SDL_Surface *const surf = SDL_LoadBMP_RW(rw, 1);
		if (surf == NULL)
			return sdl_error(-1);
#endif
		SDL_Texture *const tex =
		    SDL_CreateTextureFromSurface(___tzr_renderer, surf);
		SDL_FreeSurface(surf);
		if (tex == NULL)
			return sdl_error(-1);
		if (SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND) < 0) {
			SDL_DestroyTexture(tex);
			return sdl_error(-1);
		}
		if (SDL_QueryTexture(tex, NULL, NULL,
		                     &res->image.width, &res->image.height)) {
			SDL_DestroyTexture(tex);
			return sdl_error(-1);
		}
		res->image.ptr = tex;
	} break;
	case TZR_RES_SOUND: {
		if (!___tzr_config.mixer) {
			SDL_Log("audio mixer disabled, skip loading");
			return -1;
		}
		SDL_RWops *const rw = SDL_RWFromConstMem(data, size);
		if (rw == NULL)
			return sdl_error(-1);
		Mix_Chunk *const chunk = Mix_LoadWAV_RW(rw, 0);
		SDL_RWclose(rw);
		if (chunk == NULL)
			return sdl_error(-1);
		res->sound.ptr = chunk;
	} break;
	default:
		fprintf(stderr, "invalid type\n");
		return -1;
	}
	return 0;
}