Editor now operates in a zone context.
[cantaveria.git] / loader.c
blobbf759f2e035afdc9e892982f7afddb38b0b9c78c
1 /*
2 Cantaveria - action adventure platform game
3 Copyright (C) 2009 2010 Evan Rinehart
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to
18 The Free Software Foundation, Inc.
19 51 Franklin Street, Fifth Floor
20 Boston, MA 02110-1301, USA
23 #include <string.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <stdio.h>
29 #include <list.h>
30 #include <loader.h>
31 #include <util.h>
32 #include <zip.h>
34 struct reader {
35 zip_file* zf;
36 FILE* ff;
37 int next_c;
40 zip_archive* arc;
41 int data_mode = 1;
44 void loader_data_mode(int flag){
45 if(flag == 0) data_mode = 0;
46 if(flag == 1) data_mode = 1;
49 void loader_init(){
50 char* filename = "data.zip";
51 arc = zip_aropenf(filename);
52 if(arc == NULL){
53 fatal_error("loader: unable to load data archive \"%s\" (%s)\n", filename, zip_geterror());
55 boot_msg("loader: game data found\n");
58 void loader_quit(){
59 zip_arclose(arc);
62 reader* loader_opend(char* filename){
63 char buf[1024] = "data/";
64 int L = strlen(buf);
65 strncpy(buf+L,filename,1024-L);
66 buf[1023] = 0;
68 reader* rd = xmalloc(sizeof(reader));
69 rd->ff = NULL;
70 rd->zf = zip_fopen(arc, filename);
71 if(!rd->zf){
72 error_msg("loader_open: can't open %s (%s)\n", filename, zip_geterror());
73 free(rd);
74 return NULL;
76 return rd;
79 reader* loader_openf(char* path){
80 reader* rd = xmalloc(sizeof(reader));
81 rd->zf = NULL;
82 rd->ff = fopen(path, "r");
83 if(rd->ff == NULL){
84 error_msg("loader_fopen: can't open %s\n", path);
85 free(rd);
86 return NULL;
88 return rd;
91 reader* loader_open(char* filename){
92 if(data_mode == 0){
93 return loader_openf(filename);
95 else if(data_mode == 1){
96 return loader_opend(filename);
98 else{
99 error_msg("loader_open: inconsistent data_mode\n");
100 return NULL;
104 void loader_close(reader* rd){
105 if(rd->ff) fclose(rd->ff);
106 if(rd->zf) zip_fclose(rd->zf);
107 free(rd);
111 int loader_read(reader* rd, void* buf, int count){
112 if(rd->zf){
113 int n = zip_fread(rd->zf, buf, count);
114 if(n < 0){
115 error_msg("loader_read: %s\n", zip_geterror());
116 return -1;
118 return n;
120 else if(rd->ff){
121 int n = fread(buf, 1, count, rd->ff);
122 if(n < 0){
123 error_msg("loader_read: read error\n");
124 return -1;
126 return n;
128 else{
129 error_msg("loader_read: inconsistent reader\n");
130 return -1;
134 unsigned char* loader_readall(char* filename, int* size){
135 reader* rd = loader_open(filename);
136 if(!rd) return NULL;
138 /* somehow read all of rd into a buffer and return it */
140 /* FIXME */
141 error_msg("loader_readall: not yet implemented\n");
142 return NULL;
145 int loader_readline(reader* rd, char* buf, int size){
146 char c;
147 int i = 0;
148 int n;
150 while(i < size){
151 n = loader_read(rd, &c, 1);
152 if(n == 0){ /* end of file */
153 buf[i] = '\0';
154 return 0;
157 if(n < 0){
158 error_msg("loader_readline: %s\n", zip_geterror());
159 return -1;
162 if(c == '\r'){ /* CRLF ? */
163 n = loader_read(rd, &c, 1);
164 if(n == 0){ /* file ended with CR... well take it */
165 buf[i] = '\0';
166 return 0;
169 if(n < 0){
170 error_msg("loader_readline: %s\n", zip_geterror());
171 return -1;
174 if(c != '\n'){
175 error_msg("loader_readline: I cannot read lines ending in CR and not CRLF\n");
176 return -1;
179 buf[i] = '\0';
180 return 0;
183 if(c == '\n'){ /* LF */
184 buf[i] = '\0';
185 return 0;
188 buf[i] = c;
189 i += 1;
192 error_msg("loader_readline: buffer size too small\n");
193 return 0;
196 int loader_scanline(reader* rd, char* format, ...){
197 char buf[256] = "";
198 va_list ap;
199 int ret;
201 if(loader_readline(rd, buf, 256) < 0){
202 return -1;
205 va_start(ap, format);
206 ret = vsscanf(buf,format,ap);
207 va_end(ap);
209 return ret;
212 int loader_feof(reader* rd){
213 if(rd->zf){
214 return zip_feof(rd->zf);
216 else if(rd->ff){
217 return feof(rd->ff);
219 else{
220 error_msg("loader_feof: inconsistent reader\n");
221 return 1;
226 /*binary i/o*/
227 int read_bytes(reader* rd, unsigned char* buf, int count){
228 int n = loader_read(rd, buf, count);
229 if(n < 0){
230 error_msg("read_bytes: read error\n");
231 return -1;
233 else if(n != count){
234 error_msg("read_bytes: end of file reached prematurely (%d out of %d read)\n", n, count);
235 return -1;
237 else{
238 return 0;
242 int read_byte(reader* rd, int* out){
243 unsigned char c;
244 int n = loader_read(rd, &c, 1);
245 if(n < 0){
246 error_msg("read_byte: read error\n");
247 return -1;
249 else{
250 *out = c;
251 return 0;
255 int read_short(reader* rd, int* out){
256 unsigned char c[2];
257 int n = loader_read(rd, c, 2);
259 if(n < 0){
260 error_msg("read_byte: read error\n");
261 return -1;
263 else if(n != 2){
264 error_msg("read_short: end of file reached prematurely\n");
265 return -1;
267 else{
268 *out = (c[0]<<8) | c[1];
269 return 0;
273 int read_int(reader* rd, int* out){
274 unsigned char c[4];
275 int n = loader_read(rd, c, 4);
277 if(n < 0){
278 error_msg("read_byte: read error\n");
279 return -1;
281 else if(n != 4){
282 error_msg("read_int: end of file reached prematurely\n");
283 return -1;
285 else{
286 *out = (c[0]<<24) | (c[1]<<16) | (c[2]<<8) | c[3];
287 return 0;
291 int read_string(reader* rd, char** out){
292 unsigned L;
294 if(read_int(rd, (int*)&L) < 0){
295 return -1;
298 *out = xmalloc(L+1);
299 (*out)[L] = '\0';
301 if(read_bytes(rd, (unsigned char*)*out, L) < 0){
302 free(*out);
303 return -1;
305 else{
306 return 0;
312 list* loader_readdir(char* path){
313 zip_dir* dir = zip_opendir(arc, path);
314 if(dir == NULL){
315 error_msg("loader_readdir: unable to open '%s' (%s)\n",
316 path, zip_geterror());
317 return NULL;
320 list* dirs = empty();
321 while(1){
322 char* entry = zip_readdir(dir);
323 if(entry == NULL) break;
324 else push(dirs, entry);
327 return dirs;
330 void loader_freedirlist(list* dirs){
331 recycle(dirs);