4 * Copyright (C) Prikol Software 1996-1997
5 * Copyright (C) Aleksey Volynskov 1996-1997
6 * Copyright (C) <ARembo@gmail.com> 2011
7 * Copyright (C) Ketmar Dark 2013
9 * coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
10 * Understanding is not required. Only obedience.
12 * This program is free software. It comes without any warranty, to
13 * the extent permitted by applicable law. You can redistribute it
14 * and/or modify it under the terms of the Do What The Fuck You Want
15 * To Public License, Version 2, as published by Sam Hocevar. See
16 * http://www.wtfpl.net/ for more details.
18 * Visit the site of the original author:
19 * http://ranmantaru.com/
48 ////////////////////////////////////////////////////////////////////////////////
52 #define w_view_wdt 200
55 #define MAXX (FLDW*CELW-w_view_wdt/2)
56 #define MAXY (FLDH*CELH-w_view_hgt/2)
60 ////////////////////////////////////////////////////////////////////////////////
66 ccBool r_drawsky
= CC_TRUE
;
68 int w_viewofs_vert
, w_viewofs_x
, w_viewofs_y
;
77 vgaimg anispr
[ANIT
][5];
80 int FLDW
= 0, FLDH
= 0; // 100x100
85 ccBool cheatNoBack
= CC_FALSE
;
86 ccBool cheatNoFront
= CC_FALSE
;
89 ////////////////////////////////////////////////////////////////////////////////
90 CONVAR_BOOL(r_drawsky
, r_drawsky
, CMDCON_FLAGS_PERSISTENT
, "draw sky?")
93 ////////////////////////////////////////////////////////////////////////////////
101 void W_set_field_size (int w
, int h
) {
103 if (w
< 1) w
= 1; else if (w
> 32767) w
= 32767;
104 if (h
< 1) h
= 1; else if (h
> 32767) h
= 32767;
105 if (w
!= FLDW
|| h
!= FLDH
) {
106 if ((fldb
= realloc(fldb
, w
*h
)) == NULL
) ERR_fatal("W_set_field_size: out of memory!");
107 if ((fldf
= realloc(fldf
, w
*h
)) == NULL
) ERR_fatal("W_set_field_size: out of memory!");
108 if ((fldm
= realloc(fldm
, w
*h
)) == NULL
) ERR_fatal("W_set_field_size: out of memory!");
116 ////////////////////////////////////////////////////////////////////////////////
117 static const char *anm
[ANIT
-1][5] = {
118 {"WALL22_1", "WALL23_1", "WALL23_2", NULL
, NULL
},
119 {"WALL58_1", "WALL58_2", "WALL58_3", NULL
, NULL
},
120 {"W73A_1", "W73A_2", NULL
, NULL
, NULL
},
121 {"RP2_1", "RP2_2", "RP2_3", "RP2_4", NULL
}
126 static void getname (int n
, char *s
) {
132 memcpy(s
, "_WATER_", 8);
133 //s[7] = (char)((((uintptr_t)walp[n])&0xff)-1+'0');
134 s
[7] = walpix
[n
].wanim
-1+'0';
135 //fprintf(stderr, "n=%d; wanim=%d\n", n, walpix[n].wanim);
138 F_getresname(s
, walh
[n
]&0x7FFF);
144 static short getani (const char *n
) {
145 for (int f
= 0; f
< ANIT
-1; ++f
) if (strncasecmp(n
, anm
[f
][0], 8) == 0) return f
+1;
150 void W_adjust (void) {
151 int MAXX
= (FLDW
*CELW
-w_view_wdt
/2);
152 int MAXY
= (FLDH
*CELH
-w_view_hgt
/2);
154 if (w_viewofs_x
< w_view_wdt
/2) w_viewofs_x
= w_view_wdt
/2;
155 if (w_viewofs_y
< w_view_hgt
/2) w_viewofs_y
= w_view_hgt
/2;
156 if (w_viewofs_x
> MAXX
) w_viewofs_x
= MAXX
;
157 if (w_viewofs_y
> MAXY
) w_viewofs_y
= MAXY
;
161 ccBool r_lighting
= CC_FALSE
;
162 static int r_lights_tnum
= 0;
163 static int r_lights_trad
= 250;
164 static ccBool r_flashlight
= CC_FALSE
;
166 CONVAR_BOOL(r_lighting
, r_lighting
, 0, "test dynamic lighting")
167 CONVAR_INT(r_lights_tnum
, r_lights_tnum
, 0, "# of additional lights for testing")
168 CONVAR_INT(r_lights_trad
, r_lights_trad
, 0, "radius of additional lights")
169 CONVAR_BOOL(r_flashlight
, r_flashlight
, 0, "test marine flashlight")
172 ////////////////////////////////////////////////////////////////////////////////
176 ////////////////////////////////////////////////////////////////////////////////
177 // bg!=0: cheatNoBack
178 // bg==0: cheatNoFront
179 void Z_drawfld (const uint8_t *xfld
, int bg
) {
180 const uint8_t *p
= xfld
, *pb
= &FIELD_TBG(0, 0), *pf
= &FIELD_TFG(0, 0), *pm
= &FIELD_MAP(0, 0);
181 int semi
= (bg
? cheatNoBack
: cheatNoFront
);
183 for (int y
= 0; y
< FLDH
; ++y
) {
184 for (int x
= 0; x
< FLDW
; ++x
) {
185 int sx
= Z_MAP2SCR_X(x
*CELW
);
186 int sy
= Z_MAP2SCR_Y(y
*CELH
);
188 if (sx
>= -CELW
*256 && sx
< w_view_wdt
&& sy
>= -CELH
*256 && sy
< SCRH
) {
189 if (*p
> 0 && *p
< 255) {
191 vgaimg
*pic
= walp
[*p
];
193 // check the following in postprocessor
194 //if (pic == NULL) continue; // the thing that should not be; no, really!
196 if (pic
->wanim
<= 0) {
197 // normal texture, not 'liquid'
198 // check the following in postprocessor
199 //if (pic->w < 1) continue; // the thing that should not be; no, really!
203 if (!bg
|| pm
[0] == TILE_WALL
/*|| (pf[0] && pm[0]) || pf[0]*/) {
204 // this is impassable or foreground wall, draw it fulllit
205 V_draw_tile(sx
, sy
, pic
, semi
);
207 // this is passable wall, light it later
208 V_draw_tile_lm(sx
, sy
, pic
, semi
);
212 V_draw_tile(sx
, sy
, pic
, semi
);
217 if (r_lighting
&& bg
&& *p
== 255) {
218 // unoccupied background tile
219 // fill background, so light will have something to lit
220 V_draw_tile_lm(sx
, sy
, walp
[1], semi
);
233 void Z_drawliquids (void) {
234 const uint8_t *p
= &FIELD_TFG(0, 0);
236 for (int y
= 0; y
< FLDH
; ++y
) {
237 for (int x
= 0; x
< FLDW
; ++x
) {
238 int sx
= Z_MAP2SCR_X(x
*CELW
);
239 int sy
= Z_MAP2SCR_Y(y
*CELH
);
241 if (sx
>= -CELW
&& sx
< w_view_wdt
&& sy
>= -CELH
&& sy
< SCRH
) {
242 if (*p
> 0 && *p
< 255) {
244 vgaimg
*pic
= walp
[*p
];
246 if (pic
== NULL
) continue; // the thing that should not be; no, really!
248 if (pic
->wanim
> 0 && pic
->wanim
<= 3 && sy
< w_viewofs_vert
+w_view_hgt
) {
249 // one of the 'water' textures
254 static const Uint32 aa
[8] = {
255 0x5f<<24, 0x4f<<24, 0x3f<<24, 0x2f<<24, 0x1f<<24, 0x2f<<24, 0x3f<<24, 0x4f<<24,
258 switch (pic
->wanim
) {
259 case 1: src
= 0x5f0000ff; break; // water
260 case 2: src
= 0x5f00ff00; break; // acid
261 case 3: src
= 0x5fff0000; break; // lava
264 int ypix
= (sy
>= vidcy1
? sy
: vidcy1
), ye
= (sy
+CELH
< vidcy2
? sy
+CELH
: vidcy2
);
265 int xpix
= (sx
>= vidcx1
? sx
: vidcx1
), xe
= (sx
+CELW
< vidcx2
? sx
+CELW
: vidcx2
);
268 src
= (src
&0xffffff)|aa
[(g_time
/2)&7];
270 src
= (src
&0xffffff)|aa
[(g_time
/2)&7];
271 //src = (src&0xffffff)|(0x5f<<24);
274 for (; ypix
< ye
; ++ypix
) {
275 Uint32
*d
= (Uint32
*)(((Uint8
*)frameSfc
->pixels
)+(ypix
*frameSfc
->pitch
)+xpix
*4);
277 const uint8_t *lm = scrlightmap+SCRW*ypix+xpix;
278 const uint8_t *vs = vscrbuf+SCRW*ypix+xpix;
279 const uint8_t *lb = lightbuf+(SCRW*LB_ITEM_SZ)*ypix+(xpix*LB_ITEM_SZ);
282 for (int h
= xpix
; h
< xe
; ++h
, ++d
/*, ++lm, ++vs, lb += LB_ITEM_SZ*/) {
284 if (*lm == LMAP_NORMAL && *lb == 0) {
285 // *d = palette[*vs];
287 // pixel_blend32(d, palette[*vs]|(64<<24));
290 pixel_blend32(d
, 0x8f000000); // darken
291 pixel_blend32(d
, src
);
303 static void Z_draw_sky (void) {
305 if (r_drawsky
&& horiz
.w
> 0) {
306 //V_pic(127-(uint16_t)(w_viewofs_x-w_view_wdt/2)*56U/(uint16_t)(MAXX-w_view_wdt/2), w_viewofs_vert+123-(uint16_t)(w_viewofs_y-w_view_hgt/2)*28U/(uint16_t)(MAXY-w_view_hgt/2), horiz);
307 vgaimg
*img
= &horiz
;
311 int y
= w_viewofs_vert
;
315 V_rotspr(x
, y
, img
, d
);
318 } while (y
< w_view_hgt
+w_viewofs_vert
);
321 } while (x
< w_view_wdt
);
323 if (sky_type
== 2 && lt_time
< 0) {
324 if (!lt_side
) V_spr(0, w_viewofs_vert
+lt_ypos
, <n
[lt_type
][lt_time
< -5 ? 0 : 1]);
325 else V_spr2(w_view_wdt
-1, w_viewofs_vert
+lt_ypos
, <n
[lt_type
][lt_time
< -5 ? 0 : 1]);
328 V_clr(0, w_view_wdt
, w_viewofs_vert
+1, w_view_hgt
, 0x97);
331 V_clr(0, w_view_wdt
, w_viewofs_vert
, w_view_hgt
, 0);
336 ////////////////////////////////////////////////////////////////////////////////
337 #define DECL_CONVAR_INT(_xname,_xdef,_xfags,_xhelp) \
338 static int _xname = (_xdef); \
339 CONVAR_INT(_xname, _xname, (_xfags), (_xhelp))
341 DECL_CONVAR_INT(r_flashlight_r
, 128, 0, "flashlight red")
342 DECL_CONVAR_INT(r_flashlight_g
, 128, 0, "flashlight green")
343 DECL_CONVAR_INT(r_flashlight_b
, 0, 0, "flashlight blue")
344 DECL_CONVAR_INT(r_flashlight_a
, 255, 0, "flashlight alpha")
348 ////////////////////////////////////////////////////////////////////////////////
349 static void Z_add_lights (player_t
*p
) {
351 Uint32 stt
= SDL_GetTicks();
352 //int ang = g_time%360*2;
353 int ang
= g_time
/2%64;
356 int lang
= sin(ang
*2*(M_PI
/32.0f
))*20;
358 //Z_add_light_sector(197, 330, 192, 35+lang, 145+lang, 255, 0, 0, 120);
359 Z_add_light_sector(197, 330, 192, 35+lang
, 145+lang
, 255, 0, 0, 128);
361 Z_add_light_sector(388, 410, 192, 35+lang
, 145+lang
, 255, 0, 0, 180);
364 int lpx = sin(ang*(M_PI/32.0f))*40;
365 int lpy = sin(ang*(M_PI/32.0f))*10;
366 Z_add_light(200+lpx, 300+lpy, 128, 255, 127, 0, 200);
370 if (r_lights_tnum
> 0 && r_lights_trad
> 2) {
371 if (r_lights_trad
> 250) r_lights_trad
= 250;
373 Z_add_light(p
->o
.x
, p
->o
.y
, 64, 0, 128, 0, 255);
374 //Z_add_light(p->o.x, p->o.y, 64, 0, 0, 0, 128);
375 //Z_add_light(197, 330, 192, 255, 0, 0, 92);
376 //Z_add_light_sector(p->o.x, p->o.y, 92, ang, ang+42, 0, 255, 0, 64);
378 //Z_add_light_sector(197, 330, 192, 90-35+ang, 90+35+ang, 255, 0, 0, 92);
379 //Z_add_light_sector(197, 360, 192, 90-35+ang, 90+35+ang, 255, 0, 0, 255);
381 //Z_add_light_sector(197, 360, 192, 90-35+ang, 90+35+ang, 255, 0, 0, 255);
382 //Z_add_light_sector(197, 360, 192, 0+ang, 35+ang, 255, 0, 0, 255);
383 //Z_add_light_sector(197, 360, 192, 0, ang%180, 255, 0, 0, 255);
384 //Z_add_light_sector(197, 360, 192, 0/*90-35+ang*/, 359/*90+35+ang*/, 255, 0, 0, 255);
386 for (int f = 0; f < 30; ++f) {
387 Z_add_light(f*64, f*64, 250, 0, 0, 255-f*10, 98);
390 for (int f
= 1; f
< r_lights_tnum
; ++f
) {
391 Z_add_light(p
->o
.x
, p
->o
.y
-8, r_lights_trad
, 0, 0, 60, 40);
394 stt
= SDL_GetTicks()-stt
;
395 //fprintf(stderr, "draw: %u msecs\n", stt);
399 for (int plnum
= 0; plnum
< g_plrcount
; ++plnum
) {
400 player_t
*p
= &pl
[plnum
];
403 if (n_host
!= NULL
&& !(g_st
== GS_GAME
&& !g_trans
&& gnet_state
== GNETS_PLAYING
)) {
409 x
= p
->o
.x
-2+(p
->st
== PLST_GO
? 5 : 0);
410 y
= p
->o
.y
-24-(p
->st
== PLST_GO
? 1 : 0);
413 if (p
->f
&PLF_UP
) { ss
-= 45; se
-= 45; }
414 else if (p
->f
&PLF_DOWN
) { ss
+= 45; se
+= 45; }
417 if (p
->f
&PLF_UP
) { x
+= 2; y
+= 4; }
418 if (p
->f
&PLF_DOWN
) { x
+= 0; y
-= 6; }
421 x
= p
->o
.x
-1-(p
->st
== PLST_GO
? 4 : 0);
422 y
= p
->o
.y
-24-(p
->st
== PLST_GO
? 1 : 0);
425 if (p
->f
&PLF_UP
) { ss
+= 45; se
+= 45; }
426 else if (p
->f
&PLF_DOWN
) { ss
-= 45; se
-= 45; }
428 if (p
->f
&PLF_UP
) { x
+= 1; y
+= 4; }
429 if (p
->f
&PLF_DOWN
) { x
+= 0; y
-= 7; }
433 while (fldhit1(x
, y
) && x
>= p
->o
.x
-6) --x
;
435 while (fldhit1(x
, y
) && x
<= p
->o
.x
+6) ++x
;
437 Z_add_light_sector_mr(x
, y
, 220, ss
, se
, r_flashlight_r
, r_flashlight_g
, r_flashlight_b
, r_flashlight_a
, 8);
444 static ccBool dbg_dump_light_time
= CC_FALSE
;
445 CONVAR_BOOL(dbg_dump_light_time
, dbg_dump_light_time
, 0, "dump lightning time")
448 ////////////////////////////////////////////////////////////////////////////////
449 void Z_light_start (void) {
455 void W_draw (player_t
*p
) {
456 //memset(vscrbuf, 0, SCRW*SCRH);
457 //memset(scrlightmap, (r_lighting ? /*LMAP_BACK*/LMAP_NORMAL : LMAP_FULLLIT), SCRW*SCRH);
460 V_setrect(0, w_view_wdt
, w_viewofs_vert
, w_view_hgt
);
462 if (r_lighting
) Z_light_start();
465 Z_drawfld((const uint8_t *)fldb
, 1);
472 if (n_host
== NULL
) {
473 for (int f
= 0; f
< g_plrcount
; ++f
) PL_draw(&pl
[f
]);
475 if (g_st
== GS_GAME
&& !g_trans
&& gnet_state
== GNETS_PLAYING
) {
476 for (int f
= 0; f
< g_plrcount
; ++f
) PL_draw(&pl
[f
]);
478 PL_draw(&pl
[n_local_player_num
]);
484 Z_drawfld((const uint8_t *)fldf
, 0);
487 Uint32 st
= SDL_GetTicks();
491 lb_draw(0, w_viewofs_vert
, w_view_wdt
, w_view_hgt
);
492 if (dbg_dump_light_time
) {
493 st
= SDL_GetTicks()-st
;
494 fprintf(stderr
, "light time: %u ms\n", st
);
497 lbx_draw(0, w_viewofs_vert
, w_view_wdt
, w_view_hgt
);
501 if (sky_type
== 2 && (lt_time
== -4 || lt_time
== -2)) V_remap_rect(0, w_view_wdt
, w_viewofs_vert
+1, w_view_hgt
, clrmap
+256*11);
503 V_setrect(0, SCRW
, 0, SCRH
);
507 ////////////////////////////////////////////////////////////////////////////////
509 Z_reset_level_lights();
511 for (int i
= 1; i
< ANIT
; ++i
) {
514 for (j
= 0; anm
[i
-1][j
]; ++j
) {
515 anih
[i
][j
] = F_getresid(anm
[i
-1][j
]);
516 V_loadvga(anm
[i
-1][j
], &anispr
[i
][j
]);
518 for (; j
< 5; ++j
) anih
[i
][j
] = -1;
521 memset(anic
, 0, sizeof(anic
));
522 cheatNoBack
= cheatNoFront
= CC_FALSE
;
533 //horiz = M_lock(F_getresid("RSKY1"));
534 V_loadvga("RSKY1", &horiz
);
538 m_notarget
= CC_FALSE
;
542 static void fix_anim (void) {
545 for (int f
= 1; f
< 256; ++f
) {
548 walp
[f
] = &walpix
[f
];
549 if (a
!= 0) walp
[f
] = &anispr
[a
][anic
[a
]];
555 if (g_time
%3 != 0) return;
557 for (int f
= 1; f
< 256; ++f
) {
561 if (anih
[a
][++anic
[a
]] == -1) anic
[a
] = 0;
562 //walp[f] = M_lock(anih[a][anic[a]]);
563 //fprintf(stderr, "f=%d; a=%d; anic=%u; anih=%d\n", f, a, anic[a], anih[a][anic[a]]);
564 walp
[f
] = &anispr
[a
][anic
[a
]];
565 //walp[f]->wanim = 666;
571 ////////////////////////////////////////////////////////////////////////////////
572 static wall_t w_wallnames
[256];
574 static int W_mapload_wallnames (MemBuffer
*mbuf
, const map_block_t
*blk
) {
575 if (mbuf
== NULL
) return 0; // no post-processing
581 for (f
= 0; f
< 256; ++f
) {
586 memset(w_wallnames
, 0, sizeof(w_wallnames
));
588 for (f
= 1; f
< 256 && sz
> 0; ++f
, sz
-= sizeof(w
)) {
589 if (membuf_read_full(mbuf
, &w
, sizeof(w
)) < 0) return -1;
592 if (strncasecmp(w
.n
, "_WATER_", 7) == 0) {
593 // animated water/laval/acid texture
594 V_freevga(&walpix
[f
]);
595 walpix
[f
].wanim
= (w
.n
[7]-'0'+1);
599 walh
[f
] = F_getresid(w
.n
);
600 V_loadvga(w
.n
, &walpix
[f
]);
601 if (w
.n
[0] == 'S' && w
.n
[1] == 'W' && w
.n
[4] == '_') walswp
[f
] = 0;
602 walf
[f
] = (w
.t
? 1 : 0);
603 if (w
.t
) walh
[f
] |= 0x8000;
604 if (strncasecmp(w
.n
, "VTRAP01", 8) == 0) walf
[f
] |= 2;
605 walani
[f
] = getani(w
.n
);
608 for (c
= f
, f
= 1; f
< 256; ++f
) {
609 if (walswp
[f
] == 0) {
613 F_getresname(w
.n
, walh
[f
]&0x7FFF);
615 g
= F_getresid(w
.n
)|(walh
[f
]&0x8000);
616 for (k
= 1; k
< 256; ++k
) if (walh
[k
] == g
) break;
619 V_loadvga(w
.n
, &walpix
[k
]);// = M_lock(g);
620 walf
[k
] = (g
&0x8000)?1:0;
632 static int W_mapload_sky (MemBuffer
*mbuf
, const map_block_t
*blk
) {
635 if (mbuf
== NULL
) return 0; // no post-processing
637 memset(n
, 0, sizeof(n
));
638 sky_type
= membuf_read_ui16(mbuf
);
639 if (sky_type
> 2) sky_type
= 0;
642 V_loadvga(n
, &horiz
);
648 static void rle_unpack (const void *buf
, int len
, void *obuf
) {
653 for (p
= (const uint8_t *)buf
, o
= (uint8_t *)obuf
, l
= len
; l
; ++p
, --l
) {
655 n
= *((const uint16_t *)(++p
));
656 memset(o
, *(p
+= 2), n
);
666 // fill tiles occupied by big textures
667 static int postprocess_field (uint8_t *fld
) {
671 memset(reported
, 0, sizeof(reported
));
673 for (int y
= 0; y
< FLDH
; ++y
) {
674 for (int x
= 0; x
< FLDW
; ++x
, ++fp
) {
677 conlogf("too many different tiles on level!\n");
682 // let's fill this with 255, so light will have something to lit
683 // for foreground tiles -- mark as 'unoccupied'
686 const vgaimg
*pic
= walp
[*fp
];
688 if (pic
== NULL
|| pic
->w
< 1) {
689 if (!reported
[*fp
]) {
695 memcpy(n
, w_wallnames
[*fp
].n
, 8);
696 if (strncasecmp(n
, "_water_", 7) != 0) {
697 conlogf("invalid texture on level: %u! [%s]\n", *fp
, n
);
710 for (int y
= 0; y
< FLDH
; ++y
) {
711 for (int x
= 0; x
< FLDW
; ++x
, ++fp
) {
712 if (*fp
> 0 && *fp
< 255) {
713 // this is textured tile, let's try to mark adjacent tiles as used if necessary
714 const vgaimg
*pic
= walp
[*fp
];
716 if (pic
!= NULL
&& pic
->w
> 0 && pic
->wanim
<= 0) {
717 int sx
= x
*CELW
-pic
->sx
, ex
= sx
+pic
->w
;
718 int sy
= y
*CELH
-pic
->sy
, ey
= sy
+pic
->h
;
720 for (int yy
= sy
; yy
< ey
; yy
+= CELH
) {
721 for (int xx
= sx
; xx
< ex
; xx
+= CELW
) {
722 int fx
= xx
/CELW
, fy
= yy
/CELH
;
724 if (fx
>= 0 && fx
< FLDW
&& fy
>= 0 && fy
< FLDH
) {
725 uint8_t *ff
= fld
+fy
*FLDW
+fx
;
727 if (*ff
== 255) *ff
= 0; // this tile is 'occupied'
740 static int W_mapload_field (MemBuffer
*mbuf
, const map_block_t
*blk
, uint8_t *fld
) {
745 if (membuf_read_full(mbuf
, fld
, FLDW
*FLDH
) < 0) return -1;
748 if ((buf
= malloc(blk
->sz
)) == NULL
) {
749 conlogf("map loader: out of memory!\n");
752 if (membuf_read_full(mbuf
, buf
, blk
->sz
) < 0) { free(buf
); return -1; }
753 rle_unpack(buf
, blk
->sz
, fld
);
763 static int W_mapload_back (MemBuffer
*mbuf
, const map_block_t
*blk
) {
764 if (mbuf
== NULL
) return postprocess_field(fldb
);
766 return W_mapload_field(mbuf
, blk
, fldb
);
769 static int W_mapload_front (MemBuffer
*mbuf
, const map_block_t
*blk
) {
770 if (mbuf
== NULL
) return postprocess_field(fldf
);
772 return W_mapload_field(mbuf
, blk
, fldf
);
775 static int W_mapload_wtype (MemBuffer
*mbuf
, const map_block_t
*blk
) {
776 if (mbuf
== NULL
) return 0; // no post-processing
778 return W_mapload_field(mbuf
, blk
, fldm
);
782 ////////////////////////////////////////////////////////////////////////////////
783 static int W_savegame (MemBuffer
*mbuf
, int waserror
) {
785 membuf_write_ui8(mbuf
, 0); // version
786 membuf_write_ui16(mbuf
, FLDW
);
787 membuf_write_ui16(mbuf
, FLDH
);
788 membuf_write_ui8(mbuf
, sky_type
&0x7f);
790 for (int f
= 1; f
< 256; ++f
) {
794 membuf_write(mbuf
, s
, 8);
797 membuf_write(mbuf
, walf
, sizeof(walf
));
798 membuf_write(mbuf
, walswp
, sizeof(walswp
));
799 membuf_write(mbuf
, fldb
, FLDW
*FLDH
);
800 membuf_write(mbuf
, fldm
, FLDW
*FLDH
);
801 membuf_write(mbuf
, fldf
, FLDW
*FLDH
);
808 static int W_loadgame (MemBuffer
*mbuf
, int waserror
) {
813 if (membuf_read_ui8(mbuf
) != 0) {
814 conlogf("LOADGAME ERROR: invalid map version!\n");
817 w
= membuf_read_ui16(mbuf
);
818 h
= membuf_read_ui16(mbuf
);
819 if (w
< 1 || w
> 32767 || h
< 1 || h
> 32767) {
820 conlogf("LOADGAME ERROR: invalid map size!\n");
823 W_set_field_size(w
, h
);
824 sky_type
= membuf_read_ui8(mbuf
);
826 conlogf("LOADGAME WARNING: invalid sky!\n");
830 for (int f
= 1; f
< 256; ++f
) {
831 memset(s
, 0, sizeof(s
));
833 walp
[f
] = &walpix
[f
];
834 if (membuf_read_full(mbuf
, s
, 8) < 0) return -1;
837 V_freevga(&walpix
[f
]);
841 walani
[f
] = getani(s
);
842 if (strncasecmp(s
, "_WATER_", 7) == 0) {
844 walpix
[f
].wanim
= (s
[7]-'0'+1);
846 walh
[f
] = F_getresid(s
);
847 V_loadvga(s
, &walpix
[f
]);
851 membuf_read_full(mbuf
, walf
, sizeof(walf
));
852 for (int f
= 1; f
< 256; ++f
) if (walf
[f
]&1) walh
[f
] |= 0x8000;
853 membuf_read_full(mbuf
, walswp
, sizeof(walswp
));
854 membuf_read_full(mbuf
, fldb
, FLDW
*FLDH
);
855 membuf_read_full(mbuf
, fldm
, FLDW
*FLDH
);
856 membuf_read_full(mbuf
, fldf
, FLDW
*FLDH
);
860 V_loadvga(s
, &horiz
);
869 ////////////////////////////////////////////////////////////////////////////////
870 GCC_CONSTRUCTOR_USER
{
871 for (size_t f
= 0; f
< sizeof(ltn
)/sizeof(ltn
[0]); ++f
) { V_initvga(<n
[f
][0]); V_initvga(<n
[f
][1]); }
872 for (size_t f
= 0; f
< sizeof(walpix
)/sizeof(walpix
[0]); ++f
) V_initvga(&walpix
[f
]);
873 for (size_t f
= 0; f
< sizeof(anih
)/sizeof(anih
[0]); ++f
) {
874 V_initvga(&anispr
[f
][0]);
875 V_initvga(&anispr
[f
][1]);
876 V_initvga(&anispr
[f
][2]);
877 V_initvga(&anispr
[f
][3]);
878 V_initvga(&anispr
[f
][4]);
882 _light_constructor_();
884 F_registerMapLoad(MB_WALLNAMES
, W_mapload_wallnames
, NULL
);
885 F_registerMapLoad(MB_BACK
, W_mapload_back
, NULL
);
886 F_registerMapLoad(MB_WTYPE
, W_mapload_wtype
, NULL
);
887 F_registerMapLoad(MB_FRONT
, W_mapload_front
, NULL
);
888 F_registerMapLoad(MB_SKY
, W_mapload_sky
, NULL
);
890 F_registerSaveLoad("LEVELMAPS", W_savegame
, W_loadgame
, SAV_NORMAL
);
891 F_registerSaveLoad("LEVELLIGHTS", W_savelights
, W_loadlights
, SAV_OPTIONAL
);
895 GCC_DESTRUCTOR_USER
{
896 for (size_t f
= 0; f
< sizeof(ltn
)/sizeof(ltn
[0]); ++f
) { V_freevga(<n
[f
][0]); V_freevga(<n
[f
][1]); }
897 for (size_t f
= 0; f
< sizeof(walpix
)/sizeof(walpix
[0]); ++f
) V_freevga(&walpix
[f
]);
898 for (size_t f
= 0; f
< sizeof(anih
)/sizeof(anih
[0]); ++f
) {
899 V_freevga(&anispr
[f
][0]);
900 V_freevga(&anispr
[f
][1]);
901 V_freevga(&anispr
[f
][2]);
902 V_freevga(&anispr
[f
][3]);
903 V_freevga(&anispr
[f
][4]);