ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
(Generate patch)

Comparing deliantra/Deliantra-Client/Client.xs (file contents):
Revision 1.295 by root, Mon Dec 21 03:30:22 2009 UTC vs.
Revision 1.327 by root, Sun Nov 18 12:01:50 2018 UTC

15 15
16#include "EXTERN.h" 16#include "EXTERN.h"
17#include "perl.h" 17#include "perl.h"
18#include "XSUB.h" 18#include "XSUB.h"
19 19
20#include "flat_hash_map.hpp"
21
20#ifdef _WIN32 22#ifdef _WIN32
21# undef pipe 23# undef pipe
22// microsoft vs. C 24// microsoft vs. C
23# define sqrtf(x) sqrt(x) 25# define sqrtf(x) sqrt(x)
24# define atan2f(x,y) atan2(x,y) 26# define atan2f(x,y) atan2(x,y)
25# define M_PI 3.14159265f 27# define M_PI 3.14159265f
26#endif 28#endif
27 29
28#include <assert.h> 30#include <cassert>
29#include <math.h> 31#include <cmath>
30#include <string.h> 32#include <cstring>
31#include <stdio.h> 33#include <cstdio>
32#include <stdlib.h> 34#include <cstdlib>
35
36#include <utility>
37#include <bitset>
33 38
34#define USE_RWOPS 1 // for SDL_mixer:LoadMUS_RW 39#define USE_RWOPS 1 // for SDL_mixer:LoadMUS_RW
35 40
36#include <SDL.h> 41#include <SDL.h>
37#include <SDL_thread.h> 42#include <SDL_thread.h>
41#include <SDL_opengl.h> 46#include <SDL_opengl.h>
42 47
43/* work around os x broken headers */ 48/* work around os x broken headers */
44#ifdef __MACOSX__ 49#ifdef __MACOSX__
45typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); 50typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
51typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
52typedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t);
46#endif 53#endif
47 54
48#define PANGO_ENABLE_BACKEND 55#define PANGO_ENABLE_BACKEND
49#define G_DISABLE_CAST_CHECKS 56#define G_DISABLE_CAST_CHECKS
50 57
51#include <glib/gmacros.h> 58#include <glib.h>
52 59
53#include <pango/pango.h> 60#include <pango/pango.h>
54 61
55#ifndef PANGO_VERSION_CHECK 62#ifndef PANGO_VERSION_CHECK
56# define PANGO_VERSION_CHECK(a,b,c) 0 63# define PANGO_VERSION_CHECK(a,b,c) 0
80#define expect_false(expr) expect ((expr) != 0, 0) 87#define expect_false(expr) expect ((expr) != 0, 0)
81#define expect_true(expr) expect ((expr) != 0, 1) 88#define expect_true(expr) expect ((expr) != 0, 1)
82 89
83#define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, object replacement character */ 90#define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, object replacement character */
84 91
92/* this is used as fow flag as well, so has to have a different value */
93/* then anything that is computed by incoming darkness */
85#define FOW_DARKNESS 64 94#define FOW_DARKNESS 50
86#define DARKNESS_ADJUST(n) ((29 * (int)(n)) >> 5) /* times 0.9 */ 95#define DARKNESS_ADJUST(n) (n)
87 96
88#define MAP_EXTEND_X 32 97#define MAP_EXTEND_X 32
89#define MAP_EXTEND_Y 512 98#define MAP_EXTEND_Y 512
90 99
91#define MIN_FONT_HEIGHT 10 100#define MIN_FONT_HEIGHT 10
95 104
96#define KMOD_LRAM 0x10000 // our extension 105#define KMOD_LRAM 0x10000 // our extension
97 106
98#define TEXID_SPEECH 1 107#define TEXID_SPEECH 1
99#define TEXID_NOFACE 2 108#define TEXID_NOFACE 2
100#define TEXID_HIDDEN 3 109
110static char *
111fast_sv_grow (SV *sv, STRLEN need)
112{
113 STRLEN len = SvLEN (sv);
114 STRLEN want = SvCUR (sv) + need;
115
116 if (expect_false (len < want))
117 {
118 do
119 len *= 2;
120 while (len < want);
121
122 sv_grow (sv, len);
123 }
124
125 SvCUR_set (sv, want);
126 return SvEND (sv) - need;
127}
101 128
102static AV *texture_av; 129static AV *texture_av;
103 130
104static struct 131static struct
105{ 132{
162{ 189{
163 GSList *attrs = run->item->analysis.extra_attrs; 190 GSList *attrs = run->item->analysis.extra_attrs;
164 191
165 while (attrs) 192 while (attrs)
166 { 193 {
167 PangoAttribute *attr = attrs->data; 194 PangoAttribute *attr = (PangoAttribute *)attrs->data;
168 195
169 if (attr->klass->type == PANGO_ATTR_SHAPE) 196 if (attr->klass->type == PANGO_ATTR_SHAPE)
170 return 1; 197 return 1;
171 198
172 attrs = attrs->next; 199 attrs = attrs->next;
173 } 200 }
174 201
175 return 0; 202 return 0;
176} 203}
177 204
178typedef struct cf_layout { 205struct cf_layout {
179 PangoLayout *pl; 206 PangoLayout *pl;
180 float r, g, b, a; // default color for rgba mode 207 float r, g, b, a; // default color for rgba mode
181 int base_height; 208 int base_height;
182 DC__Font font; 209 DC__Font font;
183 rc_t *rc; 210 rc_t rc;
184} *DC__Layout; 211};
212
213typedef cf_layout *DC__Layout;
185 214
186static DC__Font default_font; 215static DC__Font default_font;
187static PangoContext *opengl_context; 216static PangoContext *opengl_context;
188static PangoFontMap *opengl_fontmap; 217static PangoFontMap *opengl_fontmap;
189 218
190static void 219static void
191substitute_func (FcPattern *pattern, gpointer data) 220substitute_func (FcPattern *pattern, gpointer data)
192{ 221{
193 FcPatternAddBool (pattern, FC_HINTING, 1); 222 FcPatternAddBool (pattern, FC_HINTING, 1);
194#ifdef FC_HINT_STYLE 223#ifdef FC_HINT_STYLE
195 FcPatternAddBool (pattern, FC_HINT_STYLE, FC_HINT_FULL); 224 FcPatternAddInteger (pattern, FC_HINT_STYLE, FC_HINT_FULL);
196#endif 225#endif
197 FcPatternAddBool (pattern, FC_AUTOHINT, 0); 226 FcPatternAddBool (pattern, FC_AUTOHINT, 0);
198} 227}
199 228
200static void 229static void
230} 259}
231 260
232typedef uint16_t tileid; 261typedef uint16_t tileid;
233typedef uint16_t faceid; 262typedef uint16_t faceid;
234 263
235typedef struct { 264struct maptex
265{
236 GLuint name; 266 GLuint name;
237 int w, h; 267 int w, h;
238 float s, t; 268 float s, t;
239 uint8_t r, g, b, a; 269 uint8_t r, g, b, a;
240 tileid smoothtile; 270 tileid smoothtile;
241 uint8_t smoothlevel; 271 uint8_t smoothlevel;
242 uint8_t unused; /* set to zero on use */ 272 uint8_t unused; /* set to zero on use */
243} maptex; 273};
244 274
245typedef struct { 275struct mapcell
276{
246 uint32_t player; 277 uint32_t player;
247 tileid tile[3]; 278 tileid tile[3];
248 uint16_t darkness; 279 uint16_t darkness;
249 uint8_t stat_width, stat_hp, flags, smoothmax; 280 uint8_t stat_width, stat_hp, flags, smoothmax;
250} mapcell; 281};
251 282
252typedef struct { 283struct maprow
284{
253 int32_t c0, c1; 285 int32_t c0, c1;
254 mapcell *col; 286 mapcell *col;
255} maprow; 287};
256 288
257typedef struct map { 289struct mapgrid {
258 int x, y, w, h; 290 int x, y, w, h;
259 int ox, oy; /* offset to virtual global coordinate system */ 291 int ox, oy; /* offset to virtual global coordinate system */
260 int faces; tileid *face2tile; // [faceid] 292 std::vector<tileid> tile;
261 int texs; maptex *tex; // [tileid] 293 std::vector<maptex> tex;
262 294
263 int32_t rows; 295 int32_t rows;
264 maprow *row; 296 maprow *row;
265} *DC__Map; 297
298 ~mapgrid ()
299 {
300 clear_cells ();
301 }
302
303 void clear_cells ();
304};
305
306typedef mapgrid *DC__Map;
266 307
267static char * 308static char *
268prepend (char *ptr, int sze, int inc) 309prepend (char *ptr, int sze, int inc)
269{ 310{
270 char *p; 311 char *p;
287} 328}
288 329
289#define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type)) 330#define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
290#define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type)) 331#define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
291 332
292static void
293need_facenum (struct map *self, faceid face)
294{
295 while (self->faces <= face)
296 {
297 Append (tileid, self->face2tile, self->faces, self->faces);
298 self->faces *= 2;
299 }
300}
301
302static void
303need_texid (struct map *self, int texid)
304{
305 while (self->texs <= texid)
306 {
307 Append (maptex, self->tex, self->texs, self->texs);
308 self->texs *= 2;
309 }
310}
311
312static maprow * 333static maprow *
313map_get_row (DC__Map self, int y) 334map_get_row (mapgrid *self, int y)
314{ 335{
315 if (0 > y) 336 if (0 > y)
316 { 337 {
317 int extend = - y + MAP_EXTEND_Y; 338 int extend = - y + MAP_EXTEND_Y;
318 Prepend (maprow, self->row, self->rows, extend); 339 Prepend (maprow, self->row, self->rows, extend);
356 377
357 return row->col + (x - row->c0); 378 return row->col + (x - row->c0);
358} 379}
359 380
360static mapcell * 381static mapcell *
361map_get_cell (DC__Map self, int x, int y) 382map_get_cell (mapgrid *self, int x, int y)
362{ 383{
363 return row_get_cell (map_get_row (self, y), x); 384 return row_get_cell (map_get_row (self, y), x);
364} 385}
365 386
366static void 387void mapgrid::clear_cells ()
367map_clear (DC__Map self)
368{ 388{
369 int r; 389 int r;
370 390
371 for (r = 0; r < self->rows; r++) 391 for (r = 0; r < rows; r++)
372 Safefree (self->row[r].col); 392 Safefree (row[r].col);
373 393
374 Safefree (self->row); 394 Safefree (row);
375 395
376 self->x = 0; 396 x = 0;
377 self->y = 0; 397 y = 0;
378 self->ox = 0; 398 ox = 0;
379 self->oy = 0; 399 oy = 0;
380 self->row = 0; 400 row = 0;
381 self->rows = 0; 401 rows = 0;
382} 402}
383 403
384#define CELL_CLEAR(cell) \ 404#define CELL_CLEAR(cell) \
385 do { \ 405 do { \
386 if ((cell)->player) \ 406 if ((cell)->player) \
390 (cell)->flags = 0; \ 410 (cell)->flags = 0; \
391 (cell)->player = 0; \ 411 (cell)->player = 0; \
392 } while (0) 412 } while (0)
393 413
394static void 414static void
395map_blank (DC__Map self, int x0, int y0, int w, int h) 415map_blank (mapgrid *self, int x0, int y0, int w, int h)
396{ 416{
397 int x, y; 417 int x, y;
398 maprow *row; 418 maprow *row;
399 mapcell *cell; 419 mapcell *cell;
400 420
417 CELL_CLEAR (cell); 437 CELL_CLEAR (cell);
418 } 438 }
419 } 439 }
420} 440}
421 441
422typedef struct { 442struct smooth_key
443{
423 tileid tile; 444 tileid tile;
424 uint8_t x, y, level; 445 uint8_t x, y, level;
425} smooth_key; 446
447 bool operator == (const smooth_key &o) const
448 {
449 return tile == o.tile && x == o.x && y == o.y && level == o.level;
450 }
451};
452
453typedef ska::flat_hash_map<smooth_key, IV> smooth_hash;
454
455namespace std {
456 template <>
457 struct hash<smooth_key>
458 {
459 size_t operator () (const smooth_key &v) const
460 {
461 return v.tile + (v.x << 8) + (v.y << 16) + (v.level << 24);
462 }
463 };
464}
426 465
427static void 466static void
428smooth_or_bits (HV *hv, smooth_key *key, IV bits) 467smooth_or_bits (smooth_hash &h, smooth_key &key, IV bits)
429{ 468{
430 SV **sv = hv_fetch (hv, (char *)key, sizeof (*key), 1); 469 auto &&it = h.find (key);
431 470
432 if (SvIOK (*sv)) 471 if (it == h.end ())
433 SvIV_set (*sv, SvIVX (*sv) | bits); 472 h.insert (std::make_pair (key, bits));
434 else 473 else
435 sv_setiv (*sv, bits); 474 it->second |= bits;
436} 475}
437 476
438static void 477static void
439music_finished (void) 478music_finished (void)
440{ 479{
457 ev.code = 1; 496 ev.code = 1;
458 ev.data1 = (void *)(long)channel; 497 ev.data1 = (void *)(long)channel;
459 ev.data2 = 0; 498 ev.data2 = 0;
460 499
461 SDL_PushEvent ((SDL_Event *)&ev); 500 SDL_PushEvent ((SDL_Event *)&ev);
501}
502
503// approximately divide by 255
504static unsigned int
505div255 (unsigned int n)
506{
507 return (n + (n >> 8)) >> 8;
462} 508}
463 509
464static unsigned int 510static unsigned int
465minpot (unsigned int n) 511minpot (unsigned int n)
466{ 512{
549 595
550 return mod; 596 return mod;
551} 597}
552 598
553static void 599static void
554deliantra_main () 600deliantra_main (SV *real_main)
555{ 601{
556 char *argv[] = { 0 }; 602 dSP;
557 call_argv ("::main", G_DISCARD | G_VOID, argv); 603
604 PUSHMARK (SP);
605 call_sv (real_main, G_DISCARD | G_VOID);
558} 606}
559 607
560#ifdef __MACOSX__ 608#ifdef __MACOSX__
609 static SV *real_main;
610
561 /* to due surprising braindamage on the side of SDL design, we 611 /* to due surprising braindamage on the side of SDL design, we
562 * do some mind-boggling hack here: SDL requires a custom main() 612 * do some mind-boggling hack here: SDL requires a custom main()
563 * on OS X, so... we provide one and call the original main(), which, 613 * on OS X, so... we provide one and call the original main(), which,
564 * due to share dlibrary magic, calls -lSDLmain's main, not perl's main, 614 * due to shared library magic, calls -lSDLmain's main, not perl's main,
565 * and which calls our main (== SDL_main) back. 615 * and which calls our main (== SDL_main) back.
566 */ 616 */
567 extern C_LINKAGE int 617 extern C_LINKAGE int
568 main (int argc, char *argv[]) 618 main (int argc, char *argv[])
569 { 619 {
570 deliantra_main (); 620 deliantra_main (real_main);
571 } 621 }
572 622
573 #undef main 623 #undef main
574 624
575 extern C_LINKAGE int main (int argc, char *argv[]); 625 extern C_LINKAGE int main (int argc, char *argv[]);
576 626
577 static void 627 static void
578 SDL_braino (void) 628 SDL_main_hack (SV *real_main_)
579 { 629 {
630 real_main = real_main_;
631
580 char *argv[] = { "deliantra client", 0 }; 632 char *argv[] = { "deliantra client", 0 };
581 (main) (1, argv); 633 (main) (1, argv);
582 } 634 }
583#else 635#else
584 static void 636 static void
585 SDL_braino (void) 637 SDL_main_hack (SV *real_main)
586 { 638 {
587 deliantra_main (); 639 deliantra_main (real_main);
588 } 640 }
589#endif 641#endif
590 642
591MODULE = Deliantra::Client PACKAGE = DC 643MODULE = Deliantra::Client PACKAGE = DC
592 644
793 845
794 const_iv (FOW_DARKNESS) 846 const_iv (FOW_DARKNESS)
795# undef const_iv 847# undef const_iv
796 }; 848 };
797 849
798 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) 850 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--)
799 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 851 newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv));
800 852
801 assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK); 853 assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK);
802 assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE); 854 assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE);
803} 855}
804 856
843#endif 895#endif
844} 896}
845 897
846char *SDL_GetError () 898char *SDL_GetError ()
847 899
848void SDL_braino () 900void SDL_main_hack (SV *real_main)
901 PROTOTYPE: &
849 902
850int SDL_Init (U32 flags) 903int SDL_Init (U32 flags)
851 904
852int SDL_InitSubSystem (U32 flags) 905int SDL_InitSubSystem (U32 flags)
853 906
854void SDL_QuitSubSystem (U32 flags) 907void SDL_QuitSubSystem (U32 flags)
855 908
856void SDL_Quit () 909void SDL_Quit ()
857 910
858int SDL_GL_SetAttribute (int attr, int value) 911int SDL_GL_SetAttribute (int attr, int value)
912 C_ARGS: (SDL_GLattr)attr, value
859 913
860int SDL_GL_GetAttribute (int attr) 914int SDL_GL_GetAttribute (int attr)
861 CODE: 915 CODE:
862 if (SDL_GL_GetAttribute (attr, &RETVAL)) 916 if (SDL_GL_GetAttribute ((SDL_GLattr)attr, &RETVAL))
863 XSRETURN_UNDEF; 917 XSRETURN_UNDEF;
864 OUTPUT: 918 OUTPUT:
865 RETVAL 919 RETVAL
866 920
867void 921void
922 ); 976 );
923 977
924 if (RETVAL) 978 if (RETVAL)
925 { 979 {
926 av_clear (texture_av); 980 av_clear (texture_av);
927
928 SDL_WM_SetCaption ("Deliantra MORPG Client " VERSION, "Deliantra");
929#define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name); 981#define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name);
930#include "glfunc.h" 982#include "glfunc.h"
931#undef GL_FUNC 983#undef GL_FUNC
984 if (!gl.ActiveTexture ) gl.ActiveTexture = gl.ActiveTextureARB;
985 if (!gl.MultiTexCoord2f) gl.MultiTexCoord2f = gl.MultiTexCoord2fARB;
932 } 986 }
933} 987}
934 OUTPUT: 988 OUTPUT:
935 RETVAL 989 RETVAL
990
991void
992SDL_WM_SetCaption (const char *title, const char *icon)
936 993
937void 994void
938SDL_GL_SwapBuffers () 995SDL_GL_SwapBuffers ()
939 996
940char * 997char *
941SDL_GetKeyName (int sym) 998SDL_GetKeyName (int sym)
999 C_ARGS: (SDLKey)sym
942 1000
943int 1001int
944SDL_GetAppState () 1002SDL_GetAppState ()
945 1003
946int 1004int
947SDL_GetModState () 1005SDL_GetModState ()
948 1006
1007int
1008SDL_WaitEvent ()
1009 C_ARGS: 0
1010
949void 1011void
1012SDL_PumpEvents ()
1013
1014void
950poll_events () 1015peep_events ()
951 PPCODE: 1016 PPCODE:
952{ 1017{
953 SDL_Event ev; 1018 SDL_Event ev;
954 1019
955 SDL_PumpEvents (); 1020 SDL_PumpEvents ();
1021 1086
1022 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("DC::UI::Event", 1)))); 1087 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("DC::UI::Event", 1))));
1023 } 1088 }
1024} 1089}
1025 1090
1091char *
1092SDL_AudioDriverName ()
1093 CODE:
1094{
1095 char buf [256];
1096 if (!SDL_AudioDriverName (buf, sizeof (buf)))
1097 XSRETURN_UNDEF;
1098
1099 RETVAL = buf;
1100}
1101 OUTPUT:
1102 RETVAL
1103
1026int 1104int
1027Mix_OpenAudio (int frequency = 44100, int format = MIX_DEFAULT_FORMAT, int channels = 2, int chunksize = 4096) 1105Mix_OpenAudio (int frequency = 44100, int format = MIX_DEFAULT_FORMAT, int channels = 2, int chunksize = 4096)
1028 POSTCALL: 1106 POSTCALL:
1029 Mix_HookMusicFinished (music_finished); 1107 Mix_HookMusicFinished (music_finished);
1030 Mix_ChannelFinished (channel_finished); 1108 Mix_ChannelFinished (channel_finished);
1031 1109
1032void 1110void
1033Mix_QuerySpec () 1111Mix_QuerySpec ()
1092add_font (char *file) 1170add_font (char *file)
1093 CODE: 1171 CODE:
1094 RETVAL = FcConfigAppFontAddFile (0, (const FcChar8 *)file); 1172 RETVAL = FcConfigAppFontAddFile (0, (const FcChar8 *)file);
1095 OUTPUT: 1173 OUTPUT:
1096 RETVAL 1174 RETVAL
1175
1176void
1177IMG_Init (int flags = IMG_INIT_JPG | IMG_INIT_PNG)
1178
1179# MIX_INIT_MP3 gives smpeg + libstdc++ + libgcc_s
1180void
1181Mix_Init (int flags = MIX_INIT_MOD | MIX_INIT_OGG)
1097 1182
1098void 1183void
1099load_image_inline (SV *image_) 1184load_image_inline (SV *image_)
1100 ALIAS: 1185 ALIAS:
1101 load_image_file = 1 1186 load_image_file = 1
1147 1232
1148 SDL_LockSurface (surface2); 1233 SDL_LockSurface (surface2);
1149 EXTEND (SP, 6); 1234 EXTEND (SP, 6);
1150 PUSHs (sv_2mortal (newSViv (surface2->w))); 1235 PUSHs (sv_2mortal (newSViv (surface2->w)));
1151 PUSHs (sv_2mortal (newSViv (surface2->h))); 1236 PUSHs (sv_2mortal (newSViv (surface2->h)));
1152 PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch))); 1237 PUSHs (sv_2mortal (newSVpvn ((const char *)surface2->pixels, surface2->h * surface2->pitch)));
1153 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB))); 1238 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
1154 PUSHs (sv_2mortal (newSViv (GL_RGBA))); 1239 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
1155 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE))); 1240 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
1156 SDL_UnlockSurface (surface2); 1241 SDL_UnlockSurface (surface2);
1157 1242
1229MODULE = Deliantra::Client PACKAGE = DC::Font 1314MODULE = Deliantra::Client PACKAGE = DC::Font
1230 1315
1231PROTOTYPES: DISABLE 1316PROTOTYPES: DISABLE
1232 1317
1233DC::Font 1318DC::Font
1234new_from_file (SV *class, char *path, int id = 0) 1319new_from_file (SV *klass, char *path, int id = 0)
1235 CODE: 1320 CODE:
1236{ 1321{
1237 int count; 1322 int count;
1238 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count); 1323 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count);
1239 RETVAL = pango_fc_font_description_from_pattern (pattern, 0); 1324 RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
1268 PROTOTYPE: 1353 PROTOTYPE:
1269 CODE: 1354 CODE:
1270 tc_restore (); 1355 tc_restore ();
1271 1356
1272DC::Layout 1357DC::Layout
1273new (SV *class) 1358new (SV *klass)
1274 CODE: 1359 CODE:
1275 New (0, RETVAL, 1, struct cf_layout); 1360 RETVAL = new cf_layout;
1276 1361
1277 RETVAL->pl = pango_layout_new (opengl_context); 1362 RETVAL->pl = pango_layout_new (opengl_context);
1278 RETVAL->r = 1.; 1363 RETVAL->r = 1.;
1279 RETVAL->g = 1.; 1364 RETVAL->g = 1.;
1280 RETVAL->b = 1.; 1365 RETVAL->b = 1.;
1281 RETVAL->a = 1.; 1366 RETVAL->a = 1.;
1282 RETVAL->base_height = MIN_FONT_HEIGHT; 1367 RETVAL->base_height = MIN_FONT_HEIGHT;
1283 RETVAL->font = 0; 1368 RETVAL->font = 0;
1284 RETVAL->rc = rc_alloc ();
1285 1369
1286 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR); 1370 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
1287 layout_update_font (RETVAL); 1371 layout_update_font (RETVAL);
1288 OUTPUT: 1372 OUTPUT:
1289 RETVAL 1373 RETVAL
1290 1374
1291void 1375void
1292DESTROY (DC::Layout self) 1376DESTROY (DC::Layout self)
1293 CODE: 1377 CODE:
1294 g_object_unref (self->pl); 1378 g_object_unref (self->pl);
1295 rc_free (self->rc);
1296 Safefree (self); 1379 delete self;
1297 1380
1298void 1381void
1299set_text (DC::Layout self, SV *text_) 1382set_text (DC::Layout self, SV *text_)
1300 CODE: 1383 CODE:
1301{ 1384{
1427 1510
1428void 1511void
1429set_height (DC::Layout self, int base_height) 1512set_height (DC::Layout self, int base_height)
1430 CODE: 1513 CODE:
1431 if (self->base_height != base_height) 1514 if (self->base_height != base_height)
1432 { 1515 {
1433 self->base_height = base_height; 1516 self->base_height = base_height;
1434 layout_update_font (self); 1517 layout_update_font (self);
1435 } 1518 }
1436 1519
1437void 1520void
1555} 1638}
1556 1639
1557void 1640void
1558render (DC::Layout self, float x, float y, int flags = 0) 1641render (DC::Layout self, float x, float y, int flags = 0)
1559 CODE: 1642 CODE:
1560 rc_clear (self->rc); 1643 self->rc.clear ();
1561 pango_opengl_render_layout_subpixel ( 1644 pango_opengl_render_layout_subpixel (
1562 self->pl, 1645 self->pl,
1563 self->rc, 1646 &self->rc,
1564 x * PANGO_SCALE, y * PANGO_SCALE, 1647 x * PANGO_SCALE, y * PANGO_SCALE,
1565 self->r, self->g, self->b, self->a, 1648 self->r, self->g, self->b, self->a,
1566 flags 1649 flags
1567 ); 1650 );
1568 // we assume that context_change actually clears/frees stuff 1651 // we assume that context_change actually clears/frees stuff
1579 gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 1662 gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1580 GL_ONE , GL_ONE_MINUS_SRC_ALPHA); 1663 GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1581 glEnable (GL_ALPHA_TEST); 1664 glEnable (GL_ALPHA_TEST);
1582 glAlphaFunc (GL_GREATER, 7.f / 255.f); 1665 glAlphaFunc (GL_GREATER, 7.f / 255.f);
1583 1666
1584 rc_draw (self->rc); 1667 self->rc.draw ();
1585 1668
1586 glDisable (GL_ALPHA_TEST); 1669 glDisable (GL_ALPHA_TEST);
1587 glDisable (GL_BLEND); 1670 glDisable (GL_BLEND);
1588 glDisable (GL_TEXTURE_2D); 1671 glDisable (GL_TEXTURE_2D);
1589} 1672}
1665 glDisable (GL_BLEND); 1748 glDisable (GL_BLEND);
1666 } 1749 }
1667} 1750}
1668 1751
1669void 1752void
1670draw_fow_texture (float intensity, int name1, float s1, float t1, float w1, float h1, float blend = 0.f, float dx = 0.f, float dy = 0.f, int name2 = 0, float s2 = 0.f, float t2 = 0.f, float w2 = 0.f, float h2 = 0.f) 1753draw_fow_texture (float intensity, int hidden_tex, int name1, uint8_t *data1, float s, float t, int w, int h, float blend = 0.f, int dx = 0, int dy = 0, int name2 = 0, uint8_t *data2 = data1)
1671 PROTOTYPE: @ 1754 PROTOTYPE: @
1672 CODE: 1755 CODE:
1673{ 1756{
1757 glEnable (GL_BLEND);
1758 glBlendFunc (intensity ? GL_SRC_ALPHA : GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1674 glEnable (GL_TEXTURE_2D); 1759 glEnable (GL_TEXTURE_2D);
1675 glEnable (GL_BLEND);
1676 glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1677 glBindTexture (GL_TEXTURE_2D, name1); 1760 glBindTexture (GL_TEXTURE_2D, name1);
1678 1761
1679 glColor3f (intensity, intensity, intensity); 1762 glColor3f (intensity, intensity, intensity);
1680 glPushMatrix (); 1763 glPushMatrix ();
1681 glScalef (1./3, 1./3, 1.); 1764 glScalef (1./3, 1./3, 1.);
1682 1765
1683 if (blend > 0.f) 1766 if (blend > 0.f)
1684 { 1767 {
1685 float S2, T2; /* 0. 0. for texture 2 */ 1768 float dx3 = dx * -3.f / w;
1686 float w = w1 > w2 ? w1 : w2; 1769 float dy3 = dy * -3.f / h;
1687 float h = h1 > h2 ? h1 : h2;
1688 GLfloat env_color[4] = { 0., 0., 0., blend }; 1770 GLfloat env_color[4] = { 0., 0., 0., blend };
1689 1771
1690 /* interpolate the two shadow textures */ 1772 /* interpolate the two shadow textures */
1691 /* stage 0 == rgb(glcolor) + alpha(t0) */ 1773 /* stage 0 == rgb(glcolor) + alpha(t0) */
1692 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 1774 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1697 glBindTexture (GL_TEXTURE_2D, name2); 1779 glBindTexture (GL_TEXTURE_2D, name2);
1698 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); 1780 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
1699 1781
1700 /* rgb == rgb(glcolor) */ 1782 /* rgb == rgb(glcolor) */
1701 glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); 1783 glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
1702 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_CONSTANT); 1784 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
1703 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); 1785 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
1704 1786
1705 /* alpha = interpolate t0, t1 by env_alpha */ 1787 /* alpha = interpolate t0, t1 by env_alpha */
1706 glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, env_color); 1788 glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, env_color);
1707 1789
1713 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); 1795 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
1714 1796
1715 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_CONSTANT); 1797 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_CONSTANT);
1716 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA); 1798 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA);
1717 1799
1718 s1 *= w / w1;
1719 t1 *= h / h1;
1720
1721 dx *= -3.f / w2;
1722 dy *= -3.f / h2;
1723 dx *= w / w2;
1724 dy *= h / h2;
1725
1726 s2 *= w / w2;
1727 t2 *= h / h2;
1728
1729 glBegin (GL_QUADS); 1800 glBegin (GL_QUADS);
1730 gl.MultiTexCoord2f (GL_TEXTURE0, 0, 0); gl.MultiTexCoord2f (GL_TEXTURE1, dx , dy ); glVertex2f ( 0, 0); 1801 gl.MultiTexCoord2f (GL_TEXTURE0, 0, 0); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 , dy3 ); glVertex2i (0, 0);
1731 gl.MultiTexCoord2f (GL_TEXTURE0, 0, t1); gl.MultiTexCoord2f (GL_TEXTURE1, dx , dy + t2); glVertex2f ( 0, h1); 1802 gl.MultiTexCoord2f (GL_TEXTURE0, 0, t); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 , dy3 + t); glVertex2i (0, h);
1732 gl.MultiTexCoord2f (GL_TEXTURE0, s1, t1); gl.MultiTexCoord2f (GL_TEXTURE1, dx + s2, dy + t2); glVertex2f (w1, h1); 1803 gl.MultiTexCoord2f (GL_TEXTURE0, s, t); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 + s, dy3 + t); glVertex2i (w, h);
1733 gl.MultiTexCoord2f (GL_TEXTURE0, s1, 0); gl.MultiTexCoord2f (GL_TEXTURE1, dx + s2, dy ); glVertex2f (w1, 0); 1804 gl.MultiTexCoord2f (GL_TEXTURE0, s, 0); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 + s, dy3 ); glVertex2i (w, 0);
1734 glEnd (); 1805 glEnd ();
1735 1806
1736 glDisable (GL_TEXTURE_2D); 1807 glDisable (GL_TEXTURE_2D);
1737 gl.ActiveTexture (GL_TEXTURE0); 1808 gl.ActiveTexture (GL_TEXTURE0);
1738 } 1809 }
1740 { 1811 {
1741 /* simple blending of one texture, also opengl <1.3 path */ 1812 /* simple blending of one texture, also opengl <1.3 path */
1742 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 1813 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1743 1814
1744 glBegin (GL_QUADS); 1815 glBegin (GL_QUADS);
1745 glTexCoord2f ( 0, 0); glVertex2f ( 0, 0); 1816 glTexCoord2f (0, 0); glVertex2f (0, 0);
1746 glTexCoord2f ( 0, t1); glVertex2f ( 0, h1); 1817 glTexCoord2f (0, t); glVertex2f (0, h);
1747 glTexCoord2f (s1, t1); glVertex2f (w1, h1); 1818 glTexCoord2f (s, t); glVertex2f (w, h);
1748 glTexCoord2f (s1, 0); glVertex2f (w1, 0); 1819 glTexCoord2f (s, 0); glVertex2f (w, 0);
1749 glEnd (); 1820 glEnd ();
1750 } 1821 }
1822
1823 /* draw ?-marks or equivalent, this is very clumsy code :/ */
1824 {
1825 int x, y;
1826 int dx3 = dx * 3;
1827 int dy3 = dy * 3;
1828
1829 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1830 glBindTexture (GL_TEXTURE_2D, hidden_tex);
1831 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1832 glTranslatef (-1., -1., 0);
1833 glBegin (GL_QUADS);
1834
1835 for (y = 1; y < h; y += 3)
1836 {
1837 int y1 = y - dy3;
1838 int y1valid = y1 >= 0 && y1 < h;
1839
1840 for (x = 1; x < w; x += 3)
1841 {
1842 int x1 = x - dx3;
1843 uint8_t h1 = data1 [x + y * w] == DARKNESS_ADJUST (255 - FOW_DARKNESS);
1844 uint8_t h2;
1845
1846 if (y1valid && x1 >= 0 && x1 < w)
1847 h2 = data2 [x1 + y1 * w] == DARKNESS_ADJUST (255 - FOW_DARKNESS);
1848 else
1849 h2 = 1; /* out of range == invisible */
1850
1851 if (h1 || h2)
1852 {
1853 float alpha = h1 == h2 ? 1.f : h1 ? 1.f - blend : blend;
1854 glColor4f (1., 1., 1., alpha);
1855
1856 glTexCoord2f (0, 0.); glVertex2i (x , y );
1857 glTexCoord2f (0, 1.); glVertex2i (x , y + 3);
1858 glTexCoord2f (1, 1.); glVertex2i (x + 3, y + 3);
1859 glTexCoord2f (1, 0.); glVertex2i (x + 3, y );
1860 }
1861 }
1862 }
1863 }
1864
1865 glEnd ();
1751 1866
1752 glPopMatrix (); 1867 glPopMatrix ();
1753 1868
1754 glDisable (GL_TEXTURE_2D); 1869 glDisable (GL_TEXTURE_2D);
1755 glDisable (GL_BLEND); 1870 glDisable (GL_BLEND);
1769MODULE = Deliantra::Client PACKAGE = DC::Map 1884MODULE = Deliantra::Client PACKAGE = DC::Map
1770 1885
1771PROTOTYPES: DISABLE 1886PROTOTYPES: DISABLE
1772 1887
1773DC::Map 1888DC::Map
1774new (SV *class) 1889new (SV *klass)
1775 CODE: 1890 CODE:
1776 New (0, RETVAL, 1, struct map); 1891 RETVAL = new mapgrid;
1777 RETVAL->x = 0; 1892 RETVAL->x = 0;
1778 RETVAL->y = 0; 1893 RETVAL->y = 0;
1779 RETVAL->w = 0; 1894 RETVAL->w = 0;
1780 RETVAL->h = 0; 1895 RETVAL->h = 0;
1781 RETVAL->ox = 0; 1896 RETVAL->ox = 0;
1782 RETVAL->oy = 0; 1897 RETVAL->oy = 0;
1783 RETVAL->faces = 8192; Newz (0, RETVAL->face2tile, RETVAL->faces, tileid);
1784 RETVAL->texs = 8192; Newz (0, RETVAL->tex , RETVAL->texs , maptex);
1785 RETVAL->rows = 0; 1898 RETVAL->rows = 0;
1786 RETVAL->row = 0; 1899 RETVAL->row = 0;
1787 OUTPUT: 1900 OUTPUT:
1788 RETVAL 1901 RETVAL
1789 1902
1790void 1903void
1791DESTROY (DC::Map self) 1904DESTROY (DC::Map self)
1792 CODE: 1905 CODE:
1793{ 1906{
1794 map_clear (self);
1795 Safefree (self->face2tile);
1796 Safefree (self->tex);
1797 Safefree (self); 1907 delete self;
1798} 1908}
1799 1909
1800void 1910void
1801resize (DC::Map self, int map_width, int map_height) 1911resize (DC::Map self, int map_width, int map_height)
1802 CODE: 1912 CODE:
1804 self->h = map_height; 1914 self->h = map_height;
1805 1915
1806void 1916void
1807clear (DC::Map self) 1917clear (DC::Map self)
1808 CODE: 1918 CODE:
1809 map_clear (self); 1919 self->clear_cells ();
1810 1920
1811void 1921void
1812set_tileid (DC::Map self, int face, int tile) 1922set_tileid (DC::Map self, int face, int tile)
1813 CODE: 1923 CODE:
1814{ 1924{
1815 need_facenum (self, face); self->face2tile [face] = tile; 1925 if (self->tile.size () <= face) self->tile.resize (face + 1);
1816 need_texid (self, tile); 1926 self->tile[face] = tile;
1927 if (self->tex.size () <= tile) self->tex .resize (tile + 1);
1817} 1928}
1818 1929
1819void 1930void
1820set_smooth (DC::Map self, int face, int smooth, int level) 1931set_smooth (DC::Map self, int face, int smooth, int level)
1821 CODE: 1932 CODE:
1822{ 1933{
1823 tileid texid;
1824 maptex *tex;
1825
1826 if (face < 0 || face >= self->faces) 1934 if (face < 0 || face >= self->tile.size ())
1827 return; 1935 return;
1828 1936
1829 if (smooth < 0 || smooth >= self->faces) 1937 if (smooth < 0 || smooth >= self->tile.size ())
1830 return; 1938 return;
1831 1939
1832 texid = self->face2tile [face]; 1940 tileid texid = self->tile[face];
1833 1941
1834 if (!texid) 1942 if (!texid)
1835 return; 1943 return;
1836 1944
1837 tex = self->tex + texid; 1945 maptex &tex = self->tex[texid];
1838 tex->smoothtile = self->face2tile [smooth]; 1946 tex.smoothtile = self->tile[smooth];
1839 tex->smoothlevel = level; 1947 tex.smoothlevel = level;
1840} 1948}
1841 1949
1842void 1950void
1843set_texture (DC::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a) 1951set_texture (DC::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a)
1844 CODE: 1952 CODE:
1845{ 1953{
1846 need_texid (self, texid); 1954 if (self->tex.size () < texid) self->tex.resize (texid + 1);
1847 1955
1848 { 1956 {
1849 maptex *tex = self->tex + texid; 1957 maptex &tex = self->tex[texid];
1850 1958
1851 tex->name = name; 1959 tex.name = name;
1852 tex->w = w; 1960 tex.w = w;
1853 tex->h = h; 1961 tex.h = h;
1854 tex->s = s; 1962 tex.s = s;
1855 tex->t = t; 1963 tex.t = t;
1856 tex->r = r; 1964 tex.r = r;
1857 tex->g = g; 1965 tex.g = g;
1858 tex->b = b; 1966 tex.b = b;
1859 tex->a = a; 1967 tex.a = a;
1860 } 1968 }
1861 1969
1862 // somewhat hackish, but for textures that require it, it really 1970 // somewhat hackish, but for textures that require it, it really
1863 // improves the look, and most others don't suffer. 1971 // improves the look, and most others don't suffer.
1864 glBindTexture (GL_TEXTURE_2D, name); 1972 glBindTexture (GL_TEXTURE_2D, name);
1870} 1978}
1871 1979
1872void 1980void
1873expire_textures (DC::Map self, int texid, int count) 1981expire_textures (DC::Map self, int texid, int count)
1874 PPCODE: 1982 PPCODE:
1875 for (; texid < self->texs && count; ++texid, --count) 1983 for (; texid < self->tex.size () && count; ++texid, --count)
1876 { 1984 {
1877 maptex *tex = self->tex + texid; 1985 maptex &tex = self->tex[texid];
1878 1986
1879 if (tex->name) 1987 if (tex.name)
1880 { 1988 {
1881 if (tex->unused) 1989 if (tex.unused)
1882 { 1990 {
1883 tex->name = 0; 1991 tex.name = 0;
1884 tex->unused = 0; 1992 tex.unused = 0;
1885 XPUSHs (sv_2mortal (newSViv (texid))); 1993 XPUSHs (sv_2mortal (newSViv (texid)));
1886 } 1994 }
1887 else 1995 else
1888 tex->unused = 1; 1996 tex.unused = 1;
1889 } 1997 }
1890 } 1998 }
1891 1999
1892int 2000int
1893ox (DC::Map self) 2001ox (DC::Map self)
1935 self->y += MAP_EXTEND_Y; 2043 self->y += MAP_EXTEND_Y;
1936 } 2044 }
1937} 2045}
1938 2046
1939SV * 2047SV *
1940map1a_update (DC::Map self, SV *data_, int extmap) 2048map1a_update (DC::Map self, SV *data_)
1941 CODE: 2049 CODE:
1942{ 2050{
1943 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_); 2051 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1944 uint8_t *data_end = (uint8_t *)SvEND (data_); 2052 uint8_t *data_end = (uint8_t *)SvEND (data_);
1945 mapcell *cell; 2053 mapcell *cell;
1966 2074
1967 //TODO: don't trust server data to be in-range(!) 2075 //TODO: don't trust server data to be in-range(!)
1968 2076
1969 if (flags & 8) 2077 if (flags & 8)
1970 { 2078 {
2079 uint8_t ext, cmd;
2080
1971 if (extmap) 2081 do
1972 { 2082 {
1973 uint8_t ext, cmd; 2083 ext = *data++;
2084 cmd = ext & 0x7f;
1974 2085
1975 do 2086 if (cmd < 4)
2087 cell->darkness = 255 - ext * 64 + 1; /* make sure this doesn't collide with FOW_DARKNESS */
2088 else if (cmd == 5) // health
1976 { 2089 {
1977 ext = *data++;
1978 cmd = ext & 0x7f;
1979
1980 if (cmd < 4)
1981 cell->darkness = 255 - ext * 64 + 1;
1982 else if (cmd == 5) // health
1983 {
1984 cell->stat_width = 1; 2090 cell->stat_width = 1;
1985 cell->stat_hp = *data++; 2091 cell->stat_hp = *data++;
1986 }
1987 else if (cmd == 6) // monster width
1988 cell->stat_width = *data++ + 1;
1989 else if (cmd == 0x47)
1990 {
1991 if (*data == 1) cell->player = data [1];
1992 else if (*data == 2) cell->player = data [2] + (data [1] << 8);
1993 else if (*data == 3) cell->player = data [3] + (data [2] << 8) + (data [1] << 16);
1994 else if (*data == 4) cell->player = data [4] + (data [3] << 8) + (data [2] << 16) + (data [1] << 24);
1995
1996 data += *data + 1;
1997 }
1998 else if (cmd == 8) // cell flags
1999 cell->flags = *data++;
2000 else if (ext & 0x40) // unknown, multibyte => skip
2001 data += *data + 1;
2002 else
2003 data++;
2004 } 2092 }
2005 while (ext & 0x80); 2093 else if (cmd == 6) // monster width
2094 cell->stat_width = *data++ + 1;
2095 else if (cmd == 0x47)
2096 {
2097 if (*data == 1) cell->player = data [1];
2098 else if (*data == 2) cell->player = data [2] + (data [1] << 8);
2099 else if (*data == 3) cell->player = data [3] + (data [2] << 8) + (data [1] << 16);
2100 else if (*data == 4) cell->player = data [4] + (data [3] << 8) + (data [2] << 16) + (data [1] << 24);
2101
2102 data += *data + 1;
2103 }
2104 else if (cmd == 8) // cell flags
2105 cell->flags = *data++;
2106 else if (ext & 0x40) // unknown, multibyte => skip
2107 data += *data + 1;
2108 else
2109 data++;
2006 } 2110 }
2007 else 2111 while (ext & 0x80);
2008 cell->darkness = *data++ + 1;
2009 } 2112 }
2010 2113
2011 for (z = 0; z <= 2; ++z) 2114 for (z = 0; z <= 2; ++z)
2012 if (flags & (4 >> z)) 2115 if (flags & (4 >> z))
2013 { 2116 {
2014 faceid face = (data [0] << 8) + data [1]; data += 2; 2117 faceid face = (data[0] << 8) + data[1]; data += 2;
2015 need_facenum (self, face); 2118 if (self->tile.size () <= face) self->tile.resize (face + 1);
2016 cell->tile [z] = self->face2tile [face]; 2119 cell->tile[z] = self->tile[face];
2017 2120
2018 if (cell->tile [z]) 2121 if (cell->tile[z])
2019 { 2122 {
2020 maptex *tex = self->tex + cell->tile [z]; 2123 maptex &tex = self->tex[cell->tile[z]];
2021 tex->unused = 0; 2124 tex.unused = 0;
2022 if (!tex->name) 2125 if (!tex.name)
2023 av_push (missing, newSViv (cell->tile [z])); 2126 av_push (missing, newSViv (cell->tile [z]));
2024 2127
2025 if (tex->smoothtile) 2128 if (tex.smoothtile)
2026 { 2129 {
2027 maptex *smooth = self->tex + tex->smoothtile; 2130 maptex &smooth = self->tex[tex.smoothtile];
2028 smooth->unused = 0; 2131 smooth.unused = 0;
2029 if (!smooth->name) 2132 if (!smooth.name)
2030 av_push (missing, newSViv (tex->smoothtile)); 2133 av_push (missing, newSViv (tex.smoothtile));
2031 } 2134 }
2032 } 2135 }
2033 } 2136 }
2034 } 2137 }
2035 else 2138 else
2061 ? self->row + y 2164 ? self->row + y
2062 : 0; 2165 : 0;
2063 2166
2064 for (x = x0; x < x1; x++) 2167 for (x = x0; x < x1; x++)
2065 { 2168 {
2066 int r = 32, g = 32, b = 32, a = 192; 2169 unsigned int r = 32, g = 32, b = 32, a = 192;
2067 2170
2068 if (row && row->c0 <= x && x < row->c1) 2171 if (row && row->c0 <= x && x < row->c1)
2069 { 2172 {
2070 mapcell *cell = row->col + (x - row->c0); 2173 mapcell *cell = row->col + (x - row->c0);
2071 2174
2073 { 2176 {
2074 maptex tex = self->tex [cell->tile [z]]; 2177 maptex tex = self->tex [cell->tile [z]];
2075 int a0 = 255 - tex.a; 2178 int a0 = 255 - tex.a;
2076 int a1 = tex.a; 2179 int a1 = tex.a;
2077 2180
2078 r = (r * a0 + tex.r * a1) / 255; 2181 r = div255 (r * a0 + tex.r * a1);
2079 g = (g * a0 + tex.g * a1) / 255; 2182 g = div255 (g * a0 + tex.g * a1);
2080 b = (b * a0 + tex.b * a1) / 255; 2183 b = div255 (b * a0 + tex.b * a1);
2081 a = (a * a0 + tex.a * a1) / 255; 2184 a = div255 (a * a0 + tex.a * a1);
2082 } 2185 }
2083 } 2186 }
2084 2187
2085 *map++ = (r ) 2188 *map++ = (r )
2086 | (g << 8) 2189 | (g << 8)
2087 | (b << 16) 2190 | (b << 16)
2088 | (a << 24); 2191 | (a << 24);
2089 } 2192 }
2090 } 2193 }
2091 2194
2092 RETVAL = map_sv; 2195 RETVAL = map_sv;
2093} 2196}
2094 OUTPUT: 2197 OUTPUT:
2095 RETVAL 2198 RETVAL
2096 2199
2097void 2200void
2098draw (DC::Map self, int mx, int my, int sw, int sh, int T, U32 player = 0xffffffff, int sdx = 0, int sdy = 0) 2201draw (DC::Map self, int mx, int my, int sw, int sh, int Tw, int Th, U32 player = 0xffffffff, int sdx = 0, int sdy = 0)
2099 CODE: 2202 CODE:
2100{ 2203{
2101 int x, y, z; 2204 int x, y, z;
2102 2205
2103 HV *smooth = (HV *)sv_2mortal ((SV *)newHV ());
2104 uint32_t smooth_level[256 / 32]; // one bit for every possible smooth level
2105 static uint8_t smooth_max[256][256]; // egad, fast and wasteful on memory (64k) 2206 static uint8_t smooth_max[256][256]; // egad, fast and wasteful on memory (64k), also, static!
2106 smooth_key skey;
2107 int pl_x, pl_y; 2207 int pl_x, pl_y;
2108 maptex pl_tex; 2208 maptex pl_tex;
2109 rc_t *rc = rc_alloc (); 2209 rc_t rc;
2110 rc_t *rc_ov = rc_alloc (); 2210 rc_t rc_ov;
2111 rc_key_t key; 2211 rc_key_t key;
2112 rc_array_t *arr, *arr_hidden; 2212 rc_t::array_t *arr;
2113 2213
2114 pl_tex.name = 0; 2214 pl_tex.name = 0;
2115 2215
2116 // that's current max. sorry. 2216 // that's current max. sorry.
2117 if (sw > 255) sw = 255; 2217 if (sw > 255) sw = 255;
2118 if (sh > 255) sh = 255; 2218 if (sh > 255) sh = 255;
2119
2120 // clear key, in case of extra padding
2121 memset (&skey, 0, sizeof (skey));
2122 2219
2123 memset (&key, 0, sizeof (key)); 2220 memset (&key, 0, sizeof (key));
2124 key.r = 255; 2221 key.r = 255;
2125 key.g = 255; 2222 key.g = 255;
2126 key.b = 255; 2223 key.b = 255;
2132 my += self->y; 2229 my += self->y;
2133 2230
2134 // first pass: determine smooth_max 2231 // first pass: determine smooth_max
2135 // rather ugly, if you ask me 2232 // rather ugly, if you ask me
2136 // could also be stored inside mapcell and updated on change 2233 // could also be stored inside mapcell and updated on change
2137 memset (smooth_max, 0, sizeof (smooth_max)); 2234 memset (smooth_max, 0, sizeof (smooth_max[0]) * (sh + 1));
2138 2235
2139 for (y = 0; y < sh; y++) 2236 for (y = 0; y < sh; y++)
2140 if (0 <= y + my && y + my < self->rows) 2237 if (0 <= y + my && y + my < self->rows)
2141 { 2238 {
2142 maprow *row = self->row + (y + my); 2239 maprow *row = self->row + (y + my);
2155 2252
2156 glEnable (GL_BLEND); 2253 glEnable (GL_BLEND);
2157 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2254 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2158 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 2255 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2159 2256
2160 key.texname = self->tex [TEXID_HIDDEN].name;
2161 arr_hidden = rc_array (rc_ov, &key);
2162
2163 for (z = 0; z <= 2; z++) 2257 for (z = 0; z <= 2; z++)
2164 { 2258 {
2165 memset (smooth_level, 0, sizeof (smooth_level)); 2259 std::bitset<256> smooth_level; // one bit for every possible smooth level
2260 smooth_key skey;
2261 smooth_hash smooth;
2166 key.texname = -1; 2262 key.texname = -1;
2167 2263
2168 for (y = 0; y < sh; y++) 2264 for (y = 0; y < sh; y++)
2169 if (0 <= y + my && y + my < self->rows) 2265 if (0 <= y + my && y + my < self->rows)
2170 { 2266 {
2187 2283
2188 if (!tex.name) 2284 if (!tex.name)
2189 tex = self->tex [TEXID_NOFACE]; /* missing, replace by noface */ 2285 tex = self->tex [TEXID_NOFACE]; /* missing, replace by noface */
2190 2286
2191 key.texname = tex.name; 2287 key.texname = tex.name;
2192 arr = rc_array (rc, &key); 2288 arr = &rc.array (key);
2193 } 2289 }
2194 2290
2195 px = (x + 1) * T - tex.w; 2291 px = (x + 1) * Th - tex.w;
2196 py = (y + 1) * T - tex.h; 2292 py = (y + 1) * Tw - tex.h;
2197 2293
2198 if (expect_false (cell->player == player) && expect_false (z == 2)) 2294 if (expect_false (cell->player == player) && expect_false (z == 2))
2199 { 2295 {
2200 pl_x = px; 2296 pl_x = px;
2201 pl_y = py; 2297 pl_y = py;
2202 pl_tex = tex; 2298 pl_tex = tex;
2203 continue; 2299 continue;
2204 } 2300 }
2205 2301
2206 rc_t2f_v3f (arr, 0 , 0 , px , py , 0); 2302 arr->t2f_v3f (0 , 0 , px , py , 0);
2207 rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0); 2303 arr->t2f_v3f (0 , tex.t, px , py + tex.h, 0);
2208 rc_t2f_v3f (arr, tex.s, tex.t, px + tex.w, py + tex.h, 0); 2304 arr->t2f_v3f (tex.s, tex.t, px + tex.w, py + tex.h, 0);
2209 rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0); 2305 arr->t2f_v3f (tex.s, 0 , px + tex.w, py , 0);
2210 2306
2211 // update smooth hash 2307 // update smooth hash
2212 if (tex.smoothtile) 2308 if (tex.smoothtile)
2213 { 2309 {
2214 skey.tile = tex.smoothtile; 2310 skey.tile = tex.smoothtile;
2215 skey.level = tex.smoothlevel; 2311 skey.level = tex.smoothlevel;
2216 2312
2217 smooth_level [tex.smoothlevel >> 5] |= ((uint32_t)1) << (tex.smoothlevel & 31); 2313 smooth_level[tex.smoothlevel] = 1;
2218 2314
2219 // add bits to current tile and all neighbours. skey.x|y is 2315 // add bits to current tile and all neighbours. skey.x|y is
2220 // shifted +1|+1 so we always stay positive. 2316 // shifted +1|+1 so we always stay positive.
2221 2317
2222 // bits is ___n cccc CCCC bbbb 2318 // bits is ___n cccc CCCC bbbb
2230 2326
2231 // corners: 1 ┛· 2 ·┗ 4 ·· 8 ·· 2327 // corners: 1 ┛· 2 ·┗ 4 ·· 8 ··
2232 // ·· ·· ·┏ ┓· 2328 // ·· ·· ·┏ ┓·
2233 2329
2234 // full tile 2330 // full tile
2235 skey.x = x + 1; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x1000); 2331 skey.x = x + 1; skey.y = y + 1; smooth_or_bits (smooth, skey, 0x1000);
2236 2332
2237 // borders 2333 // borders
2238 skey.x = x + 2; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0091); 2334 skey.x = x + 2; skey.y = y + 1; smooth_or_bits (smooth, skey, 0x0091);
2239 skey.x = x + 1; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0032); 2335 skey.x = x + 1; skey.y = y + 2; smooth_or_bits (smooth, skey, 0x0032);
2240 skey.x = x ; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0064); 2336 skey.x = x ; skey.y = y + 1; smooth_or_bits (smooth, skey, 0x0064);
2241 skey.x = x + 1; skey.y = y ; smooth_or_bits (smooth, &skey, 0x00c8); 2337 skey.x = x + 1; skey.y = y ; smooth_or_bits (smooth, skey, 0x00c8);
2242 2338
2243 // corners 2339 // corners
2244 skey.x = x + 2; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0100); 2340 skey.x = x + 2; skey.y = y + 2; smooth_or_bits (smooth, skey, 0x0100);
2245 skey.x = x ; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0200); 2341 skey.x = x ; skey.y = y + 2; smooth_or_bits (smooth, skey, 0x0200);
2246 skey.x = x ; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0400); 2342 skey.x = x ; skey.y = y ; smooth_or_bits (smooth, skey, 0x0400);
2247 skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0800); 2343 skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, skey, 0x0800);
2248 } 2344 }
2249 } 2345 }
2250 2346
2251 if (expect_false (z == 2)) 2347 if (expect_false (z == 2) && expect_false (cell->flags))
2252 { 2348 {
2253 /* draw question marks on top of hidden spaces */ 2349 // overlays such as the speech bubble, probably more to come
2254 if (!cell->darkness) 2350 if (cell->flags & 1)
2255 { 2351 {
2256 maptex tex = self->tex [TEXID_HIDDEN];
2257 int px = (x + 1) * T - tex.w;
2258 int py = (y + 1) * T - tex.h;
2259
2260 rc_t2f_v3f (arr_hidden, 0 , 0 , px , py , 0);
2261 rc_t2f_v3f (arr_hidden, 0 , tex.t, px , py + tex.h, 0);
2262 rc_t2f_v3f (arr_hidden, tex.s, tex.t, px + tex.w, py + tex.h, 0);
2263 rc_t2f_v3f (arr_hidden, tex.s, 0 , px + tex.w, py , 0);
2264 }
2265
2266 if (expect_false (cell->flags))
2267 {
2268 // overlays such as the speech bubble, probably more to come
2269 if (cell->flags & 1)
2270 {
2271 rc_key_t key_ov = key; 2352 rc_key_t key_ov = key;
2272 maptex tex = self->tex [TEXID_SPEECH]; 2353 maptex tex = self->tex[TEXID_SPEECH];
2273 rc_array_t *arr;
2274 int px = x * T + T * 2 / 32; 2354 int px = x * Tw + Tw * 2 / 32;
2275 int py = y * T - T * 6 / 32; 2355 int py = y * Th - Th * 6 / 32;
2276 2356
2277 key_ov.texname = tex.name; 2357 key_ov.texname = tex.name;
2278 arr = rc_array (rc_ov, &key_ov); 2358 rc_t::array_t &arr = rc_ov.array (key_ov);
2279 2359
2280 rc_t2f_v3f (arr, 0 , 0 , px , py , 0); 2360 arr.t2f_v3f (0 , 0 , px , py , 0);
2281 rc_t2f_v3f (arr, 0 , tex.t, px , py + T, 0); 2361 arr.t2f_v3f (0 , tex.t, px , py + Th, 0);
2282 rc_t2f_v3f (arr, tex.s, tex.t, px + T, py + T, 0); 2362 arr.t2f_v3f (tex.s, tex.t, px + Tw, py + Th, 0);
2283 rc_t2f_v3f (arr, tex.s, 0 , px + T, py , 0); 2363 arr.t2f_v3f (tex.s, 0 , px + Tw, py , 0);
2284 }
2285 } 2364 }
2286 } 2365 }
2287 } 2366 }
2288 } 2367 }
2289 2368
2290 rc_draw (rc); 2369 rc.draw ();
2291 rc_clear (rc); 2370 rc.clear ();
2292 2371
2293 // go through all smoothlevels, lowest to highest, then draw. 2372 // go through all smoothlevels, lowest to highest, then draw.
2294 // this is basically counting sort 2373 // this is basically counting sort
2295 { 2374 {
2296 int w, b; 2375 int w, b;
2297 2376
2298 glEnable (GL_TEXTURE_2D); 2377 glEnable (GL_TEXTURE_2D);
2299 glBegin (GL_QUADS); 2378 glBegin (GL_QUADS);
2300 for (w = 0; w < 256 / 32; ++w) 2379 for (int level = 0; level < smooth_level.size (); ++level)
2380 if (smooth_level[level])
2381 for (auto &&it = smooth.begin (); it != smooth.end (); ++it)
2301 { 2382 {
2302 uint32_t smask = smooth_level [w]; 2383 smooth_key &skey = it->first;
2303 if (smask) 2384 IV bits = it->second;
2304 for (b = 0; b < 32; ++b) 2385
2305 if (smask & (((uint32_t)1) << b)) 2386 if (!(bits & 0x1000)
2387 && skey.level == level
2388 && level > smooth_max [skey.x][skey.y])
2306 { 2389 {
2307 int level = (w << 5) | b; 2390 maptex tex = self->tex [skey.tile];
2391 int px = (((int)skey.x) - 1) * Tw;
2392 int py = (((int)skey.y) - 1) * Th;
2393 int border = bits & 15;
2394 int corner = (bits >> 8) & ~(bits >> 4) & 15;
2395 float dx = tex.s * .0625f; // 16 images/row
2396 float dy = tex.t * .5f ; // 2 images/column
2397
2308 HE *he; 2398 if (tex.name)
2309
2310 hv_iterinit (smooth);
2311 while ((he = hv_iternext (smooth)))
2312 { 2399 {
2313 smooth_key *skey = (smooth_key *)HeKEY (he); 2400 // this time avoiding texture state changes
2314 IV bits = SvIVX (HeVAL (he)); 2401 // save gobs of state changes.
2315 2402 if (key.texname != tex.name)
2316 if (!(bits & 0x1000)
2317 && skey->level == level
2318 && level > smooth_max [skey->x][skey->y])
2319 { 2403 {
2320 maptex tex = self->tex [skey->tile];
2321 int px = (((int)skey->x) - 1) * T;
2322 int py = (((int)skey->y) - 1) * T;
2323 int border = bits & 15;
2324 int corner = (bits >> 8) & ~(bits >> 4) & 15;
2325 float dx = tex.s * .0625f; // 16 images/row
2326 float dy = tex.t * .5f ; // 2 images/column
2327
2328 if (tex.name)
2329 {
2330 // this time avoiding texture state changes
2331 // save gobs of state changes.
2332 if (key.texname != tex.name)
2333 {
2334 self->tex [skey->tile].unused = 0; 2404 self->tex [skey.tile].unused = 0;
2335 2405
2336 glEnd (); 2406 glEnd ();
2337 glBindTexture (GL_TEXTURE_2D, key.texname = tex.name); 2407 glBindTexture (GL_TEXTURE_2D, key.texname = tex.name);
2338 glBegin (GL_QUADS); 2408 glBegin (GL_QUADS);
2339 } 2409 }
2340 2410
2341 if (border) 2411 if (border)
2342 { 2412 {
2343 float ox = border * dx; 2413 float ox = border * dx;
2344 2414
2345 glTexCoord2f (ox , 0.f ); glVertex2i (px , py ); 2415 glTexCoord2f (ox , 0.f ); glVertex2i (px , py );
2346 glTexCoord2f (ox , dy ); glVertex2i (px , py + T); 2416 glTexCoord2f (ox , dy ); glVertex2i (px , py + Th);
2347 glTexCoord2f (ox + dx, dy ); glVertex2i (px + T, py + T); 2417 glTexCoord2f (ox + dx, dy ); glVertex2i (px + Tw, py + Th);
2348 glTexCoord2f (ox + dx, 0.f ); glVertex2i (px + T, py ); 2418 glTexCoord2f (ox + dx, 0.f ); glVertex2i (px + Tw, py );
2349 } 2419 }
2350 2420
2351 if (corner) 2421 if (corner)
2352 { 2422 {
2353 float ox = corner * dx; 2423 float ox = corner * dx;
2354 2424
2355 glTexCoord2f (ox , dy ); glVertex2i (px , py ); 2425 glTexCoord2f (ox , dy ); glVertex2i (px , py );
2356 glTexCoord2f (ox , dy * 2.f); glVertex2i (px , py + T); 2426 glTexCoord2f (ox , dy * 2.f); glVertex2i (px , py + Th);
2357 glTexCoord2f (ox + dx, dy * 2.f); glVertex2i (px + T, py + T); 2427 glTexCoord2f (ox + dx, dy * 2.f); glVertex2i (px + Tw, py + Th);
2358 glTexCoord2f (ox + dx, dy ); glVertex2i (px + T, py ); 2428 glTexCoord2f (ox + dx, dy ); glVertex2i (px + Tw, py );
2359 }
2360 }
2361 } 2429 }
2362 } 2430 }
2363 } 2431 }
2364 } 2432 }
2365 2433
2366 glEnd (); 2434 glEnd ();
2367 glDisable (GL_TEXTURE_2D); 2435 glDisable (GL_TEXTURE_2D);
2368 key.texname = -1; 2436 key.texname = -1;
2369 } 2437 }
2370
2371 hv_clear (smooth);
2372 } 2438 }
2373 2439
2374 if (pl_tex.name) 2440 if (pl_tex.name)
2375 { 2441 {
2376 maptex tex = pl_tex; 2442 maptex tex = pl_tex;
2377 int px = pl_x + sdx; 2443 int px = pl_x + sdx;
2378 int py = pl_y + sdy; 2444 int py = pl_y + sdy;
2379 2445
2380 key.texname = tex.name; 2446 key.texname = tex.name;
2381 arr = rc_array (rc, &key); 2447 rc_t::array_t &arr = rc.array (key);
2382 2448
2383 rc_t2f_v3f (arr, 0 , 0 , px , py , 0); 2449 arr.t2f_v3f (0 , 0 , px , py , 0);
2384 rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0); 2450 arr.t2f_v3f (0 , tex.t, px , py + tex.h, 0);
2385 rc_t2f_v3f (arr, tex.s, tex.t, px + tex.w, py + tex.h, 0); 2451 arr.t2f_v3f (tex.s, tex.t, px + tex.w, py + tex.h, 0);
2386 rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0); 2452 arr.t2f_v3f (tex.s, 0 , px + tex.w, py , 0);
2387 2453
2388 rc_draw (rc); 2454 rc.draw ();
2389 } 2455 }
2390 2456
2391 rc_draw (rc_ov); 2457 rc_ov.draw ();
2392 rc_clear (rc_ov); 2458 rc_ov.clear ();
2393 2459
2394 glDisable (GL_BLEND); 2460 glDisable (GL_BLEND);
2395 rc_free (rc);
2396 rc_free (rc_ov);
2397 2461
2398 // top layer: overlays such as the health bar 2462 // top layer: overlays such as the health bar
2399 for (y = 0; y < sh; y++) 2463 for (y = 0; y < sh; y++)
2400 if (0 <= y + my && y + my < self->rows) 2464 if (0 <= y + my && y + my < self->rows)
2401 { 2465 {
2404 for (x = 0; x < sw; x++) 2468 for (x = 0; x < sw; x++)
2405 if (row->c0 <= x + mx && x + mx < row->c1) 2469 if (row->c0 <= x + mx && x + mx < row->c1)
2406 { 2470 {
2407 mapcell *cell = row->col + (x + mx - row->c0); 2471 mapcell *cell = row->col + (x + mx - row->c0);
2408 2472
2409 int px = x * T; 2473 int px = x * Tw;
2410 int py = y * T; 2474 int py = y * Th;
2411 2475
2412 if (expect_false (cell->player == player)) 2476 if (expect_false (cell->player == player))
2413 { 2477 {
2414 px += sdx; 2478 px += sdx;
2415 py += sdy; 2479 py += sdy;
2416 } 2480 }
2417 2481
2418 if (cell->stat_hp) 2482 if (cell->stat_hp)
2419 { 2483 {
2420 int width = cell->stat_width * T; 2484 int width = cell->stat_width * Tw;
2421 int thick = (sh * T / 32 + 27) / 28 + 1 + cell->stat_width; 2485 int thick = (sh * Th / 32 + 27) / 28 + 1 + cell->stat_width;
2422 2486
2423 glColor3ub (0, 0, 0); 2487 glColor3ub (0, 0, 0);
2424 glRectf (px + 1, py - thick - 2, 2488 glRectf (px + 1, py - thick - 2,
2425 px + width - 1, py); 2489 px + width - 1, py);
2426 2490
2463 int x, y; 2527 int x, y;
2464 2528
2465 glEnable (GL_TEXTURE_2D); 2529 glEnable (GL_TEXTURE_2D);
2466 /* GL_REPLACE would be correct, as we don't need to modulate alpha, 2530 /* GL_REPLACE would be correct, as we don't need to modulate alpha,
2467 * but the nvidia driver (185.18.14) mishandles alpha textures 2531 * but the nvidia driver (185.18.14) mishandles alpha textures
2468 * ansd takes the colour from god knows where instead of using 2532 * and takes the colour from god knows where instead of using
2469 * Cp. MODULATE results in the same colour, but slightly different 2533 * Cp. MODULATE results in the same colour, but slightly different
2470 * alpha, but atcually gives us the correct colour with nvidia. 2534 * alpha, but atcually gives us the correct colour with nvidia.
2471 */ 2535 */
2472 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 2536 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2473 glEnable (GL_BLEND); 2537 glEnable (GL_BLEND);
2502void 2566void
2503fow_texture (DC::Map self, int mx, int my, int sw, int sh) 2567fow_texture (DC::Map self, int mx, int my, int sw, int sh)
2504 PPCODE: 2568 PPCODE:
2505{ 2569{
2506 int x, y; 2570 int x, y;
2507 int sw1 = sw + 2; 2571 int sw1 = sw + 2;
2508 int sh1 = sh + 2; 2572 int sh1 = sh + 2;
2509 int sh3 = sh * 3; 2573 int sh3 = sh * 3;
2510 int sw34 = (sw * 3 + 3) & ~3; 2574 int sw3 = sw * 3;
2575 SV *darkness3_sv = sv_2mortal (newSV (sw3 * sh3));
2576 uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv);
2511 uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1); 2577 uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1);
2512 SV *darkness3_sv = sv_2mortal (newSV (sw34 * sh3)); 2578 memset (darkness1, 0, sw1*sh1);
2513 uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv);
2514 2579
2515 SvPOK_only (darkness3_sv); 2580 SvPOK_only (darkness3_sv);
2516 SvCUR_set (darkness3_sv, sw34 * sh3); 2581 SvCUR_set (darkness3_sv, sw3 * sh3);
2517 2582
2518 mx += self->x - 1; 2583 mx += self->x - 1;
2519 my += self->y - 1; 2584 my += self->y - 1;
2520
2521 memset (darkness1, DARKNESS_ADJUST (255 - FOW_DARKNESS), sw1 * sh1);
2522 2585
2523 for (y = 0; y < sh1; y++) 2586 for (y = 0; y < sh1; y++)
2524 if (0 <= y + my && y + my < self->rows) 2587 if (0 <= y + my && y + my < self->rows)
2525 { 2588 {
2526 maprow *row = self->row + (y + my); 2589 maprow *row = self->row + (y + my);
2559 2622
2560 uint8_t r13 = (d13 + d23 + d12) / 3; 2623 uint8_t r13 = (d13 + d23 + d12) / 3;
2561 uint8_t r23 = d23; 2624 uint8_t r23 = d23;
2562 uint8_t r33 = (d23 + d33 + d32) / 3; 2625 uint8_t r33 = (d23 + d33 + d32) / 3;
2563 2626
2564 darkness3 [(y * 3 ) * sw34 + (x * 3 )] = MAX (d22, r11); 2627 darkness3 [(y * 3 ) * sw3 + (x * 3 )] = MAX (d22, r11);
2565 darkness3 [(y * 3 ) * sw34 + (x * 3 + 1)] = MAX (d22, r21); 2628 darkness3 [(y * 3 ) * sw3 + (x * 3 + 1)] = MAX (d22, r21);
2566 darkness3 [(y * 3 ) * sw34 + (x * 3 + 2)] = MAX (d22, r31); 2629 darkness3 [(y * 3 ) * sw3 + (x * 3 + 2)] = MAX (d22, r31);
2567 darkness3 [(y * 3 + 1) * sw34 + (x * 3 )] = MAX (d22, r12); 2630 darkness3 [(y * 3 + 1) * sw3 + (x * 3 )] = MAX (d22, r12);
2568 darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 1)] = MAX (d22, r22); 2631 darkness3 [(y * 3 + 1) * sw3 + (x * 3 + 1)] = MAX (d22, r22); /* this MUST be == d22 */
2569 darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 2)] = MAX (d22, r32); 2632 darkness3 [(y * 3 + 1) * sw3 + (x * 3 + 2)] = MAX (d22, r32);
2570 darkness3 [(y * 3 + 2) * sw34 + (x * 3 )] = MAX (d22, r13); 2633 darkness3 [(y * 3 + 2) * sw3 + (x * 3 )] = MAX (d22, r13);
2571 darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 1)] = MAX (d22, r23); 2634 darkness3 [(y * 3 + 2) * sw3 + (x * 3 + 1)] = MAX (d22, r23);
2572 darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 2)] = MAX (d22, r33); 2635 darkness3 [(y * 3 + 2) * sw3 + (x * 3 + 2)] = MAX (d22, r33);
2573 } 2636 }
2574 2637
2575 free (darkness1); 2638 free (darkness1);
2576 2639
2577 EXTEND (SP, 3); 2640 EXTEND (SP, 3);
2578 PUSHs (sv_2mortal (newSViv (sw34))); 2641 PUSHs (sv_2mortal (newSViv (sw3)));
2579 PUSHs (sv_2mortal (newSViv (sh3))); 2642 PUSHs (sv_2mortal (newSViv (sh3)));
2580 PUSHs (darkness3_sv); 2643 PUSHs (darkness3_sv);
2581} 2644}
2582 2645
2583SV * 2646SV *
2646 else 2709 else
2647 *data++ = 0; 2710 *data++ = 0;
2648 } 2711 }
2649 } 2712 }
2650 2713
2651 /* if size is w*h + 5 then no data has been found */ 2714 /* if size is w*h + 5 then no data has been found */
2652 if (data - (uint8_t *)SvPVX (data_sv) != w * h + 5) 2715 if (data - (uint8_t *)SvPVX (data_sv) != w * h + 5)
2653 { 2716 {
2654 SvPOK_only (data_sv); 2717 SvPOK_only (data_sv);
2655 SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv)); 2718 SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
2656 } 2719 }
2657 2720
2658 RETVAL = data_sv; 2721 RETVAL = data_sv;
2659} 2722}
2660 OUTPUT: 2723 OUTPUT:
2661 RETVAL 2724 RETVAL
2662 2725
2663void 2726void
2670 STRLEN len; 2733 STRLEN len;
2671 uint8_t *data, *end; 2734 uint8_t *data, *end;
2672 2735
2673 len = SvLEN (data_sv); 2736 len = SvLEN (data_sv);
2674 SvGROW (data_sv, len + 8); // reserve at least 7+ bytes more 2737 SvGROW (data_sv, len + 8); // reserve at least 7+ bytes more
2675 data = SvPVbyte_nolen (data_sv); 2738 data = (uint8_t *)SvPVbyte_nolen (data_sv);
2676 end = data + len + 8; 2739 end = data + len + 8;
2677 2740
2678 if (len < 5) 2741 if (len < 5)
2679 XSRETURN_EMPTY; 2742 XSRETURN_EMPTY;
2680 2743
2724 2787
2725 for (z = 0; z <= 2; z++) 2788 for (z = 0; z <= 2; z++)
2726 { 2789 {
2727 tileid t = tile [z]; 2790 tileid t = tile [z];
2728 2791
2729 if (t >= self->texs || (t && !self->tex [t].name)) 2792 if (t >= self->tex.size () || (t && !self->tex[t].name))
2730 { 2793 {
2731 PUSHs (sv_2mortal (newSViv (t))); 2794 PUSHs (sv_2mortal (newSViv (t)));
2732 need_texid (self, t); 2795 if (self->tex.size () <= t) self->tex.resize (t + 1);
2733 } 2796 }
2734 2797
2735 cell->tile [z] = t; 2798 cell->tile[z] = t;
2736 } 2799 }
2737 } 2800 }
2738 } 2801 }
2739 } 2802 }
2740 } 2803 }
2741} 2804}
2742 2805
2743MODULE = Deliantra::Client PACKAGE = DC::RW 2806MODULE = Deliantra::Client PACKAGE = DC::RW
2744 2807
2745DC::RW 2808DC::RW
2746new (SV *class, SV *data_sv) 2809new (SV *klass, SV *data_sv)
2747 CODE: 2810 CODE:
2748{ 2811{
2749 STRLEN datalen; 2812 STRLEN datalen;
2750 char *data = SvPVbyte (data_sv, datalen); 2813 char *data = SvPVbyte (data_sv, datalen);
2751 2814
2753} 2816}
2754 OUTPUT: 2817 OUTPUT:
2755 RETVAL 2818 RETVAL
2756 2819
2757DC::RW 2820DC::RW
2758new_from_file (SV *class, const char *path, const char *mode = "rb") 2821new_from_file (SV *klass, const char *path, const char *mode = "rb")
2759 CODE: 2822 CODE:
2760 RETVAL = SDL_RWFromFile (path, mode); 2823 RETVAL = SDL_RWFromFile (path, mode);
2761 OUTPUT: 2824 OUTPUT:
2762 RETVAL 2825 RETVAL
2763 2826
2781 if (RETVAL < 0) 2844 if (RETVAL < 0)
2782 { 2845 {
2783 RETVAL = Mix_GroupOldest (-1); 2846 RETVAL = Mix_GroupOldest (-1);
2784 2847
2785 if (RETVAL < 0) 2848 if (RETVAL < 0)
2849 {
2850 // happens sometimes, maybe it just stopped playing(?)
2851 RETVAL = Mix_GroupAvailable (-1);
2852
2853 if (RETVAL < 0)
2786 XSRETURN_UNDEF; 2854 XSRETURN_UNDEF;
2787 2855 }
2856 else
2788 Mix_HaltChannel (RETVAL); 2857 Mix_HaltChannel (RETVAL);
2789 } 2858 }
2790 2859
2791 Mix_UnregisterAllEffects (RETVAL); 2860 Mix_UnregisterAllEffects (RETVAL);
2792 Mix_Volume (RETVAL, 128); 2861 Mix_Volume (RETVAL, 128);
2793} 2862}
2853 2922
2854MODULE = Deliantra::Client PACKAGE = DC::MixChunk 2923MODULE = Deliantra::Client PACKAGE = DC::MixChunk
2855 2924
2856PROTOTYPES: DISABLE 2925PROTOTYPES: DISABLE
2857 2926
2927void
2928decoders ()
2929 PPCODE:
2930#if SDL_MIXER_MAJOR_VERSION > 1 || SDL_MIXER_MINOR_VERSION > 2 || SDL_MIXER_PATCHLEVEL >= 10
2931 int i, num = Mix_GetNumChunkDecoders ();
2932 EXTEND (SP, num);
2933 for (i = 0; i < num; ++i)
2934 PUSHs (sv_2mortal (newSVpv (Mix_GetChunkDecoder (i), 0)));
2935#else
2936 XPUSHs (sv_2mortal (newSVpv ("(sdl mixer too old)", 0)));
2937#endif
2938
2858DC::MixChunk 2939DC::MixChunk
2859new (SV *class, DC::RW rwops) 2940new (SV *klass, DC::RW rwops)
2860 CODE: 2941 CODE:
2861 RETVAL = Mix_LoadWAV_RW (rwops, 1); 2942 RETVAL = Mix_LoadWAV_RW (rwops, 1);
2862 OUTPUT: 2943 OUTPUT:
2863 RETVAL 2944 RETVAL
2864 2945
2894 OUTPUT: 2975 OUTPUT:
2895 RETVAL 2976 RETVAL
2896 2977
2897MODULE = Deliantra::Client PACKAGE = DC::MixMusic 2978MODULE = Deliantra::Client PACKAGE = DC::MixMusic
2898 2979
2980void
2981decoders ()
2982 PPCODE:
2983#if SDL_MIXER_MAJOR_VERSION > 1 || SDL_MIXER_MINOR_VERSION > 2 || SDL_MIXER_PATCHLEVEL >= 10
2984 int i, num = Mix_GetNumMusicDecoders ();
2985 EXTEND (SP, num);
2986 for (i = 0; i < num; ++i)
2987 PUSHs (sv_2mortal (newSVpv (Mix_GetMusicDecoder (i), 0)));
2988#else
2989 XPUSHs (sv_2mortal (newSVpv ("(sdl mixer too old)", 0)));
2990#endif
2991
2899int 2992int
2900volume (int volume = -1) 2993volume (int volume = -1)
2901 PROTOTYPE: ;$ 2994 PROTOTYPE: ;$
2902 CODE: 2995 CODE:
2903 if (items > 0) 2996 if (items > 0)
2914void 3007void
2915halt () 3008halt ()
2916 CODE: 3009 CODE:
2917 Mix_HaltMusic (); 3010 Mix_HaltMusic ();
2918 3011
3012int
3013playing ()
3014 CODE:
3015 RETVAL = Mix_PlayingMusic ();
3016 OUTPUT:
3017 RETVAL
3018
2919DC::MixMusic 3019DC::MixMusic
2920new (SV *class, DC::RW rwops) 3020new (SV *klass, DC::RW rwops)
2921 CODE: 3021 CODE:
2922 RETVAL = Mix_LoadMUS_RW (rwops); 3022 RETVAL = Mix_LoadMUS_RW (rwops);
2923 OUTPUT: 3023 OUTPUT:
2924 RETVAL 3024 RETVAL
2925 3025
3062 const_iv (GL_FUNC_SUBTRACT), 3162 const_iv (GL_FUNC_SUBTRACT),
3063 const_iv (GL_FUNC_REVERSE_SUBTRACT), 3163 const_iv (GL_FUNC_REVERSE_SUBTRACT),
3064# undef const_iv 3164# undef const_iv
3065 }; 3165 };
3066 3166
3067 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) 3167 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--)
3068 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 3168 newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv));
3069 3169
3070 texture_av = newAV (); 3170 texture_av = newAV ();
3071 AvREAL_off (texture_av); 3171 AvREAL_off (texture_av);
3072} 3172}
3073 3173
3078 gl.BlendFuncSeparateEXT = 0; 3178 gl.BlendFuncSeparateEXT = 0;
3079 3179
3080void 3180void
3081apple_nvidia_bug (int enable) 3181apple_nvidia_bug (int enable)
3082 3182
3083char * 3183const char *
3084gl_vendor () 3184gl_vendor ()
3085 CODE: 3185 CODE:
3086 RETVAL = (char *)glGetString (GL_VENDOR); 3186 RETVAL = (const char *)glGetString (GL_VENDOR);
3087 OUTPUT: 3187 OUTPUT:
3088 RETVAL 3188 RETVAL
3089 3189
3090char * 3190const char *
3091gl_version () 3191gl_version ()
3092 CODE: 3192 CODE:
3093 RETVAL = (char *)glGetString (GL_VERSION); 3193 RETVAL = (const char *)glGetString (GL_VERSION);
3094 OUTPUT: 3194 OUTPUT:
3095 RETVAL 3195 RETVAL
3096 3196
3097char * 3197const char *
3098gl_extensions () 3198gl_extensions ()
3099 CODE: 3199 CODE:
3100 RETVAL = (char *)glGetString (GL_EXTENSIONS); 3200 RETVAL = (const char *)glGetString (GL_EXTENSIONS);
3101 OUTPUT: 3201 OUTPUT:
3102 RETVAL 3202 RETVAL
3103 3203
3104const char *glGetString (GLenum pname) 3204const char *glGetString (GLenum pname)
3205 CODE:
3206 RETVAL = (const char *)glGetString (pname);
3207 OUTPUT:
3208 RETVAL
3105 3209
3106GLint glGetInteger (GLenum pname) 3210GLint glGetInteger (GLenum pname)
3107 CODE: 3211 CODE:
3108 glGetIntegerv (pname, &RETVAL); 3212 glGetIntegerv (pname, &RETVAL);
3109 OUTPUT: 3213 OUTPUT:
3116 RETVAL 3220 RETVAL
3117 3221
3118int glGetError () 3222int glGetError ()
3119 3223
3120void glFinish () 3224void glFinish ()
3225
3226void glFlush ()
3121 3227
3122void glClear (int mask) 3228void glClear (int mask)
3123 3229
3124void glClearColor (float r, float g, float b, float a = 1.0) 3230void glClearColor (float r, float g, float b, float a = 1.0)
3125 PROTOTYPE: @ 3231 PROTOTYPE: @
3297 3403
3298void glEndList () 3404void glEndList ()
3299 3405
3300void glCallList (int list) 3406void glCallList (int list)
3301 3407
3408void c_init ()
3409 CODE:
3410 glPixelStorei (GL_PACK_ALIGNMENT , 1);
3411 glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
3412
3302MODULE = Deliantra::Client PACKAGE = DC::UI::Base 3413MODULE = Deliantra::Client PACKAGE = DC::UI::Base
3303 3414
3304PROTOTYPES: DISABLE 3415PROTOTYPES: DISABLE
3305 3416
3306void 3417void
3307find_widget (SV *self, NV x, NV y) 3418find_widget (SV *self, NV x, NV y)
3308 PPCODE: 3419 PPCODE:
3309{ 3420{
3310 if (within_widget (self, x, y)) 3421 if (within_widget (self, x, y))
3311 XPUSHs (self); 3422 XPUSHs (self);
3312} 3423}
3313 3424
3314BOOT: 3425BOOT:
3315{ 3426{
3323 3434
3324void 3435void
3325draw (SV *self) 3436draw (SV *self)
3326 CODE: 3437 CODE:
3327{ 3438{
3328 HV *hv; 3439 HV *hv;
3329 SV **svp; 3440 SV **svp;
3330 NV x, y, w, h; 3441 NV x, y, w, h;
3331 SV *draw_x_sv = GvSV (draw_x_gv); 3442 SV *draw_x_sv = GvSV (draw_x_gv);
3332 SV *draw_y_sv = GvSV (draw_y_gv); 3443 SV *draw_y_sv = GvSV (draw_y_gv);
3333 SV *draw_w_sv = GvSV (draw_w_gv); 3444 SV *draw_w_sv = GvSV (draw_w_gv);
3334 SV *draw_h_sv = GvSV (draw_h_gv); 3445 SV *draw_h_sv = GvSV (draw_h_gv);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines