2020-01-01 21:29:24 +01:00
|
|
|
#include "BinaryBlob.h"
|
|
|
|
|
2020-07-19 21:43:29 +02:00
|
|
|
#include <physfs.h> /* FIXME: Abstract to FileSystemUtils! */
|
|
|
|
#include <SDL.h>
|
2020-01-01 21:29:24 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
|
2021-02-16 03:53:17 +01:00
|
|
|
#include "Exit.h"
|
2020-08-14 10:54:19 +02:00
|
|
|
#include "UtilityClass.h"
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
binaryBlob::binaryBlob(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
numberofHeaders = 0;
|
2021-02-14 02:24:20 +01:00
|
|
|
SDL_zeroa(m_headers);
|
|
|
|
SDL_zeroa(m_memblocks);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef VVV_COMPILEMUSIC
|
|
|
|
void binaryBlob::AddFileToBinaryBlob(const char* _path)
|
|
|
|
{
|
|
|
|
long size;
|
|
|
|
char * memblock;
|
|
|
|
|
|
|
|
FILE *file = fopen(_path, "rb");
|
|
|
|
if (file != NULL)
|
|
|
|
{
|
|
|
|
fseek(file, 0, SEEK_END);
|
|
|
|
size = ftell(file);
|
|
|
|
fseek(file, 0, SEEK_SET);
|
|
|
|
|
2020-08-14 10:56:08 +02:00
|
|
|
memblock = (char*) SDL_malloc(size);
|
Bail for all SDL_malloc() failures
Following Ethan's example of bailing (calling VVV_exit()) if
binaryBlob::unPackBinary() couldn't allocate memory, I've searched
through and found every SDL_malloc(), then made sure that if it returned
NULL, the caller would bail (because you can't do much when you're out
of memory).
There should probably be an error message printed when the process is
out of memory, but unPackBinary() doesn't print an error message for
being out of memory, so this can probably be added later. (Also we don't
really have a logging system, I'd like to have something like that added
in first before adding more messages.)
Also, this doesn't account for any allocators used by STL stuff, but
we're working on removing the STL, and allocation failure just results
in an abort anyway, so there's not really a problem there.
2021-02-16 04:00:18 +01:00
|
|
|
if (memblock == NULL)
|
|
|
|
{
|
|
|
|
VVV_exit(1);
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
fread(memblock, 1, size, file);
|
|
|
|
|
|
|
|
fclose(file);
|
|
|
|
|
|
|
|
printf("The complete file size: %li\n", size);
|
|
|
|
|
|
|
|
m_memblocks[numberofHeaders] = memblock;
|
|
|
|
for (int i = 0; _path[i]; i += 1)
|
|
|
|
{
|
|
|
|
m_headers[numberofHeaders].name[i] = _path[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
m_headers[numberofHeaders].valid = true;
|
|
|
|
m_headers[numberofHeaders].size = size;
|
|
|
|
numberofHeaders += 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
printf("Unable to open file\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void binaryBlob::writeBinaryBlob(const char* _name)
|
|
|
|
{
|
|
|
|
FILE *file = fopen(_name, "wb");
|
|
|
|
if (file != NULL)
|
|
|
|
{
|
2020-07-03 12:23:54 +02:00
|
|
|
fwrite((char*) &m_headers, 1, sizeof(m_headers), file);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
for (int i = 0; i < numberofHeaders; i += 1)
|
|
|
|
{
|
|
|
|
fwrite(m_memblocks[i], 1, m_headers[i].size, file);
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(file);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
printf("Unable to open new file for writing. Feels bad.\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
bool binaryBlob::unPackBinary(const char* name)
|
|
|
|
{
|
|
|
|
PHYSFS_sint64 size;
|
|
|
|
|
|
|
|
PHYSFS_File *handle = PHYSFS_openRead(name);
|
|
|
|
if (handle == NULL)
|
|
|
|
{
|
|
|
|
printf("Unable to open file %s\n", name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
size = PHYSFS_fileLength(handle);
|
|
|
|
|
2020-07-03 12:23:54 +02:00
|
|
|
PHYSFS_readBytes(handle, &m_headers, sizeof(m_headers));
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-07-03 12:23:54 +02:00
|
|
|
int offset = 0 + (sizeof(m_headers));
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-07-03 12:23:54 +02:00
|
|
|
for (size_t i = 0; i < SDL_arraysize(m_headers); i += 1)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-06-15 04:39:06 +02:00
|
|
|
/* Name can be stupid, just needs to be terminated */
|
|
|
|
m_headers[i].name[47] = '\0';
|
|
|
|
|
2020-06-15 04:40:57 +02:00
|
|
|
if (m_headers[i].valid & ~0x1 || !m_headers[i].valid)
|
2020-06-15 04:39:06 +02:00
|
|
|
{
|
2020-07-01 02:58:34 +02:00
|
|
|
m_headers[i].valid = false;
|
2020-06-15 04:40:57 +02:00
|
|
|
continue; /* Must be EXACTLY 1 or 0 */
|
2020-06-15 04:39:06 +02:00
|
|
|
}
|
2020-06-15 04:44:34 +02:00
|
|
|
if (m_headers[i].size < 1)
|
2020-06-15 04:43:58 +02:00
|
|
|
{
|
2020-08-14 10:50:41 +02:00
|
|
|
m_headers[i].valid = false;
|
2020-06-15 04:43:58 +02:00
|
|
|
continue; /* Must be nonzero and positive */
|
|
|
|
}
|
2020-06-15 04:39:06 +02:00
|
|
|
if ((offset + m_headers[i].size) > size)
|
|
|
|
{
|
2020-08-14 10:50:41 +02:00
|
|
|
m_headers[i].valid = false;
|
2020-06-15 04:39:06 +02:00
|
|
|
continue; /* Bogus size value */
|
|
|
|
}
|
|
|
|
|
|
|
|
PHYSFS_seek(handle, offset);
|
2020-08-14 10:56:08 +02:00
|
|
|
m_memblocks[i] = (char*) SDL_malloc(m_headers[i].size);
|
2020-06-15 04:39:06 +02:00
|
|
|
if (m_memblocks[i] == NULL)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2021-02-16 03:53:17 +01:00
|
|
|
VVV_exit(1); /* Oh god we're out of memory, just bail */
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
2020-06-15 04:39:06 +02:00
|
|
|
PHYSFS_readBytes(handle, m_memblocks[i], m_headers[i].size);
|
|
|
|
offset += m_headers[i].size;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
PHYSFS_close(handle);
|
|
|
|
|
2020-01-11 02:05:26 +01:00
|
|
|
printf("The complete reloaded file size: %lli\n", size);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-07-03 12:23:54 +02:00
|
|
|
for (size_t i = 0; i < SDL_arraysize(m_headers); i += 1)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
if (m_headers[i].valid == false)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("%s unpacked\n", m_headers[i].name);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void binaryBlob::clear(void)
|
2020-06-07 22:11:35 +02:00
|
|
|
{
|
2020-07-03 12:23:54 +02:00
|
|
|
for (size_t i = 0; i < SDL_arraysize(m_headers); i += 1)
|
2020-06-07 22:11:35 +02:00
|
|
|
{
|
2021-02-14 02:20:48 +01:00
|
|
|
SDL_free(m_memblocks[i]);
|
2020-06-07 22:11:35 +02:00
|
|
|
}
|
2021-02-14 02:20:48 +01:00
|
|
|
SDL_zeroa(m_memblocks);
|
|
|
|
SDL_zeroa(m_headers);
|
2020-06-07 22:11:35 +02:00
|
|
|
}
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
int binaryBlob::getIndex(const char* _name)
|
|
|
|
{
|
2020-07-03 12:23:54 +02:00
|
|
|
for (size_t i = 0; i < SDL_arraysize(m_headers); i += 1)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-08-14 10:56:08 +02:00
|
|
|
if (SDL_strcmp(_name, m_headers[i].name) == 0 && m_headers[i].valid)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int binaryBlob::getSize(int _index)
|
|
|
|
{
|
2020-08-14 10:54:19 +02:00
|
|
|
if (!INBOUNDS_ARR(_index, m_headers))
|
|
|
|
{
|
|
|
|
puts("getSize() out-of-bounds!");
|
|
|
|
return 0;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
return m_headers[_index].size;
|
|
|
|
}
|
|
|
|
|
|
|
|
char* binaryBlob::getAddress(int _index)
|
|
|
|
{
|
2020-08-14 10:54:19 +02:00
|
|
|
if (!INBOUNDS_ARR(_index, m_memblocks))
|
|
|
|
{
|
|
|
|
puts("getAddress() out-of-bounds!");
|
|
|
|
return NULL;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
return m_memblocks[_index];
|
|
|
|
}
|
2020-07-01 00:27:57 +02:00
|
|
|
|
2021-02-18 08:48:41 +01:00
|
|
|
bool binaryBlob::nextExtra(size_t* start)
|
2020-07-01 00:27:57 +02:00
|
|
|
{
|
2021-02-18 08:48:41 +01:00
|
|
|
size_t* idx;
|
|
|
|
|
|
|
|
if (start == NULL)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (idx = start; *idx < SDL_arraysize(m_headers); *idx += 1)
|
2020-07-01 00:27:57 +02:00
|
|
|
{
|
2021-02-18 08:48:41 +01:00
|
|
|
if (m_headers[*idx].valid
|
|
|
|
#define FOREACH_TRACK(_, track_name) && SDL_strcmp(m_headers[*idx].name, track_name) != 0
|
2021-02-16 01:38:10 +01:00
|
|
|
TRACK_NAMES(_)
|
2020-07-01 00:27:57 +02:00
|
|
|
#undef FOREACH_TRACK
|
|
|
|
) {
|
2021-02-18 08:48:41 +01:00
|
|
|
return true;
|
2020-07-01 00:27:57 +02:00
|
|
|
}
|
|
|
|
}
|
2021-02-18 08:48:41 +01:00
|
|
|
return false;
|
2020-07-01 00:27:57 +02:00
|
|
|
}
|