Files
cell/source/prosperon.c
John Alanbrook 6b4062eee6
Some checks failed
Build and Deploy / build-linux (push) Failing after 1m3s
Build and Deploy / build-windows (CLANG64) (push) Successful in 9m45s
Build and Deploy / package-dist (push) Has been skipped
Build and Deploy / deploy-itch (push) Has been skipped
Build and Deploy / deploy-gitea (push) Has been skipped
add http get
2025-03-03 08:07:16 -06:00

120 lines
3.8 KiB
C

#include "script.h"
#include "physfs.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <SDL3/SDL.h>
static unsigned char *zip_buffer_global;
static char *prosperon;
void free_zip(void)
{
free(zip_buffer_global);
zip_buffer_global = NULL;
}
int prosperon_mount_core()
{
size_t size;
FILE *f = fopen(prosperon, "rb");
if (!f) { perror("fopen"); return 0; }
if (fseek(f, 0, SEEK_END) != 0) { perror("fseek"); fclose(f); return 0; }
size = ftell(f);
if (size < 0) { perror("ftell"); fclose(f); return 0; }
zip_buffer_global = malloc(size);
if (!zip_buffer_global) { perror("malloc"); fclose(f); return 0; }
rewind(f);
if (fread(zip_buffer_global, 1, size, f) != (size_t)size) {
perror("fread");
free(zip_buffer_global);
fclose(f);
return 0;
}
fclose(f);
// Search backwards for the EOCD signature "PK\x05\x06".
// The EOCD record is at most 0xFFFF (65535) bytes plus 22 bytes long.
long max_comment_len = 0xFFFF;
long eocd_search_start = (size > (max_comment_len + 22)) ? (size - (max_comment_len + 22)) : 0;
long eocd_pos = -1;
for (long i = size - 22; i >= eocd_search_start; i--) {
if (zip_buffer_global[i] == 'P' &&
zip_buffer_global[i + 1] == 'K' &&
zip_buffer_global[i + 2] == 0x05 &&
zip_buffer_global[i + 3] == 0x06) {
eocd_pos = i;
break;
}
}
if (eocd_pos < 0) {
fprintf(stderr, "EOCD not found\n");
free(zip_buffer_global);
return 0;
}
// Parse the EOCD record.
// EOCD record layout (without the comment):
// Offset 0: 4 bytes signature ("PK\x05\x06")
// Offset 4: 2 bytes disk number
// Offset 6: 2 bytes disk with central directory
// Offset 8: 2 bytes number of central dir records on this disk
// Offset 10:2 bytes total number of central dir records
// Offset 12:4 bytes size of central directory (cd_size)
// Offset 16:4 bytes offset of start of central directory (cd_offset_rel, relative to zip start)
// Offset 20:2 bytes comment length
uint16_t comment_length = zip_buffer_global[eocd_pos + 20] |
(zip_buffer_global[eocd_pos + 21] << 8);
int eocd_size = 22 + comment_length;
uint32_t cd_size = zip_buffer_global[eocd_pos + 12] |
(zip_buffer_global[eocd_pos + 13] << 8) |
(zip_buffer_global[eocd_pos + 14] << 16) |
(zip_buffer_global[eocd_pos + 15] << 24);
uint32_t cd_offset_rel = zip_buffer_global[eocd_pos + 16] |
(zip_buffer_global[eocd_pos + 17] << 8) |
(zip_buffer_global[eocd_pos + 18] << 16) |
(zip_buffer_global[eocd_pos + 19] << 24);
uint32_t appended_zip_size = cd_offset_rel + cd_size + eocd_size;
long zip_offset = size - appended_zip_size;
if (zip_offset < 0 || zip_offset >= size) {
fprintf(stderr, "Invalid zip offset computed: %ld\n", zip_offset);
free(zip_buffer_global);
return 0;
}
int ret = PHYSFS_mountMemory(zip_buffer_global + zip_offset, appended_zip_size, free_zip, "core.zip", NULL, 0);
if (!ret) {
printf("COULD NOT MOUNT! Reason: %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
return 0;
}
return 1;
}
int main(int argc, char **argv) {
SDL_Init(SDL_INIT_EVENTS);
printf("INIT TIME %g\n", (double)SDL_GetTicksNS()/1000000000.0);
prosperon = argv[0];
PHYSFS_init(argv[0]);
const char *base = PHYSFS_getBaseDir();
PHYSFS_setWriteDir(base);
PHYSFS_mount(base, "/", 0);
int mounted = prosperon_mount_core();
if (!mounted)
mounted = PHYSFS_mount("core.zip", NULL, 0);
if (!mounted) {
printf("Could not mount core. Reason: %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
return 1;
}
printf("MOUNT TIME %g\n", (double)SDL_GetTicksNS()/1000000000.0);
script_startup(argc, argv); // runs engine.js
return 0;
}