Advertisement
nezvers

Serialize game in C

Jan 30th, 2022 (edited)
1,504
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.28 KB | None | 0 0
  1. // https://www.gamedev.net/forums/topic/687035-serialization-libraries-in-c/5335190/
  2.  
  3. #pragma once
  4. #ifndef MEM_ALOC
  5. #define MEM_ALOC(x) malloc(x)
  6. #endif // !MEM_ALOC
  7.  
  8.  
  9. #define _CRT_SECURE_NO_WARNINGS
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <assert.h>
  14.  
  15. //make sure that there's no element padding, which would interfere with the layout of structures in memory
  16. #pragma pack(1)
  17.  
  18. typedef struct {
  19.     unsigned short major;
  20.     unsigned short minor;
  21. } VersionNumber;
  22.  
  23. const VersionNumber VERSION = { 1, 0 };
  24.  
  25. typedef struct {
  26.     unsigned int fourcc;
  27.     VersionNumber ver;
  28. } SaveHeader;
  29.  
  30. void save_string(const char* str, FILE* fp) {
  31.     unsigned int len = strlen(str);
  32.     //record string length
  33.     fwrite(&len, sizeof(unsigned int), 1, fp);
  34.     //record string
  35.     fwrite(str, sizeof(char), len, fp);
  36. }
  37.  
  38. void load_string(char** pstr, FILE* fp) {
  39.     //get length
  40.     unsigned int len;
  41.     errno_t err = fread(&len, sizeof(unsigned int), 1, fp);
  42.     if (len == 0) { return; }
  43.  
  44.     //allocate and read
  45.     char* str = (char*)MEM_ALOC(len + 1); //allocate an additional byte
  46.     if (str == nullptr) { return; }
  47.    
  48.     err = fread(str, sizeof(char), len, fp);
  49.     if (err) { return; }
  50.    
  51.     str[len] = 0; //remember to add the terminating zero
  52.     *pstr = str;
  53. }
  54.  
  55. void save_game(void* data, const char* filename) {
  56.     SaveHeader header;
  57.     header.fourcc = 'SAVF';
  58.     memcpy(&header.ver, &VERSION, sizeof(header.ver));
  59.  
  60.     FILE* fp;
  61.     fopen_s(&fp, filename, "wb");
  62.     if (fp == 0) { return; }
  63.  
  64.     //write header
  65.     errno_t err = fwrite(&header, sizeof(header), 1, fp);
  66.  
  67.     /*
  68.    
  69.     size_t PARTY_POD_SECTION_LENGTH = sizeof(unsigned int) + (sizeof(int) * 2);
  70.     fwrite(party, PARTY_POD_SECTION_LENGTH, 1, fp);
  71.  
  72.     //Item is POD (plain-old-data), so we can just dump the whole array
  73.     fwrite(party->inventory, sizeof(Item), party->itemCt, fp);
  74.    
  75.     //Party members have variable length strings, so we need to save them individually
  76.  
  77.     size_t PARTYMEMBER_POD_SECTION_LENGTH = sizeof(unsigned char) + (sizeof(short) * 2);
  78.     for(int i = 0; i < party->member_count; i++) {
  79.         fwrite(&party->members[i], PARTYMEMBER_POD_SECTION_LENGTH, 1, fp);
  80.         save_string(&party->members[i]->name, fp);
  81.     }
  82.    
  83.     */
  84.  
  85.     fclose(fp);
  86. }
  87.  
  88.  
  89.  
  90. void load_game(void* data, const char* filename) {
  91.     FILE* fp;
  92.     fopen_s(&fp, filename, "rb");
  93.     if (fp == nullptr) { return; }
  94.  
  95.     SaveHeader header;
  96.     fread(&header, sizeof(header), 1, fp);
  97.  
  98.     if (header.fourcc == 'FVAS') {
  99.         printf("Endian mismatch!\n");
  100.         exit(1);
  101.     }
  102.  
  103.     if (header.fourcc != 'SAVF') {
  104.         printf("Invalid savefile!\n");
  105.         exit(1);
  106.     }
  107.  
  108.     if (memcmp(&header.ver, &VERSION, sizeof(VERSION)) != 0) {
  109.         printf("Savefile version mismatch!\n");
  110.         exit(1);
  111.     }
  112.  
  113.     /*
  114.     size_t PARTY_POD_SECTION_LENGTH = sizeof(unsigned int) + (sizeof(int) * 2);
  115.     fread(party, PARTY_POD_SECTION_LENGTH, 1, fp);
  116.  
  117.     //allocate for the inventory and just read it all in at once, since it's POD
  118.     party->inventory = malloc(sizeof(Item) * party->itemCt);
  119.     fread(party->inventory, sizeof(Item), party->itemCt, fp);
  120.  
  121.     //load party members individually since they're non-POD
  122.     party->members = malloc(sizeof(PartyMember) * party->memberCt);
  123.     for(int i = 0; i < party->memberCt; i++) {
  124.         fread(&party->members[i], PARTYMEMBER_POD_SECTION_LENGTH, 1, fp);
  125.         loadString(&party->members[i]->name, fp);
  126.     }
  127.     */
  128.     fclose(fp);
  129. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement