#include "script.h" #include "physfs.h" #include #include #include #include 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) { 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; } script_startup(argc, argv); // runs engine.js return 0; }