A game engine for top-down 2D RPG games.
rpg game-engine raylib c99
at main 3.2 kB view raw
1#include <keraforge.h> 2#include <stdio.h> 3#include <stdlib.h> 4#include <string.h> 5#include <errno.h> 6#include <lzma.h> 7 8 9int kf_exists(char *filename) 10{ 11 FILE *fp = fopen(filename, "r"); 12 bool opened = fp != NULL; 13 if (opened) 14 fclose(fp); 15 return opened; 16} 17 18u8 *kf_readbin(char *filename, size_t *plen) 19{ 20 FILE *fp = fopen(filename, "rb"); 21 if (!fp) 22 return NULL; 23 24 *plen = 0; 25 fseek(fp, 0, SEEK_END); 26 *plen = ftell(fp); 27 fseek(fp, 0, SEEK_SET); 28 if (*plen == 0) 29 { 30 fclose(fp); 31 return NULL; 32 } 33 34 u8 *data = malloc(*plen); 35 (void)fread(data, 1, *plen, fp); 36 fclose(fp); 37 38 return data; 39} 40 41int kf_writebin(char *filename, u8 *data, size_t len) 42{ 43 FILE *fp = fopen(filename, "wb"); 44 if (!fp) 45 return 0; 46 47 size_t n = fwrite(data, 1, len, fp); 48 fclose(fp); 49 50 if (n != len) 51 return 0; 52 53 return 1; 54} 55 56static 57int _kf_compress(lzma_stream *s, FILE *ifp, FILE *ofp) 58{ 59 lzma_action a = LZMA_RUN; 60 u8 inbuf[BUFSIZ], outbuf[BUFSIZ]; 61 62 s->next_in = NULL; 63 s->avail_in = 0; 64 s->next_out = outbuf; 65 s->avail_out = sizeof(outbuf); 66 67 for (;;) 68 { 69 if (s->avail_in == 0 && !feof(ifp)) 70 { 71 s->next_in = inbuf; 72 s->avail_in = fread(inbuf, 1, sizeof(inbuf), ifp); 73 74 if (ferror(ifp)) 75 { 76 KF_THROW("read error: %s", strerror(errno)); 77 return 0; /* unreachable */ 78 } 79 80 if (feof(ifp)) 81 a = LZMA_FINISH; 82 } 83 84 lzma_ret r = lzma_code(s, a); 85 86 if (s->avail_out == 0 || r == LZMA_STREAM_END) 87 { 88 size_t nwrote = sizeof(outbuf) - s->avail_out; 89 90 if (fwrite(outbuf, 1, nwrote, ofp) != nwrote) 91 { 92 KF_THROW("write error: %s", strerror(errno)); 93 return 0; /* unreachable */ 94 } 95 96 s->next_out = outbuf; 97 s->avail_out = sizeof(outbuf); 98 } 99 100 if (r != LZMA_OK) 101 { 102 if (r == LZMA_STREAM_END) 103 return 1; 104 105 KF_THROW("lzma compression error: code=%d", r); 106 return 0; /* unreachable */ 107 } 108 } 109 110 KF_UNREACHABLE("broke out of for(;;) loop"); 111 return 0; /* unreachable */ 112} 113 114int kf_compress(char *infile, char *outfile) 115{ 116 FILE *ifp = fopen(infile, "r"); 117 if (!ifp) 118 { 119 KF_THROW("failed to open input file: %s", infile); 120 return 0; /* unreachable */ 121 } 122 FILE *ofp = fopen(outfile, "w"); 123 if (!ofp) 124 { 125 fclose(ifp); 126 KF_THROW("failed to open output file: %s", outfile); 127 return 0; /* unreachable */ 128 } 129 130 lzma_stream s = LZMA_STREAM_INIT; 131 lzma_ret r = lzma_easy_encoder(&s, LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC64); 132 if (r != LZMA_OK) 133 { 134 KF_THROW("failed to initialize lzma encoder: code=%d\n", r); 135 return 0; /* unreachable */ 136 } 137 138 int res = _kf_compress(&s, ifp, ofp); 139 140 lzma_end(&s); 141 fclose(ifp); 142 fclose(ofp); 143 144 return res; 145} 146 147int kf_decompress(char *infile, char *outfile) 148{ 149 FILE *ifp = fopen(infile, "r"); 150 if (!ifp) 151 { 152 KF_THROW("failed to open input file: %s", infile); 153 return 0; /* unreachable */ 154 } 155 FILE *ofp = fopen(outfile, "w"); 156 if (!ofp) 157 { 158 fclose(ifp); 159 KF_THROW("failed to open output file: %s", outfile); 160 return 0; /* unreachable */ 161 } 162 163 lzma_stream s = LZMA_STREAM_INIT; 164 lzma_ret r = lzma_stream_decoder(&s, UINT64_MAX, LZMA_CONCATENATED); 165 if (r != LZMA_OK) 166 { 167 KF_THROW("failed to initialize lzma decoder: code=%d\n", r); 168 return 0; /* unreachable */ 169 } 170 171 int res = _kf_compress(&s, ifp, ofp); 172 173 lzma_end(&s); 174 fclose(ifp); 175 fclose(ofp); 176 177 return res; 178}