1 /*
2  * Triplane Classic - a side-scrolling dogfighting game.
3  * Copyright (C) 1996,1997,2009  Dodekaedron Software Creations Oy
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
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.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  * tjt@users.sourceforge.net
19  */
20 
21 /*******************************************************************************
22 
23    Purpose:
24    	DKS-datafile handling routines for Wsystem 2.0 for DJGPP v.2.0�5
25 
26 *******************************************************************************/
27 
28 
29 #include <stdio.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <unistd.h>
34 #include <stdlib.h>
35 #include "util/wutil.h"
36 #include "io/dksfile.h"
37 
38 #define MAX_ENTRIES 8192
39 
40 #pragma pack(1)
41 struct main_directory_entry {
42     char nimi[7];
43     unsigned long int offset __attribute__ ((packed));
44     unsigned long int koko __attribute__ ((packed));
45 };
46 
47 #pragma pack()
48 
49 main_directory_entry *dirri;
50 
51 class Dirrikka {
52   public:
53     Dirrikka(void);
54      ~Dirrikka();
55 
56 };
57 
Dirrikka(void)58 Dirrikka::Dirrikka(void) {
59     dirri = (main_directory_entry *)
60         walloc(MAX_ENTRIES * sizeof(main_directory_entry));
61 }
62 
~Dirrikka()63 Dirrikka::~Dirrikka() {
64     free(dirri);
65 }
66 
67 Dirrikka dirrikka;
68 FILE *dks_faili;
69 char dks_tiedosto[FILENAME_MAX];
70 int nykyinen_faili;
71 
72 /*
73  * Find absolute path to given datafile. The following paths are tried
74  * (in that order):
75  *
76  * $TRIPLANE_DATA/$name
77  * TRIPLANE_DATA/$name
78  * $name
79  *
80  * @param name name of datafile
81  * @param path pointer to FILENAME_MAX bytes where absolute path can be
82  * written.
83  */
get_datafile_path(const char * name,char * path)84 static void get_datafile_path(const char *name, char *path) {
85     const char *data;
86 
87     data = getenv("TRIPLANE_DATA");
88     if (data) {
89         strncpy(path, data, FILENAME_MAX - 1);
90         strncat(path, "/", FILENAME_MAX - 1);
91         strncat(path, name, FILENAME_MAX - 1);
92         return;
93     }
94 
95     data = TRIPLANE_DATA;
96     {
97         int ret;
98         struct stat st;
99 
100         ret = stat(data, &st);
101         if (!ret) {
102             strncpy(path, data, FILENAME_MAX - 1);
103             strncat(path, "/", FILENAME_MAX - 1);
104             strncat(path, name, FILENAME_MAX - 1);
105             return;
106         }
107     }
108 
109     strncpy(path, name, FILENAME_MAX - 1);
110 }
111 
dksinit(const char * tiedosto)112 int dksinit(const char *tiedosto) {
113 
114     char tekstia[20];
115 
116     get_datafile_path(tiedosto, dks_tiedosto);
117 
118     if ((dks_faili = fopen(dks_tiedosto, "rb")) == NULL)
119         return (0);
120 
121     fread(tekstia, sizeof(tekstia), 1, dks_faili);
122     fread(dirri, sizeof(main_directory_entry) * MAX_ENTRIES, 1, dks_faili);
123 
124     fclose(dks_faili);
125 
126     return (1);
127 }
128 
dksopen(const char * nimi)129 int dksopen(const char *nimi) {
130     int lask;
131     int kohta = -1;
132 
133     for (lask = 0; lask < MAX_ENTRIES; lask++) {
134         if (!strcmp(dirri[lask].nimi, nimi)) {
135             kohta = lask;
136             break;
137         }
138     }
139 
140     if (kohta == -1) {
141 
142         return (0);
143     }
144 
145 
146     if ((dks_faili = fopen(dks_tiedosto, "rb")) == NULL)
147         return (0);
148 
149     fseek(dks_faili, dirri[kohta].offset, SEEK_SET);
150 
151     nykyinen_faili = kohta;
152 
153     return (1);
154 }
155 
extdksopen(const char * nimi)156 int extdksopen(const char *nimi) {
157     int lask;
158     int kohta = -1;
159     int faili = 0;
160 
161     for (lask = 0; lask < MAX_ENTRIES; lask++) {
162         if (!strcmp(dirri[lask].nimi, nimi)) {
163             kohta = lask;
164             break;
165         }
166     }
167 
168     if (kohta == -1) {
169         dks_faili = fopen(nimi, "rb");
170         faili = 1;
171         if (dks_faili == NULL)
172             return (0);
173     } else {
174         if ((dks_faili = fopen(dks_tiedosto, "rb")) == NULL)
175             return (0);
176 
177         fseek(dks_faili, dirri[kohta].offset, SEEK_SET);
178 
179         nykyinen_faili = kohta;
180     }
181 
182     return (1);
183 }
184 
185 
186 
dksclose(void)187 void dksclose(void) {
188     fclose(dks_faili);
189 
190 }
191 
dkssize(void)192 int dkssize(void) {
193     return dirri[nykyinen_faili].koko;
194 }
195 
dksread(void * mihin,unsigned long int koko)196 int dksread(void *mihin, unsigned long int koko) {
197     if (fread(mihin, koko, 1, dks_faili))
198         return 1;
199     else
200         return 0;
201 }
202 
dksseek(int offset,int mode)203 int dksseek(int offset, int mode) {
204     switch (mode) {
205     case SEEK_SET:
206         return (fseek(dks_faili, dirri[nykyinen_faili].offset + offset, SEEK_SET));
207         break;
208 
209     case SEEK_CUR:
210         return (fseek(dks_faili, offset, SEEK_CUR));
211         break;
212 
213     case SEEK_END:
214         return (fseek(dks_faili, dirri[nykyinen_faili].offset + dirri[nykyinen_faili].koko + offset, SEEK_SET));
215         break;
216 
217 
218     }
219 
220 
221     return 1;
222 }
223 
dksgetc(void)224 int dksgetc(void) {
225     return (fgetc(dks_faili));
226 }
227 
dkstell(void)228 long dkstell(void) {
229     return (ftell(dks_faili) - dirri[nykyinen_faili].offset);
230 }
231