#include "TZR_resource.h" #include "TZR_globals.h" #include "sdl_error.h" #include #include #include #include #include #include #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) { TZR_Log("stbi: %s", stbi_failure_reason()); return NULL; } if (chans != 4) { TZR_Log("TZR only supports RGBA images"); 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) { TZR_Log("%s", strerror(errno)); 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 /* TZR_STB_IMAGE */ SDL_Texture *const tex = SDL_CreateTextureFromSurface(___tzr_renderer, surf); SDL_FreeSurface(surf); if (tex == NULL) return sdl_error(-1); #ifdef TZR_OPENGL if (___tzr_config.mipmaps) { TZR_Log("generating mipmaps"); SDL_GL_BindTexture(tex, NULL, NULL); glGenerateMipmap(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -.5f); SDL_GL_UnbindTexture(tex); } #endif /* TZR_OPENGL */ 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) { TZR_Log("audio mixer disabled, skip loading"); return -1; } #ifdef TZR_SOLOUD Wav *wav = Wav_create(); if (wav == NULL) { TZR_Log("Wav_create failed"); return -1; } if (Wav_loadMemEx(wav, data, size, true, false)) { TZR_Log("Wav_loadMem failed"); Wav_destroy(wav); return -1; } res->sound.ptr = wav; #else /* TZR_SOLOUD */ 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; #endif } break; default: TZR_Log("invalid type"); return -1; } return 0; }