Merge branch 'io' into audio
[cantaveria.git] / loader.c
blobe15b341629facf4381b9f7d89fb83a0b0c26e940
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* f;
36 int next_c;
39 zip_archive* arc;
42 void loader_init(){
43 char* filename = "data.zip";
44 arc = zip_aropenf(filename);
45 if(arc == NULL){
46 fatal_error("loader: unable to load data archive \"%s\" (%s)\n", filename, zip_geterror());
48 boot_msg("loader: ... OK\n");
51 void loader_quit(){
52 zip_arclose(arc);
55 reader* data_open(char* dir, char* filename){
56 char buf[1024];
57 strcpy(buf, dir);
58 strcat(buf, filename);
59 return loader_open(buf);
62 reader* loader_open(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->f = zip_fopen(arc, filename);
70 if(!rd->f){
71 error_msg("loader_open: can't open %s (%s)\n", filename, zip_geterror());
72 free(rd);
73 return NULL;
75 return rd;
79 void loader_close(reader* rd){
80 zip_fclose(rd->f);
81 free(rd);
85 int loader_read(reader* rd, void* buf, int count){
86 int n = zip_fread(rd->f, buf, count);
87 if(n < 0){
88 error_msg("loader_read: %s\n", zip_geterror());
89 return -1;
91 return n;
94 unsigned char* loader_readall(char* filename, int* size){
95 reader* rd = loader_open(filename);
96 if(!rd) return NULL;
98 /* somehow read all of rd into a buffer and return it */
100 /* FIXME */
101 error_msg("loader_readall: not yet implemented\n");
102 return NULL;
105 int loader_readline(reader* rd, char* buf, int size){
106 char c;
107 int i = 0;
108 int n;
110 while(i < size){
111 n = loader_read(rd, &c, 1);
112 if(n == 0){ /* end of file */
113 buf[i] = '\0';
114 return 0;
117 if(n < 0){
118 error_msg("loader_readline: %s\n", zip_geterror());
119 return -1;
122 if(c == '\r'){ /* CRLF ? */
123 n = loader_read(rd, &c, 1);
124 if(n == 0){ /* file ended with CR... well take it */
125 buf[i] = '\0';
126 return 0;
129 if(n < 0){
130 error_msg("loader_readline: %s\n", zip_geterror());
131 return -1;
134 if(c != '\n'){
135 error_msg("loader_readline: I cannot read lines ending in CR and not CRLF\n");
136 return -1;
139 buf[i] = '\0';
140 return 0;
143 if(c == '\n'){ /* LF */
144 buf[i] = '\0';
145 return 0;
148 buf[i] = c;
149 i += 1;
152 error_msg("loader_readline: buffer size too small\n");
153 return 0;
156 int loader_scanline(reader* rd, char* format, ...){
157 char buf[256] = "";
158 va_list ap;
159 int ret;
161 if(loader_readline(rd, buf, 256) < 0){
162 return -1;
165 va_start(ap, format);
166 ret = vsscanf(buf,format,ap);
167 va_end(ap);
169 return ret;
175 /*binary i/o*/
176 int read_bytes(reader* rd, unsigned char* buf, int count){
177 int n = loader_read(rd, buf, count);
178 if(n < 0){
179 error_msg("read_bytes: read error\n");
180 return -1;
182 else if(n != count){
183 error_msg("read_bytes: end of file reached prematurely (%d out of %d read)\n", n, count);
184 return -1;
186 else{
187 return 0;
191 int read_byte(reader* rd, int* out){
192 unsigned char c;
193 int n = loader_read(rd, &c, 1);
194 if(n < 0){
195 error_msg("read_byte: read error\n");
196 return -1;
198 else{
199 *out = c;
200 return 0;
204 int read_short(reader* rd, int* out){
205 unsigned char c[2];
206 int n = loader_read(rd, c, 2);
208 if(n < 0){
209 error_msg("read_byte: read error\n");
210 return -1;
212 else if(n != 2){
213 error_msg("read_short: end of file reached prematurely\n");
214 return -1;
216 else{
217 *out = (c[0]<<8) | c[1];
218 return 0;
222 int read_int(reader* rd, int* out){
223 unsigned char c[4];
224 int n = loader_read(rd, c, 4);
226 if(n < 0){
227 error_msg("read_byte: read error\n");
228 return -1;
230 else if(n != 4){
231 error_msg("read_int: end of file reached prematurely\n");
232 return -1;
234 else{
235 *out = (c[0]<<24) | (c[1]<<16) | (c[2]<<8) | c[3];
236 return 0;
240 int read_string(reader* rd, char** out){
241 unsigned L;
242 if(read_int(rd, (int*)&L) < 0){
243 return -1;
246 *out = xmalloc(L+1);
247 *out[L] = '\0';
248 if(read_bytes(rd, (unsigned char*)*out, L) < 0){
249 free(*out);
250 return -1;
252 else{
253 return 0;
259 list* loader_readdir(char* path){
260 zip_dir* dir = zip_opendir(arc, path);
261 if(dir == NULL){
262 error_msg("loader_readdir: unable to open '%s' (%s)\n",
263 path, zip_geterror());
264 return NULL;
267 list* dirs = empty();
268 while(1){
269 char* entry = zip_readdir(dir);
270 if(entry == NULL) break;
271 else push(dirs, entry);
274 return dirs;
277 void loader_freedirlist(list* dirs){
278 recycle(dirs);