1 /* Tower Toppler - Nebulus
2 * Copyright (C) 2000-2012 Andreas R�ver
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #include "archi.h"
20 #include "decl.h"
21 #include <zlib.h>
22 #include <string.h>
23 #include <stdlib.h>
24
25 /* this value is used as a sanity check for filnename lengths
26 */
27 #define FNAMELEN 250
28
archive(FILE * stream)29 archive::archive(FILE *stream) : f(stream) {
30
31 assert_msg(f, "Data file not found");
32
33 /* find out the number of files inside the archive
34 * alloce the neccessary memory
35 */
36 fread(&filecount, 1, 1, f);
37 files = new fileindex[filecount];
38 assert_msg(files, "Failed to alloc memory for archive index.");
39
40 /* read the information for each file */
41 for (Uint8 file = 0; file < filecount; file++) {
42
43 Uint8 strlen = 0;
44
45 /* find ut the length of the name string */
46 {
47 char c;
48 long currentpos = ftell(f);
49
50 do {
51 strlen++;
52 assert_msg(strlen <= FNAMELEN, "Filename too long, datafile corrupt?");
53 fread(&c, 1, 1, f);
54 } while (c);
55
56 fseek(f, currentpos, SEEK_SET);
57 }
58
59 /* alloc memory for string and read it */
60 files[file].name = new char[strlen];
61 for (int pos = 0; pos < strlen; pos++)
62 fread(&files[file].name[pos], 1, 1, f);
63
64 Uint8 tmp;
65
66 /* load start from archive */
67 fread(&tmp, 1, 1, f);
68 files[file].start = ((Uint32)(tmp)) << 0;
69 fread(&tmp, 1, 1, f);
70 files[file].start |= ((Uint32)(tmp)) << 8;
71 fread(&tmp, 1, 1, f);
72 files[file].start |= ((Uint32)(tmp)) << 16;
73 fread(&tmp, 1, 1, f);
74 files[file].start |= ((Uint32)(tmp)) << 24;
75
76 /* load filesize from archive */
77 fread(&tmp, 1, 1, f);
78 files[file].size = ((Uint32)(tmp)) << 0;
79 fread(&tmp, 1, 1, f);
80 files[file].size |= ((Uint32)(tmp)) << 8;
81 fread(&tmp, 1, 1, f);
82 files[file].size |= ((Uint32)(tmp)) << 16;
83 fread(&tmp, 1, 1, f);
84 files[file].size |= ((Uint32)(tmp)) << 24;
85
86 /* load compressed size from archive */
87 fread(&tmp, 1, 1, f);
88 files[file].compress = ((Uint32)(tmp)) << 0;
89 fread(&tmp, 1, 1, f);
90 files[file].compress |= ((Uint32)(tmp)) << 8;
91 fread(&tmp, 1, 1, f);
92 files[file].compress |= ((Uint32)(tmp)) << 16;
93 fread(&tmp, 1, 1, f);
94 files[file].compress |= ((Uint32)(tmp)) << 24;
95 }
96 }
97
~archive()98 archive::~archive() {
99
100 /* free memory allocated for filenames */
101 for (int i = 0; i < filecount; i++)
102 delete [] files[i].name;
103
104 /* free the file header array */
105 delete [] files;
106
107 fclose(f);
108 }
109
file(const archive * arc,const char * name)110 file::file(const archive *arc, const char *name) : bufferpos(0) {
111
112 for (Uint8 i = 0; i < arc->filecount; i++) {
113 if (strncmp(name, arc->files[i].name, FNAMELEN) == 0) {
114
115 /* allocate buffer for compressed data */
116 Uint8 *b = new Uint8[arc->files[i].compress];
117
118 /* allocate buffer for uncompressed data */
119 fsize = arc->files[i].size;
120 buffer = new Uint8[fsize];
121
122 /* read the compressed data */
123 fseek(arc->f, arc->files[i].start, SEEK_SET);
124 fread(b, arc->files[i].compress, 1, arc->f);
125
126 /* decompress it and check results */
127 assert_msg(uncompress(buffer, &fsize, b, arc->files[i].compress) == Z_OK, "Decompression problem, data file corrupt?");
128 assert_msg(fsize == arc->files[i].size, "Data file corrupt.");
129
130 /* free temporary buffer */
131 delete [] b;
132
133 return;
134 }
135 }
136
137 /* if we arrive here we couldn't find the file we looked for */
138 assert_msg(0, "File not found in archive!");
139 }
140
~file()141 file::~file() { delete [] buffer; }
142
read(void * buf,Uint32 size)143 Uint32 file::read(void *buf, Uint32 size) {
144 memcpy(buf, &buffer[bufferpos], size);
145 bufferpos += size;
146 return size;
147 }
148
getbyte(void)149 Uint8 file::getbyte(void) {
150 return buffer[bufferpos++];
151 }
152
getword(void)153 Uint16 file::getword(void) {
154 Uint16 w = (Uint16)buffer[bufferpos] + ((Uint16)buffer[bufferpos+1] << 8);
155 bufferpos+=2;
156 return w;
157 }
158
rwOps(void)159 SDL_RWops *file::rwOps(void) {
160 return SDL_RWFromMem(buffer, fsize);
161 }
162
163
164 archive * dataarchive;
165