DEADSOFTWARE

portability: use only english strings for debug
[flatwaifu.git] / src / map.c
1 /* Copyright (C) 1996-1997 Aleksey Volynskov
2 * Copyright (C) 2011 Rambo
3 * Copyright (C) 2020 SovietPony
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, version 3 of the License ONLY.
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, see <http://www.gnu.org/licenses/>.
16 */
18 #include "map.h"
20 #include "game.h"
21 #include "items.h"
22 #include "things.h"
23 #include "monster.h"
24 #include "switch.h"
25 #include "view.h"
27 #include "music.h"
28 #include "files.h"
29 #include "render.h"
31 #include <stdio.h>
32 #include <string.h>
33 #include "my.h"
34 #include "error.h"
35 #include "cp866.h"
37 enum {
38 MB_COMMENT = -1, MB_END = 0,
39 MB_WALLNAMES, MB_BACK, MB_WTYPE, MB_FRONT, MB_THING, MB_SWITCH,
40 MB_MUSIC, MB_SKY,
41 MB_SWITCH2,
42 MB__UNKNOWN
43 };
45 typedef struct map_header_t {
46 char id[8];
47 short ver;
48 } map_header_t;
50 typedef struct map_block_t {
51 short t;
52 short st;
53 int sz;
54 } map_block_t;
56 typedef struct old_thing_t {
57 short x, y;
58 short t;
59 unsigned short f;
60 } old_thing_t;
62 static map_block_t blk;
64 static int G_load (FILE *h) {
65 switch (blk.t) {
66 case MB_MUSIC:
67 myfread(g_music, 8, 1, h);
68 //if (music_random) {
69 // F_randmus(g_music);
70 //}
71 MUS_load(g_music);
72 return 1;
73 }
74 return 0;
75 }
77 static int IT_load (FILE *h) {
78 int m, i, j;
79 old_thing_t t;
80 switch (blk.t) {
81 case MB_THING:
82 for (i = 0; blk.sz > 0; ++i, blk.sz -= 8) {
83 t.x = myfread16(h);
84 t.y = myfread16(h);
85 t.t = myfread16(h);
86 t.f = myfread16(h);
87 it[i].o.x = t.x;
88 it[i].o.y = t.y;
89 it[i].t = t.t;
90 it[i].s = t.f;
91 if (it[i].t && (it[i].s & THF_DM) && !g_dm) {
92 it[i].t=0;
93 }
94 }
95 m = i;
96 for (i = 0, j = -1; i < m; ++i) {
97 if (it[i].t == TH_PLR1) {
98 j = i;
99 it[i].t = 0;
102 if (!g_dm) {
103 if (j == -1) {
104 ERR_fatal("Player 1 point not exists on the map");
106 dm_pos[0].x = it[j].o.x;
107 dm_pos[0].y = it[j].o.y;
108 dm_pos[0].d = it[j].s & THF_DIR;
110 for (i = 0, j = -1; i < m; ++i) {
111 if (it[i].t == TH_PLR2) {
112 j = i;
113 it[i].t = 0;
116 if (!g_dm && _2pl) {
117 if (j == -1) {
118 ERR_fatal("Player 2 point not exists on the map");
120 dm_pos[1].x = it[j].o.x;
121 dm_pos[1].y = it[j].o.y;
122 dm_pos[1].d = it[j].s & THF_DIR;
124 for (i = 0, j = 0; i < m; ++i) {
125 if (it[i].t == TH_DMSTART) {
126 if (g_dm) {
127 dm_pos[j].x = it[i].o.x;
128 dm_pos[j].y = it[i].o.y;
129 dm_pos[j].d = it[i].s & THF_DIR;
131 it[i].t = 0;
132 ++j;
135 if (g_dm && j < 2) {
136 ERR_fatal("Required at least two DM points on the map");
138 if (g_dm) {
139 dm_pnum = j;
140 dm_pl1p = myrand(dm_pnum);
141 do {
142 dm_pl2p = myrand(dm_pnum);
143 } while (dm_pl2p == dm_pl1p);
144 } else {
145 dm_pl1p = 0;
146 dm_pl2p = 1;
147 dm_pnum = 2;
149 PL_spawn(&pl1, dm_pos[dm_pl1p].x, dm_pos[dm_pl1p].y, dm_pos[dm_pl1p].d);
150 if (_2pl) {
151 PL_spawn(&pl2, dm_pos[dm_pl2p].x, dm_pos[dm_pl2p].y, dm_pos[dm_pl2p].d);
153 for (i = 0; i < m; ++i) {
154 if (it[i].t >= TH_CLIP && it[i].t < TH_DEMON) {
155 it[i].s = 0;
156 it[i].t = it[i].t - TH_CLIP + I_CLIP;
157 if (it[i].t >= I_KEYR && it[i].t <= I_KEYB) {
158 it[i].t |= 0x8000;
160 } else if (it[i].t >= TH_DEMON) {
161 MN_spawn(it[i].o.x, it[i].o.y, it[i].s & THF_DIR, it[i].t - TH_DEMON + MN_DEMON);
162 it[i].t = 0;
165 return 1;
167 return 0;
170 static int SW_load (FILE *h) {
171 int i;
172 switch(blk.t) {
173 case MB_SWITCH2:
174 sw_secrets = 0;
175 for (i = 0; i < MAXSW && blk.sz > 0; ++i, blk.sz -= 9) {
176 sw[i].x = myfread8(h);
177 sw[i].y = myfread8(h);
178 sw[i].t = myfread8(h);
179 sw[i].tm = myfread8(h); // unused
180 sw[i].a = myfread8(h);
181 sw[i].b = myfread8(h);
182 sw[i].c = myfread8(h);
183 sw[i].d = myfread8(h); // unused
184 sw[i].f = myfread8(h);
185 sw[i].tm = 0;
186 sw[i].d = 0;
187 sw[i].f |= 0x80;
188 if (sw[i].t == SW_SECRET) {
189 ++sw_secrets;
192 return 1;
194 return 0;
197 static void unpack (void *buf, int len, void *obuf) {
198 int i = 0;
199 int j = 0;
200 unsigned char *p = buf;
201 unsigned char *q = obuf;
202 while (i < len) {
203 int id = p[i];
204 int step = 1;
205 i += 1;
206 if (id == 0xff) {
207 step = p[i] | p[i + 1] << 8;
208 id = p[i + 2];
209 i += 3;
211 memset(&q[j], id, step);
212 j += step;
216 static int read_array (void *p, FILE *h) {
217 void *buf;
218 switch (blk.st) {
219 case 0:
220 myfread(p, FLDW * FLDH, 1, h);
221 break;
222 case 1:
223 buf = malloc(blk.sz);
224 if (buf == NULL) {
225 ERR_fatal("Out of memory");
227 myfread(buf, blk.sz, 1, h);
228 unpack(buf, blk.sz, p);
229 free(buf);
230 break;
231 default:
232 return 0;
234 return 1;
237 static int W_load (FILE *h) {
238 int i;
239 char s[8];
240 switch (blk.t) {
241 case MB_WALLNAMES:
242 R_begin_load();
243 memset(walf, 0, sizeof(walf));
244 for (i = 1; i < 256 && blk.sz > 0; i++, blk.sz -= 9) {
245 myfread(s, 8, 1, h);
246 walf[i] = myfread8(h) ? 1 : 0; // ???
247 R_load(s);
248 if (cp866_strncasecmp(s, "VTRAP01", 8) == 0) {
249 walf[i] |= 2;
252 R_end_load();
253 return 1;
254 case MB_BACK:
255 return read_array(fldb, h);
256 case MB_WTYPE:
257 return read_array(fld, h);
258 case MB_FRONT:
259 return read_array(fldf, h);
260 case MB_SKY:
261 sky_type = myfread16(h);
262 R_loadsky(sky_type);
263 return 1;
265 return 0;
268 void F_loadmap (char n[8]) {
269 int r, o;
270 FILE *h;
271 map_header_t hdr;
272 W_init();
273 r = F_getresid(n);
274 h = wadh[wad[r].f];
275 fseek(h, wad[r].o, SEEK_SET);
276 myfread(hdr.id, 8, 1, h);
277 hdr.ver = myfread16(h);
278 if (memcmp(hdr.id, "Doom2D\x1A", 8) != 0) {
279 ERR_fatal("%.8s not map", n);
281 for (;;) {
282 blk.t = myfread16(h);
283 blk.st = myfread16(h);
284 blk.sz = myfread32(h);
285 if(blk.t == MB_END) {
286 break;
288 if(blk.t == MB_COMMENT) {
289 fseek(h, blk.sz, SEEK_CUR);
290 continue;
292 o = ftell(h) + blk.sz;
293 if(!G_load(h)) {
294 if(!W_load(h)) {
295 if(!IT_load(h)) {
296 if(!SW_load(h)) {
297 ERR_fatal("Unknown block %d(%d) on map %.8s", blk.t, blk.st, n);
302 fseek(h, o, SEEK_SET);