2020-01-01 21:29:24 +01:00
|
|
|
#include "GraphicsResources.h"
|
2020-07-19 21:43:29 +02:00
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
2020-07-19 21:43:29 +02:00
|
|
|
#include "FileSystemUtils.h"
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
// Used to load PNG data
|
|
|
|
extern "C"
|
|
|
|
{
|
|
|
|
extern unsigned lodepng_decode24(
|
|
|
|
unsigned char** out,
|
|
|
|
unsigned* w,
|
|
|
|
unsigned* h,
|
|
|
|
const unsigned char* in,
|
|
|
|
size_t insize
|
|
|
|
);
|
|
|
|
extern unsigned lodepng_decode32(
|
|
|
|
unsigned char** out,
|
|
|
|
unsigned* w,
|
|
|
|
unsigned* h,
|
|
|
|
const unsigned char* in,
|
|
|
|
size_t insize
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-01-10 18:14:37 +01:00
|
|
|
static SDL_Surface* LoadImage(const char *filename, bool noBlend = true, bool noAlpha = false)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
//Temporary storage for the image that's loaded
|
|
|
|
SDL_Surface* loadedImage = NULL;
|
|
|
|
//The optimized image that will be used
|
|
|
|
SDL_Surface* optimizedImage = NULL;
|
|
|
|
|
|
|
|
unsigned char *data;
|
|
|
|
unsigned int width, height;
|
|
|
|
|
Transfer param init responsibility to loadFileToMemory
So, the codebase was kind of undecided about who is responsible for
initializing the parameters passed to FILESYSTEM_loadFileToMemory() - is
it the caller? Is it FILESYSTEM_loadFileToMemory()? Sometimes callers
would initialize one variable but not the other, and it was always a
toss-up whether or not FILESYSTEM_loadFileToMemory() would end up
initializing everything in the end.
All of this is to say that the game dereferences an uninitialized
pointer if it can't load a sound effect. Which is bad. Now, I could
either fix that single case, or fix every case. Judging by the title of
this commit, you can infer that I decided to fix every case - fixing
every case means not just all cases that currently exist (which, as far
as I know, is only the sound effect one), but all cases that could exist
in the future.
So, FILESYSTEM_loadFileToMemory() is now guaranteed to initialize its
parameters even if the file fails to be loaded. This is better than
passing the responsibility to the caller anyway, because if the caller
initialized it, then that would be wasted work if the file succeeds
anyway because FILESYSTEM_loadFileToMemory() will overwrite it, and if
the file fails to load, well that's when the variables get initialized
anyway.
2021-04-18 19:35:36 +02:00
|
|
|
unsigned char *fileIn;
|
|
|
|
size_t length;
|
2021-04-05 09:54:32 +02:00
|
|
|
FILESYSTEM_loadAssetToMemory(filename, &fileIn, &length, false);
|
2021-04-18 19:58:28 +02:00
|
|
|
if (fileIn == NULL)
|
|
|
|
{
|
|
|
|
SDL_assert(0 && "Image file missing!");
|
|
|
|
return NULL;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
if (noAlpha)
|
|
|
|
{
|
|
|
|
lodepng_decode24(&data, &width, &height, fileIn, length);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lodepng_decode32(&data, &width, &height, fileIn, length);
|
|
|
|
}
|
|
|
|
FILESYSTEM_freeMemory(&fileIn);
|
|
|
|
|
|
|
|
loadedImage = SDL_CreateRGBSurfaceFrom(
|
|
|
|
data,
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
noAlpha ? 24 : 32,
|
|
|
|
width * (noAlpha ? 3 : 4),
|
|
|
|
0x000000FF,
|
|
|
|
0x0000FF00,
|
|
|
|
0x00FF0000,
|
|
|
|
noAlpha ? 0x00000000 : 0xFF000000
|
|
|
|
);
|
|
|
|
|
|
|
|
if (loadedImage != NULL)
|
|
|
|
{
|
|
|
|
optimizedImage = SDL_ConvertSurfaceFormat(
|
|
|
|
loadedImage,
|
|
|
|
SDL_PIXELFORMAT_ABGR8888, // FIXME: Format? -flibit
|
|
|
|
0
|
|
|
|
);
|
|
|
|
SDL_FreeSurface( loadedImage );
|
Reduce dependency on libc functions
During 2.3 development, there's been a gradual shift to using SDL stdlib
functions instead of libc functions, but there are still some libc
functions (or the same libc function but from the STL) in the code.
Well, this patch replaces all the rest of them in one fell swoop.
SDL's stdlib can replace most of these, but its SDL_min() and SDL_max()
are inadequate - they aren't really functions, they're more like macros
with a nasty penchant for double-evaluation. So I just made my own
VVV_min() and VVV_max() functions and placed them in Maths.h instead,
then replaced all the previous usages of min(), max(), std::min(),
std::max(), SDL_min(), and SDL_max() with VVV_min() and VVV_max().
Additionally, there's no SDL_isxdigit(), so I just implemented my own
VVV_isxdigit().
SDL has SDL_malloc() and SDL_free(), but they have some refcounting
built in to them, so in order to use them with LodePNG, I have to
replace the malloc() and free() that LodePNG uses. Which isn't too hard,
I did it in a new file called ThirdPartyDeps.c, and LodePNG is now
compiled with the LODEPNG_NO_COMPILE_ALLOCATORS definition.
Lastly, I also refactored the awful strcpy() and strcat() usages in
PLATFORM_migrateSaveData() to use SDL_snprintf() instead. I know save
migration is getting axed in 2.4, but it still bothers me to have
something like that in the codebase otherwise.
Without further ado, here is the full list of functions that the
codebase now uses:
- SDL_strlcpy() instead of strcpy()
- SDL_strlcat() instead of strcat()
- SDL_snprintf() instead of sprintf(), strcpy(), or strcat() (see above)
- VVV_min() instead of min(), std::min(), or SDL_min()
- VVV_max() instead of max(), std::max(), or SDL_max()
- VVV_isxdigit() instead of isxdigit()
- SDL_strcmp() instead of strcmp()
- SDL_strcasecmp() instead of strcasecmp() or Win32 strcmpi()
- SDL_strstr() instead of strstr()
- SDL_strlen() instead of strlen()
- SDL_sscanf() instead of sscanf()
- SDL_getenv() instead of getenv()
- SDL_malloc() instead of malloc() (replacing in LodePNG as well)
- SDL_free() instead of free() (replacing in LodePNG as well)
2021-01-12 01:17:45 +01:00
|
|
|
SDL_free(data);
|
2020-01-01 21:29:24 +01:00
|
|
|
if (noBlend)
|
|
|
|
{
|
|
|
|
SDL_SetSurfaceBlendMode(optimizedImage, SDL_BLENDMODE_BLEND);
|
|
|
|
}
|
|
|
|
return optimizedImage;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-01-14 07:56:19 +01:00
|
|
|
SDL_free(data);
|
2020-01-01 21:29:24 +01:00
|
|
|
fprintf(stderr,"Image not found: %s\n", filename);
|
|
|
|
SDL_assert(0 && "Image not found! See stderr.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Allow using help/graphics/music/game/key/map/obj everywhere
This commit makes `help`, `graphics`, `music`, `game`, `key`, `map`, and
`obj` essentially static global objects that can be used everywhere.
This is useful in case we ever need to add a new function in the future,
so we don't have to bother with passing a new argument in which means we
have to pass a new argument in to the function that calls that function
which means having to pass a new argument into the function that calls
THAT function, etc. which is a real headache when working on fan mods of
the source code.
Note that this changes NONE of the existing function signatures, it
merely just makes those variables accessible everywhere in the same way
`script` and `ed` are.
Also note that some classes had to be initialized after the filesystem
was initialized, but C++ would keep initializing them before the
filesystem got initialized, because I *had* to put them at the top of
`main.cpp`, or else they wouldn't be global variables.
The only way to work around this was to use entityclass's initialization
style (which I'm pretty sure entityclass of all things doesn't need to
be initialized this way), where you actually initialize the class in an
`init()` function, and so then you do `graphics.init()` after the
filesystem initialization, AFTER doing `Graphics graphics` up at the
top.
I've had to do this for `graphics` (but only because its child
GraphicsResources `grphx` needs to be initialized this way), `music`,
and `game`. I don't think this will affect anything. Other than that,
`help`, `key`, and `map` are still using the C++-intended method of
having ClassName::ClassName() functions.
2020-01-29 08:35:03 +01:00
|
|
|
void GraphicsResources::init(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
im_tiles = LoadImage("graphics/tiles.png");
|
|
|
|
im_tiles2 = LoadImage("graphics/tiles2.png");
|
|
|
|
im_tiles3 = LoadImage("graphics/tiles3.png");
|
|
|
|
im_entcolours = LoadImage("graphics/entcolours.png");
|
|
|
|
im_sprites = LoadImage("graphics/sprites.png");
|
|
|
|
im_flipsprites = LoadImage("graphics/flipsprites.png");
|
|
|
|
im_bfont = LoadImage("graphics/font.png");
|
|
|
|
im_teleporter = LoadImage("graphics/teleporter.png");
|
|
|
|
|
|
|
|
im_image0 = LoadImage("graphics/levelcomplete.png", false);
|
|
|
|
im_image1 = LoadImage("graphics/minimap.png", true, true);
|
|
|
|
im_image2 = LoadImage("graphics/covered.png", true, true);
|
|
|
|
im_image3 = LoadImage("graphics/elephant.png");
|
|
|
|
im_image4 = LoadImage("graphics/gamecomplete.png", false);
|
|
|
|
im_image5 = LoadImage("graphics/fliplevelcomplete.png", false);
|
|
|
|
im_image6 = LoadImage("graphics/flipgamecomplete.png", false);
|
|
|
|
im_image7 = LoadImage("graphics/site.png", false);
|
|
|
|
im_image8 = LoadImage("graphics/site2.png");
|
|
|
|
im_image9 = LoadImage("graphics/site3.png");
|
|
|
|
im_image10 = LoadImage("graphics/ending.png");
|
|
|
|
im_image11 = LoadImage("graphics/site4.png");
|
|
|
|
im_image12 = LoadImage("graphics/minimap.png");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-06-07 22:29:48 +02:00
|
|
|
void GraphicsResources::destroy(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-07-06 22:04:34 +02:00
|
|
|
#define CLEAR(img) \
|
|
|
|
SDL_FreeSurface(img); \
|
|
|
|
img = NULL;
|
2020-01-30 16:04:03 +01:00
|
|
|
|
2020-07-06 22:04:34 +02:00
|
|
|
CLEAR(im_tiles);
|
|
|
|
CLEAR(im_tiles2);
|
|
|
|
CLEAR(im_tiles3);
|
|
|
|
CLEAR(im_entcolours);
|
|
|
|
CLEAR(im_sprites);
|
|
|
|
CLEAR(im_flipsprites);
|
|
|
|
CLEAR(im_bfont);
|
|
|
|
CLEAR(im_teleporter);
|
|
|
|
|
|
|
|
CLEAR(im_image0);
|
|
|
|
CLEAR(im_image1);
|
|
|
|
CLEAR(im_image2);
|
|
|
|
CLEAR(im_image3);
|
|
|
|
CLEAR(im_image4);
|
|
|
|
CLEAR(im_image5);
|
|
|
|
CLEAR(im_image6);
|
|
|
|
CLEAR(im_image7);
|
|
|
|
CLEAR(im_image8);
|
|
|
|
CLEAR(im_image9);
|
|
|
|
CLEAR(im_image10);
|
|
|
|
CLEAR(im_image11);
|
|
|
|
CLEAR(im_image12);
|
|
|
|
#undef CLEAR
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|