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.332 by root, Mon Nov 19 00:56:08 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
69# include <netinet/in.h> 76# include <netinet/in.h>
70# include <netinet/tcp.h> 77# include <netinet/tcp.h>
71# include <inttypes.h> 78# include <inttypes.h>
72#endif 79#endif
73 80
74#if __GNUC__ >= 4 81#include "ecb.h"
75# define expect(expr,value) __builtin_expect ((expr),(value))
76#else
77# define expect(expr,value) (expr)
78#endif
79
80#define expect_false(expr) expect ((expr) != 0, 0)
81#define expect_true(expr) expect ((expr) != 0, 1)
82 82
83#define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, object replacement character */ 83#define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, object replacement character */
84 84
85/* this is used as fow flag as well, so has to have a different value */
86/* then anything that is computed by incoming darkness */
85#define FOW_DARKNESS 64 87#define FOW_DARKNESS 50
86#define DARKNESS_ADJUST(n) ((29 * (int)(n)) >> 5) /* times 0.9 */ 88#define DARKNESS_ADJUST(n) (n)
87 89
88#define MAP_EXTEND_X 32 90#define MAP_EXTEND_X 32
89#define MAP_EXTEND_Y 512 91#define MAP_EXTEND_Y 512
90 92
91#define MIN_FONT_HEIGHT 10 93#define MIN_FONT_HEIGHT 10
95 97
96#define KMOD_LRAM 0x10000 // our extension 98#define KMOD_LRAM 0x10000 // our extension
97 99
98#define TEXID_SPEECH 1 100#define TEXID_SPEECH 1
99#define TEXID_NOFACE 2 101#define TEXID_NOFACE 2
100#define TEXID_HIDDEN 3 102
103static char *
104fast_sv_grow (SV *sv, STRLEN need)
105{
106 STRLEN len = SvLEN (sv);
107 STRLEN want = SvCUR (sv) + need;
108
109 if (ecb_expect_false (len < want))
110 {
111 do
112 len *= 2;
113 while (len < want);
114
115 sv_grow (sv, len);
116 }
117
118 SvCUR_set (sv, want);
119 return SvEND (sv) - need;
120}
101 121
102static AV *texture_av; 122static AV *texture_av;
103 123
104static struct 124static struct
105{ 125{
162{ 182{
163 GSList *attrs = run->item->analysis.extra_attrs; 183 GSList *attrs = run->item->analysis.extra_attrs;
164 184
165 while (attrs) 185 while (attrs)
166 { 186 {
167 PangoAttribute *attr = attrs->data; 187 PangoAttribute *attr = (PangoAttribute *)attrs->data;
168 188
169 if (attr->klass->type == PANGO_ATTR_SHAPE) 189 if (attr->klass->type == PANGO_ATTR_SHAPE)
170 return 1; 190 return 1;
171 191
172 attrs = attrs->next; 192 attrs = attrs->next;
173 } 193 }
174 194
175 return 0; 195 return 0;
176} 196}
177 197
178typedef struct cf_layout { 198struct cf_layout {
179 PangoLayout *pl; 199 PangoLayout *pl;
180 float r, g, b, a; // default color for rgba mode 200 float r, g, b, a; // default color for rgba mode
181 int base_height; 201 int base_height;
182 DC__Font font; 202 DC__Font font;
183 rc_t *rc; 203 rc_t rc;
184} *DC__Layout; 204};
205
206typedef cf_layout *DC__Layout;
185 207
186static DC__Font default_font; 208static DC__Font default_font;
187static PangoContext *opengl_context; 209static PangoContext *opengl_context;
188static PangoFontMap *opengl_fontmap; 210static PangoFontMap *opengl_fontmap;
189 211
190static void 212static void
191substitute_func (FcPattern *pattern, gpointer data) 213substitute_func (FcPattern *pattern, gpointer data)
192{ 214{
193 FcPatternAddBool (pattern, FC_HINTING, 1); 215 FcPatternAddBool (pattern, FC_HINTING, 1);
194#ifdef FC_HINT_STYLE 216#ifdef FC_HINT_STYLE
195 FcPatternAddBool (pattern, FC_HINT_STYLE, FC_HINT_FULL); 217 FcPatternAddInteger (pattern, FC_HINT_STYLE, FC_HINT_FULL);
196#endif 218#endif
197 FcPatternAddBool (pattern, FC_AUTOHINT, 0); 219 FcPatternAddBool (pattern, FC_AUTOHINT, 0);
198} 220}
199 221
200static void 222static void
227 249
228 *w = rect.width; 250 *w = rect.width;
229 *h = rect.height; 251 *h = rect.height;
230} 252}
231 253
254/////////////////////////////////////////////////////////////////////////////
255
232typedef uint16_t tileid; 256typedef uint16_t tileid;
233typedef uint16_t faceid; 257typedef uint16_t faceid;
234 258
235typedef struct { 259struct maptex
260{
236 GLuint name; 261 GLuint name;
237 int w, h; 262 int w, h;
238 float s, t; 263 float s, t;
239 uint8_t r, g, b, a; 264 uint8_t r, g, b, a;
240 tileid smoothtile; 265 tileid smoothtile;
241 uint8_t smoothlevel; 266 uint8_t smoothlevel;
242 uint8_t unused; /* set to zero on use */ 267 uint8_t unused; /* set to zero on use */
243} maptex; 268};
244 269
245typedef struct { 270struct mapcell
271{
246 uint32_t player; 272 uint32_t player;
247 tileid tile[3]; 273 tileid tile[3];
248 uint16_t darkness; 274 uint16_t darkness;
249 uint8_t stat_width, stat_hp, flags, smoothmax; 275 uint8_t stat_width, stat_hp, flags, smoothmax;
250} mapcell; 276};
251 277
252typedef struct { 278struct maprow
279{
253 int32_t c0, c1; 280 int32_t c0, c1;
254 mapcell *col; 281 mapcell *col;
255} maprow; 282};
256 283
257typedef struct map { 284struct mapgrid {
258 int x, y, w, h; 285 int x, y, w, h;
259 int ox, oy; /* offset to virtual global coordinate system */ 286 int ox, oy; /* offset to virtual global coordinate system */
260 int faces; tileid *face2tile; // [faceid] 287 int faces; tileid *face2tile; // [faceid]
261 int texs; maptex *tex; // [tileid] 288 int texs; maptex *tex; // [tileid]
262 289
263 int32_t rows; 290 int32_t rows;
264 maprow *row; 291 maprow *row;
265} *DC__Map; 292};
266 293
267static char * 294typedef mapgrid *DC__Map;
295
296template<typename T>
297static void
268prepend (char *ptr, int sze, int inc) 298prepend (T *&ptr, int sze, int inc)
269{ 299{
270 char *p; 300 T *p;
271 301
272 New (0, p, sze + inc, char); 302 Newx (p, inc + sze, T);
273 Zero (p, inc, char); 303 Zero (p, inc, T);
274 Move (ptr, p + inc, sze, char); 304 Move (ptr, p + inc, sze, T);
275 Safefree (ptr); 305 Safefree (ptr);
276 306
277 return p; 307 ptr = p;
278} 308}
279 309
280static char * 310template<typename T>
281append (char *ptr, int sze, int inc)
282{
283 Renew (ptr, sze + inc, char);
284 Zero (ptr + sze, inc, char);
285
286 return ptr;
287}
288
289#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))
291
292static void 311static void
312append (T *&ptr, int sze, int inc)
313{
314 Renew (ptr, sze + inc, T);
315 Zero (ptr + sze, inc, T);
316}
317
318static void
293need_facenum (struct map *self, faceid face) 319need_facenum (struct mapgrid *self, faceid face)
294{ 320{
295 while (self->faces <= face) 321 while (self->faces <= face)
296 { 322 {
297 Append (tileid, self->face2tile, self->faces, self->faces); 323 append (self->face2tile, self->faces, self->faces);
298 self->faces *= 2; 324 self->faces *= 2;
299 } 325 }
300} 326}
301 327
302static void 328static void
303need_texid (struct map *self, int texid) 329need_texid (struct mapgrid *self, int texid)
304{ 330{
305 while (self->texs <= texid) 331 while (self->texs <= texid)
306 { 332 {
307 Append (maptex, self->tex, self->texs, self->texs); 333 append (self->tex, self->texs, self->texs);
308 self->texs *= 2; 334 self->texs *= 2;
309 } 335 }
310} 336}
311 337
312static maprow * 338static maprow *
313map_get_row (DC__Map self, int y) 339map_get_row (mapgrid *self, int y)
314{ 340{
315 if (0 > y) 341 if (0 > y)
316 { 342 {
317 int extend = - y + MAP_EXTEND_Y; 343 int extend = - y + MAP_EXTEND_Y;
318 Prepend (maprow, self->row, self->rows, extend); 344 prepend (self->row, self->rows, extend);
319 345
320 self->rows += extend; 346 self->rows += extend;
321 self->y += extend; 347 self->y += extend;
322 y += extend; 348 y += extend;
323 } 349 }
324 else if (y >= self->rows) 350 else if (y >= self->rows)
325 { 351 {
326 int extend = y - self->rows + MAP_EXTEND_Y; 352 int extend = y - self->rows + MAP_EXTEND_Y;
327 Append (maprow, self->row, self->rows, extend); 353 append (self->row, self->rows, extend);
328 self->rows += extend; 354 self->rows += extend;
329 } 355 }
330 356
331 return self->row + y; 357 return self->row + y;
332} 358}
342 } 368 }
343 369
344 if (row->c0 > x) 370 if (row->c0 > x)
345 { 371 {
346 int extend = row->c0 - x + MAP_EXTEND_X; 372 int extend = row->c0 - x + MAP_EXTEND_X;
347 Prepend (mapcell, row->col, row->c1 - row->c0, extend); 373 prepend (row->col, row->c1 - row->c0, extend);
348 row->c0 -= extend; 374 row->c0 -= extend;
349 } 375 }
350 else if (x >= row->c1) 376 else if (x >= row->c1)
351 { 377 {
352 int extend = x - row->c1 + MAP_EXTEND_X; 378 int extend = x - row->c1 + MAP_EXTEND_X;
353 Append (mapcell, row->col, row->c1 - row->c0, extend); 379 append (row->col, row->c1 - row->c0, extend);
354 row->c1 += extend; 380 row->c1 += extend;
355 } 381 }
356 382
357 return row->col + (x - row->c0); 383 return row->col + (x - row->c0);
358} 384}
359 385
360static mapcell * 386static mapcell *
361map_get_cell (DC__Map self, int x, int y) 387map_get_cell (mapgrid *self, int x, int y)
362{ 388{
363 return row_get_cell (map_get_row (self, y), x); 389 return row_get_cell (map_get_row (self, y), x);
364} 390}
365 391
366static void 392static void
367map_clear (DC__Map self) 393map_clear (mapgrid *self)
368{ 394{
369 int r; 395 int r;
370 396
371 for (r = 0; r < self->rows; r++) 397 for (r = 0; r < self->rows; r++)
372 Safefree (self->row[r].col); 398 Safefree (self->row[r].col);
390 (cell)->flags = 0; \ 416 (cell)->flags = 0; \
391 (cell)->player = 0; \ 417 (cell)->player = 0; \
392 } while (0) 418 } while (0)
393 419
394static void 420static void
395map_blank (DC__Map self, int x0, int y0, int w, int h) 421map_blank (mapgrid *self, int x0, int y0, int w, int h)
396{ 422{
397 int x, y; 423 int x, y;
398 maprow *row; 424 maprow *row;
399 mapcell *cell; 425 mapcell *cell;
400 426
417 CELL_CLEAR (cell); 443 CELL_CLEAR (cell);
418 } 444 }
419 } 445 }
420} 446}
421 447
422typedef struct { 448struct smooth_key
449{
423 tileid tile; 450 tileid tile;
424 uint8_t x, y, level; 451 uint8_t x, y, level;
425} smooth_key; 452
453 bool operator == (const smooth_key &o) const
454 {
455 return tile == o.tile && x == o.x && y == o.y && level == o.level;
456 }
457};
458
459typedef ska::flat_hash_map<smooth_key, IV> smooth_hash;
460
461namespace std {
462 template <>
463 struct hash<smooth_key>
464 {
465 size_t operator () (const smooth_key &v) const
466 {
467 return v.tile + (v.x << 8) + (v.y << 16) + (v.level << 24);
468 }
469 };
470}
426 471
427static void 472static void
428smooth_or_bits (HV *hv, smooth_key *key, IV bits) 473smooth_or_bits (smooth_hash &h, smooth_key &key, IV bits)
429{ 474{
430 SV **sv = hv_fetch (hv, (char *)key, sizeof (*key), 1); 475 auto &&it = h.find (key);
431 476
432 if (SvIOK (*sv)) 477 if (it == h.end ())
433 SvIV_set (*sv, SvIVX (*sv) | bits); 478 h.insert (std::make_pair (key, bits));
434 else 479 else
435 sv_setiv (*sv, bits); 480 it->second |= bits;
436} 481}
437 482
438static void 483static void
439music_finished (void) 484music_finished (void)
440{ 485{
457 ev.code = 1; 502 ev.code = 1;
458 ev.data1 = (void *)(long)channel; 503 ev.data1 = (void *)(long)channel;
459 ev.data2 = 0; 504 ev.data2 = 0;
460 505
461 SDL_PushEvent ((SDL_Event *)&ev); 506 SDL_PushEvent ((SDL_Event *)&ev);
507}
508
509// approximately divide by 255
510static unsigned int
511div255 (unsigned int n)
512{
513 return (n + (n >> 8)) >> 8;
462} 514}
463 515
464static unsigned int 516static unsigned int
465minpot (unsigned int n) 517minpot (unsigned int n)
466{ 518{
476 n |= n >> 16; 528 n |= n >> 16;
477 529
478 return n + 1; 530 return n + 1;
479} 531}
480 532
481static unsigned int
482popcount (unsigned int n)
483{
484 n -= (n >> 1) & 0x55555555U;
485 n = ((n >> 2) & 0x33333333U) + (n & 0x33333333U);
486 n = ((n >> 4) + n) & 0x0f0f0f0fU;
487 n *= 0x01010101U;
488
489 return n >> 24;
490}
491
492/* SDL should provide this, really. */ 533/* SDL should provide this, really. */
493#define SDLK_MODIFIER_MIN 300 534#define SDLK_MODIFIER_MIN 300
494#define SDLK_MODIFIER_MAX 314 535#define SDLK_MODIFIER_MAX 314
495 536
496/******************************************************************************/ 537/******************************************************************************/
549 590
550 return mod; 591 return mod;
551} 592}
552 593
553static void 594static void
554deliantra_main () 595deliantra_main (SV *real_main)
555{ 596{
556 char *argv[] = { 0 }; 597 dSP;
557 call_argv ("::main", G_DISCARD | G_VOID, argv); 598
599 PUSHMARK (SP);
600 call_sv (real_main, G_DISCARD | G_VOID);
558} 601}
559 602
560#ifdef __MACOSX__ 603#ifdef __MACOSX__
604 static SV *real_main;
605
561 /* to due surprising braindamage on the side of SDL design, we 606 /* to due surprising braindamage on the side of SDL design, we
562 * do some mind-boggling hack here: SDL requires a custom main() 607 * 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, 608 * 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, 609 * due to shared library magic, calls -lSDLmain's main, not perl's main,
565 * and which calls our main (== SDL_main) back. 610 * and which calls our main (== SDL_main) back.
566 */ 611 */
567 extern C_LINKAGE int 612 extern C_LINKAGE int
568 main (int argc, char *argv[]) 613 main (int argc, char *argv[])
569 { 614 {
570 deliantra_main (); 615 deliantra_main (real_main);
571 } 616 }
572 617
573 #undef main 618 #undef main
574 619
575 extern C_LINKAGE int main (int argc, char *argv[]); 620 extern C_LINKAGE int main (int argc, char *argv[]);
576 621
577 static void 622 static void
578 SDL_braino (void) 623 SDL_main_hack (SV *real_main_)
579 { 624 {
625 real_main = real_main_;
626
580 char *argv[] = { "deliantra client", 0 }; 627 char *argv[] = { "deliantra client", 0 };
581 (main) (1, argv); 628 (main) (1, argv);
582 } 629 }
583#else 630#else
584 static void 631 static void
585 SDL_braino (void) 632 SDL_main_hack (SV *real_main)
586 { 633 {
587 deliantra_main (); 634 deliantra_main (real_main);
588 } 635 }
589#endif 636#endif
590 637
591MODULE = Deliantra::Client PACKAGE = DC 638MODULE = Deliantra::Client PACKAGE = DC
592 639
793 840
794 const_iv (FOW_DARKNESS) 841 const_iv (FOW_DARKNESS)
795# undef const_iv 842# undef const_iv
796 }; 843 };
797 844
798 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) 845 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--)
799 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 846 newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv));
800 847
801 assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK); 848 assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK);
802 assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE); 849 assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE);
803} 850}
804 851
819 866
820NV ceil (NV x) 867NV ceil (NV x)
821 868
822IV minpot (UV n) 869IV minpot (UV n)
823 870
871UV ld32 (UV n)
872 CODE:
873 RETVAL = ecb_ld32 (n);
874 OUTPUT:
875 RETVAL
876
824IV popcount (UV n) 877IV popcount (UV n)
878 CODE:
879 RETVAL = ecb_popcount32 (n);
880 OUTPUT:
881 RETVAL
825 882
826NV distance (NV dx, NV dy) 883NV distance (NV dx, NV dy)
827 CODE: 884 CODE:
828 RETVAL = pow (dx * dx + dy * dy, 0.5); 885 RETVAL = pow (dx * dx + dy * dy, 0.5);
829 OUTPUT: 886 OUTPUT:
843#endif 900#endif
844} 901}
845 902
846char *SDL_GetError () 903char *SDL_GetError ()
847 904
848void SDL_braino () 905void SDL_main_hack (SV *real_main)
906 PROTOTYPE: &
849 907
850int SDL_Init (U32 flags) 908int SDL_Init (U32 flags)
851 909
852int SDL_InitSubSystem (U32 flags) 910int SDL_InitSubSystem (U32 flags)
853 911
854void SDL_QuitSubSystem (U32 flags) 912void SDL_QuitSubSystem (U32 flags)
855 913
856void SDL_Quit () 914void SDL_Quit ()
857 915
858int SDL_GL_SetAttribute (int attr, int value) 916int SDL_GL_SetAttribute (int attr, int value)
917 C_ARGS: (SDL_GLattr)attr, value
859 918
860int SDL_GL_GetAttribute (int attr) 919int SDL_GL_GetAttribute (int attr)
861 CODE: 920 CODE:
862 if (SDL_GL_GetAttribute (attr, &RETVAL)) 921 if (SDL_GL_GetAttribute ((SDL_GLattr)attr, &RETVAL))
863 XSRETURN_UNDEF; 922 XSRETURN_UNDEF;
864 OUTPUT: 923 OUTPUT:
865 RETVAL 924 RETVAL
866 925
867void 926void
922 ); 981 );
923 982
924 if (RETVAL) 983 if (RETVAL)
925 { 984 {
926 av_clear (texture_av); 985 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); 986#define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name);
930#include "glfunc.h" 987#include "glfunc.h"
931#undef GL_FUNC 988#undef GL_FUNC
989 if (!gl.ActiveTexture ) gl.ActiveTexture = gl.ActiveTextureARB;
990 if (!gl.MultiTexCoord2f) gl.MultiTexCoord2f = gl.MultiTexCoord2fARB;
932 } 991 }
933} 992}
934 OUTPUT: 993 OUTPUT:
935 RETVAL 994 RETVAL
995
996void
997SDL_WM_SetCaption (const char *title, const char *icon)
936 998
937void 999void
938SDL_GL_SwapBuffers () 1000SDL_GL_SwapBuffers ()
939 1001
940char * 1002char *
941SDL_GetKeyName (int sym) 1003SDL_GetKeyName (int sym)
1004 C_ARGS: (SDLKey)sym
942 1005
943int 1006int
944SDL_GetAppState () 1007SDL_GetAppState ()
945 1008
946int 1009int
947SDL_GetModState () 1010SDL_GetModState ()
948 1011
1012int
1013SDL_WaitEvent ()
1014 C_ARGS: 0
1015
949void 1016void
1017SDL_PumpEvents ()
1018
1019void
950poll_events () 1020peep_events ()
951 PPCODE: 1021 PPCODE:
952{ 1022{
953 SDL_Event ev; 1023 SDL_Event ev;
954 1024
955 SDL_PumpEvents (); 1025 SDL_PumpEvents ();
1021 1091
1022 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("DC::UI::Event", 1)))); 1092 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("DC::UI::Event", 1))));
1023 } 1093 }
1024} 1094}
1025 1095
1096char *
1097SDL_AudioDriverName ()
1098 CODE:
1099{
1100 char buf [256];
1101 if (!SDL_AudioDriverName (buf, sizeof (buf)))
1102 XSRETURN_UNDEF;
1103
1104 RETVAL = buf;
1105}
1106 OUTPUT:
1107 RETVAL
1108
1026int 1109int
1027Mix_OpenAudio (int frequency = 44100, int format = MIX_DEFAULT_FORMAT, int channels = 2, int chunksize = 4096) 1110Mix_OpenAudio (int frequency = 44100, int format = MIX_DEFAULT_FORMAT, int channels = 2, int chunksize = 4096)
1028 POSTCALL: 1111 POSTCALL:
1029 Mix_HookMusicFinished (music_finished); 1112 Mix_HookMusicFinished (music_finished);
1030 Mix_ChannelFinished (channel_finished); 1113 Mix_ChannelFinished (channel_finished);
1031 1114
1032void 1115void
1033Mix_QuerySpec () 1116Mix_QuerySpec ()
1092add_font (char *file) 1175add_font (char *file)
1093 CODE: 1176 CODE:
1094 RETVAL = FcConfigAppFontAddFile (0, (const FcChar8 *)file); 1177 RETVAL = FcConfigAppFontAddFile (0, (const FcChar8 *)file);
1095 OUTPUT: 1178 OUTPUT:
1096 RETVAL 1179 RETVAL
1180
1181void
1182IMG_Init (int flags = IMG_INIT_JPG | IMG_INIT_PNG)
1183
1184# MIX_INIT_MP3 gives smpeg + libstdc++ + libgcc_s
1185void
1186Mix_Init (int flags = MIX_INIT_MOD | MIX_INIT_OGG)
1097 1187
1098void 1188void
1099load_image_inline (SV *image_) 1189load_image_inline (SV *image_)
1100 ALIAS: 1190 ALIAS:
1101 load_image_file = 1 1191 load_image_file = 1
1147 1237
1148 SDL_LockSurface (surface2); 1238 SDL_LockSurface (surface2);
1149 EXTEND (SP, 6); 1239 EXTEND (SP, 6);
1150 PUSHs (sv_2mortal (newSViv (surface2->w))); 1240 PUSHs (sv_2mortal (newSViv (surface2->w)));
1151 PUSHs (sv_2mortal (newSViv (surface2->h))); 1241 PUSHs (sv_2mortal (newSViv (surface2->h)));
1152 PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch))); 1242 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))); 1243 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
1154 PUSHs (sv_2mortal (newSViv (GL_RGBA))); 1244 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
1155 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE))); 1245 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
1156 SDL_UnlockSurface (surface2); 1246 SDL_UnlockSurface (surface2);
1157 1247
1229MODULE = Deliantra::Client PACKAGE = DC::Font 1319MODULE = Deliantra::Client PACKAGE = DC::Font
1230 1320
1231PROTOTYPES: DISABLE 1321PROTOTYPES: DISABLE
1232 1322
1233DC::Font 1323DC::Font
1234new_from_file (SV *class, char *path, int id = 0) 1324new_from_file (SV *klass, char *path, int id = 0)
1235 CODE: 1325 CODE:
1236{ 1326{
1237 int count; 1327 int count;
1238 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count); 1328 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count);
1239 RETVAL = pango_fc_font_description_from_pattern (pattern, 0); 1329 RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
1268 PROTOTYPE: 1358 PROTOTYPE:
1269 CODE: 1359 CODE:
1270 tc_restore (); 1360 tc_restore ();
1271 1361
1272DC::Layout 1362DC::Layout
1273new (SV *class) 1363new (SV *klass)
1274 CODE: 1364 CODE:
1275 New (0, RETVAL, 1, struct cf_layout); 1365 RETVAL = new cf_layout;
1276 1366
1277 RETVAL->pl = pango_layout_new (opengl_context); 1367 RETVAL->pl = pango_layout_new (opengl_context);
1278 RETVAL->r = 1.; 1368 RETVAL->r = 1.;
1279 RETVAL->g = 1.; 1369 RETVAL->g = 1.;
1280 RETVAL->b = 1.; 1370 RETVAL->b = 1.;
1281 RETVAL->a = 1.; 1371 RETVAL->a = 1.;
1282 RETVAL->base_height = MIN_FONT_HEIGHT; 1372 RETVAL->base_height = MIN_FONT_HEIGHT;
1283 RETVAL->font = 0; 1373 RETVAL->font = 0;
1284 RETVAL->rc = rc_alloc ();
1285 1374
1286 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR); 1375 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
1287 layout_update_font (RETVAL); 1376 layout_update_font (RETVAL);
1288 OUTPUT: 1377 OUTPUT:
1289 RETVAL 1378 RETVAL
1290 1379
1291void 1380void
1292DESTROY (DC::Layout self) 1381DESTROY (DC::Layout self)
1293 CODE: 1382 CODE:
1294 g_object_unref (self->pl); 1383 g_object_unref (self->pl);
1295 rc_free (self->rc);
1296 Safefree (self); 1384 delete self;
1297 1385
1298void 1386void
1299set_text (DC::Layout self, SV *text_) 1387set_text (DC::Layout self, SV *text_)
1300 CODE: 1388 CODE:
1301{ 1389{
1427 1515
1428void 1516void
1429set_height (DC::Layout self, int base_height) 1517set_height (DC::Layout self, int base_height)
1430 CODE: 1518 CODE:
1431 if (self->base_height != base_height) 1519 if (self->base_height != base_height)
1432 { 1520 {
1433 self->base_height = base_height; 1521 self->base_height = base_height;
1434 layout_update_font (self); 1522 layout_update_font (self);
1435 } 1523 }
1436 1524
1437void 1525void
1555} 1643}
1556 1644
1557void 1645void
1558render (DC::Layout self, float x, float y, int flags = 0) 1646render (DC::Layout self, float x, float y, int flags = 0)
1559 CODE: 1647 CODE:
1560 rc_clear (self->rc); 1648 self->rc.clear ();
1561 pango_opengl_render_layout_subpixel ( 1649 pango_opengl_render_layout_subpixel (
1562 self->pl, 1650 self->pl,
1563 self->rc, 1651 &self->rc,
1564 x * PANGO_SCALE, y * PANGO_SCALE, 1652 x * PANGO_SCALE, y * PANGO_SCALE,
1565 self->r, self->g, self->b, self->a, 1653 self->r, self->g, self->b, self->a,
1566 flags 1654 flags
1567 ); 1655 );
1568 // we assume that context_change actually clears/frees stuff 1656 // we assume that context_change actually clears/frees stuff
1579 gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 1667 gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1580 GL_ONE , GL_ONE_MINUS_SRC_ALPHA); 1668 GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1581 glEnable (GL_ALPHA_TEST); 1669 glEnable (GL_ALPHA_TEST);
1582 glAlphaFunc (GL_GREATER, 7.f / 255.f); 1670 glAlphaFunc (GL_GREATER, 7.f / 255.f);
1583 1671
1584 rc_draw (self->rc); 1672 self->rc.draw ();
1585 1673
1586 glDisable (GL_ALPHA_TEST); 1674 glDisable (GL_ALPHA_TEST);
1587 glDisable (GL_BLEND); 1675 glDisable (GL_BLEND);
1588 glDisable (GL_TEXTURE_2D); 1676 glDisable (GL_TEXTURE_2D);
1589} 1677}
1665 glDisable (GL_BLEND); 1753 glDisable (GL_BLEND);
1666 } 1754 }
1667} 1755}
1668 1756
1669void 1757void
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) 1758draw_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: @ 1759 PROTOTYPE: @
1672 CODE: 1760 CODE:
1673{ 1761{
1762 glEnable (GL_BLEND);
1763 glBlendFunc (intensity ? GL_SRC_ALPHA : GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1674 glEnable (GL_TEXTURE_2D); 1764 glEnable (GL_TEXTURE_2D);
1675 glEnable (GL_BLEND);
1676 glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1677 glBindTexture (GL_TEXTURE_2D, name1); 1765 glBindTexture (GL_TEXTURE_2D, name1);
1678 1766
1679 glColor3f (intensity, intensity, intensity); 1767 glColor3f (intensity, intensity, intensity);
1680 glPushMatrix (); 1768 glPushMatrix ();
1681 glScalef (1./3, 1./3, 1.); 1769 glScalef (1./3, 1./3, 1.);
1682 1770
1683 if (blend > 0.f) 1771 if (blend > 0.f)
1684 { 1772 {
1685 float S2, T2; /* 0. 0. for texture 2 */ 1773 float dx3 = dx * -3.f / w;
1686 float w = w1 > w2 ? w1 : w2; 1774 float dy3 = dy * -3.f / h;
1687 float h = h1 > h2 ? h1 : h2;
1688 GLfloat env_color[4] = { 0., 0., 0., blend }; 1775 GLfloat env_color[4] = { 0., 0., 0., blend };
1689 1776
1690 /* interpolate the two shadow textures */ 1777 /* interpolate the two shadow textures */
1691 /* stage 0 == rgb(glcolor) + alpha(t0) */ 1778 /* stage 0 == rgb(glcolor) + alpha(t0) */
1692 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 1779 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1697 glBindTexture (GL_TEXTURE_2D, name2); 1784 glBindTexture (GL_TEXTURE_2D, name2);
1698 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); 1785 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
1699 1786
1700 /* rgb == rgb(glcolor) */ 1787 /* rgb == rgb(glcolor) */
1701 glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); 1788 glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
1702 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_CONSTANT); 1789 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
1703 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); 1790 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
1704 1791
1705 /* alpha = interpolate t0, t1 by env_alpha */ 1792 /* alpha = interpolate t0, t1 by env_alpha */
1706 glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, env_color); 1793 glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, env_color);
1707 1794
1713 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); 1800 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
1714 1801
1715 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_CONSTANT); 1802 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_CONSTANT);
1716 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA); 1803 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA);
1717 1804
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); 1805 glBegin (GL_QUADS);
1730 gl.MultiTexCoord2f (GL_TEXTURE0, 0, 0); gl.MultiTexCoord2f (GL_TEXTURE1, dx , dy ); glVertex2f ( 0, 0); 1806 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); 1807 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); 1808 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); 1809 gl.MultiTexCoord2f (GL_TEXTURE0, s, 0); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 + s, dy3 ); glVertex2i (w, 0);
1734 glEnd (); 1810 glEnd ();
1735 1811
1736 glDisable (GL_TEXTURE_2D); 1812 glDisable (GL_TEXTURE_2D);
1737 gl.ActiveTexture (GL_TEXTURE0); 1813 gl.ActiveTexture (GL_TEXTURE0);
1738 } 1814 }
1740 { 1816 {
1741 /* simple blending of one texture, also opengl <1.3 path */ 1817 /* simple blending of one texture, also opengl <1.3 path */
1742 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 1818 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1743 1819
1744 glBegin (GL_QUADS); 1820 glBegin (GL_QUADS);
1745 glTexCoord2f ( 0, 0); glVertex2f ( 0, 0); 1821 glTexCoord2f (0, 0); glVertex2f (0, 0);
1746 glTexCoord2f ( 0, t1); glVertex2f ( 0, h1); 1822 glTexCoord2f (0, t); glVertex2f (0, h);
1747 glTexCoord2f (s1, t1); glVertex2f (w1, h1); 1823 glTexCoord2f (s, t); glVertex2f (w, h);
1748 glTexCoord2f (s1, 0); glVertex2f (w1, 0); 1824 glTexCoord2f (s, 0); glVertex2f (w, 0);
1749 glEnd (); 1825 glEnd ();
1750 } 1826 }
1827
1828 /* draw ?-marks or equivalent, this is very clumsy code :/ */
1829 {
1830 int x, y;
1831 int dx3 = dx * 3;
1832 int dy3 = dy * 3;
1833
1834 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1835 glBindTexture (GL_TEXTURE_2D, hidden_tex);
1836 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1837 glTranslatef (-1., -1., 0);
1838 glBegin (GL_QUADS);
1839
1840 for (y = 1; y < h; y += 3)
1841 {
1842 int y1 = y - dy3;
1843 int y1valid = y1 >= 0 && y1 < h;
1844
1845 for (x = 1; x < w; x += 3)
1846 {
1847 int x1 = x - dx3;
1848 uint8_t h1 = data1 [x + y * w] == DARKNESS_ADJUST (255 - FOW_DARKNESS);
1849 uint8_t h2;
1850
1851 if (y1valid && x1 >= 0 && x1 < w)
1852 h2 = data2 [x1 + y1 * w] == DARKNESS_ADJUST (255 - FOW_DARKNESS);
1853 else
1854 h2 = 1; /* out of range == invisible */
1855
1856 if (h1 || h2)
1857 {
1858 float alpha = h1 == h2 ? 1.f : h1 ? 1.f - blend : blend;
1859 glColor4f (1., 1., 1., alpha);
1860
1861 glTexCoord2f (0, 0.); glVertex2i (x , y );
1862 glTexCoord2f (0, 1.); glVertex2i (x , y + 3);
1863 glTexCoord2f (1, 1.); glVertex2i (x + 3, y + 3);
1864 glTexCoord2f (1, 0.); glVertex2i (x + 3, y );
1865 }
1866 }
1867 }
1868 }
1869
1870 glEnd ();
1751 1871
1752 glPopMatrix (); 1872 glPopMatrix ();
1753 1873
1754 glDisable (GL_TEXTURE_2D); 1874 glDisable (GL_TEXTURE_2D);
1755 glDisable (GL_BLEND); 1875 glDisable (GL_BLEND);
1769MODULE = Deliantra::Client PACKAGE = DC::Map 1889MODULE = Deliantra::Client PACKAGE = DC::Map
1770 1890
1771PROTOTYPES: DISABLE 1891PROTOTYPES: DISABLE
1772 1892
1773DC::Map 1893DC::Map
1774new (SV *class) 1894new (SV *klass)
1775 CODE: 1895 CODE:
1776 New (0, RETVAL, 1, struct map); 1896 New (0, RETVAL, 1, mapgrid);
1777 RETVAL->x = 0; 1897 RETVAL->x = 0;
1778 RETVAL->y = 0; 1898 RETVAL->y = 0;
1779 RETVAL->w = 0; 1899 RETVAL->w = 0;
1780 RETVAL->h = 0; 1900 RETVAL->h = 0;
1781 RETVAL->ox = 0; 1901 RETVAL->ox = 0;
1818 1938
1819void 1939void
1820set_smooth (DC::Map self, int face, int smooth, int level) 1940set_smooth (DC::Map self, int face, int smooth, int level)
1821 CODE: 1941 CODE:
1822{ 1942{
1823 tileid texid; 1943 tileid texid;
1824 maptex *tex; 1944 maptex *tex;
1825 1945
1826 if (face < 0 || face >= self->faces) 1946 if (face < 0 || face >= self->faces)
1827 return; 1947 return;
1828 1948
1829 if (smooth < 0 || smooth >= self->faces) 1949 if (smooth < 0 || smooth >= self->faces)
1830 return; 1950 return;
1831 1951
1832 texid = self->face2tile [face]; 1952 texid = self->face2tile [face];
1833 1953
1834 if (!texid) 1954 if (!texid)
1835 return; 1955 return;
1836 1956
1837 tex = self->tex + texid; 1957 tex = self->tex + texid;
1870} 1990}
1871 1991
1872void 1992void
1873expire_textures (DC::Map self, int texid, int count) 1993expire_textures (DC::Map self, int texid, int count)
1874 PPCODE: 1994 PPCODE:
1875 for (; texid < self->texs && count; ++texid, --count) 1995 for (; texid < self->texs && count; ++texid, --count)
1876 { 1996 {
1877 maptex *tex = self->tex + texid; 1997 maptex *tex = self->tex + texid;
1878 1998
1879 if (tex->name) 1999 if (tex->name)
1880 { 2000 {
1927 self->ox += dx; self->x += dx; 2047 self->ox += dx; self->x += dx;
1928 self->oy += dy; self->y += dy; 2048 self->oy += dy; self->y += dy;
1929 2049
1930 while (self->y < 0) 2050 while (self->y < 0)
1931 { 2051 {
1932 Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y); 2052 prepend (self->row, self->rows, MAP_EXTEND_Y);
1933 2053
1934 self->rows += MAP_EXTEND_Y; 2054 self->rows += MAP_EXTEND_Y;
1935 self->y += MAP_EXTEND_Y; 2055 self->y += MAP_EXTEND_Y;
1936 } 2056 }
1937} 2057}
1938 2058
1939SV * 2059SV *
1940map1a_update (DC::Map self, SV *data_, int extmap) 2060map1a_update (DC::Map self, SV *data_)
1941 CODE: 2061 CODE:
1942{ 2062{
1943 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_); 2063 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1944 uint8_t *data_end = (uint8_t *)SvEND (data_); 2064 uint8_t *data_end = (uint8_t *)SvEND (data_);
1945 mapcell *cell; 2065 mapcell *cell;
1966 2086
1967 //TODO: don't trust server data to be in-range(!) 2087 //TODO: don't trust server data to be in-range(!)
1968 2088
1969 if (flags & 8) 2089 if (flags & 8)
1970 { 2090 {
2091 uint8_t ext, cmd;
2092
1971 if (extmap) 2093 do
1972 { 2094 {
1973 uint8_t ext, cmd; 2095 ext = *data++;
2096 cmd = ext & 0x7f;
1974 2097
1975 do 2098 if (cmd < 4)
2099 cell->darkness = 255 - ext * 64 + 1; /* make sure this doesn't collide with FOW_DARKNESS */
2100 else if (cmd == 5) // health
1976 { 2101 {
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; 2102 cell->stat_width = 1;
1985 cell->stat_hp = *data++; 2103 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 } 2104 }
2005 while (ext & 0x80); 2105 else if (cmd == 6) // monster width
2106 cell->stat_width = *data++ + 1;
2107 else if (cmd == 0x47)
2108 {
2109 if (*data == 1) cell->player = data [1];
2110 else if (*data == 2) cell->player = data [2] + (data [1] << 8);
2111 else if (*data == 3) cell->player = data [3] + (data [2] << 8) + (data [1] << 16);
2112 else if (*data == 4) cell->player = data [4] + (data [3] << 8) + (data [2] << 16) + (data [1] << 24);
2113
2114 data += *data + 1;
2115 }
2116 else if (cmd == 8) // cell flags
2117 cell->flags = *data++;
2118 else if (ext & 0x40) // unknown, multibyte => skip
2119 data += *data + 1;
2120 else
2121 data++;
2006 } 2122 }
2007 else 2123 while (ext & 0x80);
2008 cell->darkness = *data++ + 1;
2009 } 2124 }
2010 2125
2011 for (z = 0; z <= 2; ++z) 2126 for (z = 0; z <= 2; ++z)
2012 if (flags & (4 >> z)) 2127 if (flags & (4 >> z))
2013 { 2128 {
2061 ? self->row + y 2176 ? self->row + y
2062 : 0; 2177 : 0;
2063 2178
2064 for (x = x0; x < x1; x++) 2179 for (x = x0; x < x1; x++)
2065 { 2180 {
2066 int r = 32, g = 32, b = 32, a = 192; 2181 unsigned int r = 32, g = 32, b = 32, a = 192;
2067 2182
2068 if (row && row->c0 <= x && x < row->c1) 2183 if (row && row->c0 <= x && x < row->c1)
2069 { 2184 {
2070 mapcell *cell = row->col + (x - row->c0); 2185 mapcell *cell = row->col + (x - row->c0);
2071 2186
2073 { 2188 {
2074 maptex tex = self->tex [cell->tile [z]]; 2189 maptex tex = self->tex [cell->tile [z]];
2075 int a0 = 255 - tex.a; 2190 int a0 = 255 - tex.a;
2076 int a1 = tex.a; 2191 int a1 = tex.a;
2077 2192
2078 r = (r * a0 + tex.r * a1) / 255; 2193 r = div255 (r * a0 + tex.r * a1);
2079 g = (g * a0 + tex.g * a1) / 255; 2194 g = div255 (g * a0 + tex.g * a1);
2080 b = (b * a0 + tex.b * a1) / 255; 2195 b = div255 (b * a0 + tex.b * a1);
2081 a = (a * a0 + tex.a * a1) / 255; 2196 a = div255 (a * a0 + tex.a * a1);
2082 } 2197 }
2083 } 2198 }
2084 2199
2085 *map++ = (r ) 2200 *map++ = (r )
2086 | (g << 8) 2201 | (g << 8)
2087 | (b << 16) 2202 | (b << 16)
2088 | (a << 24); 2203 | (a << 24);
2089 } 2204 }
2090 } 2205 }
2091 2206
2092 RETVAL = map_sv; 2207 RETVAL = map_sv;
2093} 2208}
2094 OUTPUT: 2209 OUTPUT:
2095 RETVAL 2210 RETVAL
2096 2211
2097void 2212void
2098draw (DC::Map self, int mx, int my, int sw, int sh, int T, U32 player = 0xffffffff, int sdx = 0, int sdy = 0) 2213draw (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: 2214 CODE:
2100{ 2215{
2101 int x, y, z; 2216 int x, y, z;
2102 2217
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) 2218 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; 2219 int pl_x, pl_y;
2108 maptex pl_tex; 2220 maptex pl_tex;
2109 rc_t *rc = rc_alloc (); 2221 rc_t rc;
2110 rc_t *rc_ov = rc_alloc (); 2222 rc_t rc_ov;
2111 rc_key_t key; 2223 rc_key_t key;
2112 rc_array_t *arr, *arr_hidden; 2224 rc_t::array_t *arr;
2113 2225
2114 pl_tex.name = 0; 2226 pl_tex.name = 0;
2115 2227
2116 // that's current max. sorry. 2228 // that's current max. sorry.
2117 if (sw > 255) sw = 255; 2229 if (sw > 255) sw = 255;
2118 if (sh > 255) sh = 255; 2230 if (sh > 255) sh = 255;
2119
2120 // clear key, in case of extra padding
2121 memset (&skey, 0, sizeof (skey));
2122 2231
2123 memset (&key, 0, sizeof (key)); 2232 memset (&key, 0, sizeof (key));
2124 key.r = 255; 2233 key.r = 255;
2125 key.g = 255; 2234 key.g = 255;
2126 key.b = 255; 2235 key.b = 255;
2132 my += self->y; 2241 my += self->y;
2133 2242
2134 // first pass: determine smooth_max 2243 // first pass: determine smooth_max
2135 // rather ugly, if you ask me 2244 // rather ugly, if you ask me
2136 // could also be stored inside mapcell and updated on change 2245 // could also be stored inside mapcell and updated on change
2137 memset (smooth_max, 0, sizeof (smooth_max)); 2246 memset (smooth_max, 0, sizeof (smooth_max[0]) * (sh + 1));
2138 2247
2139 for (y = 0; y < sh; y++) 2248 for (y = 0; y < sh; y++)
2140 if (0 <= y + my && y + my < self->rows) 2249 if (0 <= y + my && y + my < self->rows)
2141 { 2250 {
2142 maprow *row = self->row + (y + my); 2251 maprow *row = self->row + (y + my);
2155 2264
2156 glEnable (GL_BLEND); 2265 glEnable (GL_BLEND);
2157 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2266 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2158 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 2267 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2159 2268
2160 key.texname = self->tex [TEXID_HIDDEN].name;
2161 arr_hidden = rc_array (rc_ov, &key);
2162
2163 for (z = 0; z <= 2; z++) 2269 for (z = 0; z <= 2; z++)
2164 { 2270 {
2165 memset (smooth_level, 0, sizeof (smooth_level)); 2271 std::bitset<256> smooth_level; // one bit for every possible smooth level
2272 smooth_key skey;
2273 smooth_hash smooth;
2166 key.texname = -1; 2274 key.texname = -1;
2167 2275
2168 for (y = 0; y < sh; y++) 2276 for (y = 0; y < sh; y++)
2169 if (0 <= y + my && y + my < self->rows) 2277 if (0 <= y + my && y + my < self->rows)
2170 { 2278 {
2187 2295
2188 if (!tex.name) 2296 if (!tex.name)
2189 tex = self->tex [TEXID_NOFACE]; /* missing, replace by noface */ 2297 tex = self->tex [TEXID_NOFACE]; /* missing, replace by noface */
2190 2298
2191 key.texname = tex.name; 2299 key.texname = tex.name;
2192 arr = rc_array (rc, &key); 2300 arr = &rc.array (key);
2193 } 2301 }
2194 2302
2195 px = (x + 1) * T - tex.w; 2303 px = (x + 1) * Th - tex.w;
2196 py = (y + 1) * T - tex.h; 2304 py = (y + 1) * Tw - tex.h;
2197 2305
2198 if (expect_false (cell->player == player) && expect_false (z == 2)) 2306 if (ecb_expect_false (cell->player == player) && ecb_expect_false (z == 2))
2199 { 2307 {
2200 pl_x = px; 2308 pl_x = px;
2201 pl_y = py; 2309 pl_y = py;
2202 pl_tex = tex; 2310 pl_tex = tex;
2203 continue; 2311 continue;
2204 } 2312 }
2205 2313
2206 rc_t2f_v3f (arr, 0 , 0 , px , py , 0); 2314 arr->t2f_v3f (0 , 0 , px , py , 0);
2207 rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0); 2315 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); 2316 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); 2317 arr->t2f_v3f (tex.s, 0 , px + tex.w, py , 0);
2210 2318
2211 // update smooth hash 2319 // update smooth hash
2212 if (tex.smoothtile) 2320 if (tex.smoothtile)
2213 { 2321 {
2214 skey.tile = tex.smoothtile; 2322 skey.tile = tex.smoothtile;
2215 skey.level = tex.smoothlevel; 2323 skey.level = tex.smoothlevel;
2216 2324
2217 smooth_level [tex.smoothlevel >> 5] |= ((uint32_t)1) << (tex.smoothlevel & 31); 2325 smooth_level[tex.smoothlevel] = 1;
2218 2326
2219 // add bits to current tile and all neighbours. skey.x|y is 2327 // add bits to current tile and all neighbours. skey.x|y is
2220 // shifted +1|+1 so we always stay positive. 2328 // shifted +1|+1 so we always stay positive.
2221 2329
2222 // bits is ___n cccc CCCC bbbb 2330 // bits is ___n cccc CCCC bbbb
2230 2338
2231 // corners: 1 ┛· 2 ·┗ 4 ·· 8 ·· 2339 // corners: 1 ┛· 2 ·┗ 4 ·· 8 ··
2232 // ·· ·· ·┏ ┓· 2340 // ·· ·· ·┏ ┓·
2233 2341
2234 // full tile 2342 // full tile
2235 skey.x = x + 1; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x1000); 2343 skey.x = x + 1; skey.y = y + 1; smooth_or_bits (smooth, skey, 0x1000);
2236 2344
2237 // borders 2345 // borders
2238 skey.x = x + 2; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0091); 2346 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); 2347 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); 2348 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); 2349 skey.x = x + 1; skey.y = y ; smooth_or_bits (smooth, skey, 0x00c8);
2242 2350
2243 // corners 2351 // corners
2244 skey.x = x + 2; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0100); 2352 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); 2353 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); 2354 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); 2355 skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, skey, 0x0800);
2248 } 2356 }
2249 } 2357 }
2250 2358
2251 if (expect_false (z == 2)) 2359 if (ecb_expect_false (z == 2) && ecb_expect_false (cell->flags))
2252 { 2360 {
2253 /* draw question marks on top of hidden spaces */ 2361 // overlays such as the speech bubble, probably more to come
2254 if (!cell->darkness) 2362 if (cell->flags & 1)
2255 { 2363 {
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; 2364 rc_key_t key_ov = key;
2272 maptex tex = self->tex [TEXID_SPEECH]; 2365 maptex tex = self->tex[TEXID_SPEECH];
2273 rc_array_t *arr;
2274 int px = x * T + T * 2 / 32; 2366 int px = x * Tw + Tw * 2 / 32;
2275 int py = y * T - T * 6 / 32; 2367 int py = y * Th - Th * 6 / 32;
2276 2368
2277 key_ov.texname = tex.name; 2369 key_ov.texname = tex.name;
2278 arr = rc_array (rc_ov, &key_ov); 2370 rc_t::array_t &arr = rc_ov.array (key_ov);
2279 2371
2280 rc_t2f_v3f (arr, 0 , 0 , px , py , 0); 2372 arr.t2f_v3f (0 , 0 , px , py , 0);
2281 rc_t2f_v3f (arr, 0 , tex.t, px , py + T, 0); 2373 arr.t2f_v3f (0 , tex.t, px , py + Th, 0);
2282 rc_t2f_v3f (arr, tex.s, tex.t, px + T, py + T, 0); 2374 arr.t2f_v3f (tex.s, tex.t, px + Tw, py + Th, 0);
2283 rc_t2f_v3f (arr, tex.s, 0 , px + T, py , 0); 2375 arr.t2f_v3f (tex.s, 0 , px + Tw, py , 0);
2284 }
2285 } 2376 }
2286 } 2377 }
2287 } 2378 }
2288 } 2379 }
2289 2380
2290 rc_draw (rc); 2381 rc.draw ();
2291 rc_clear (rc); 2382 rc.clear ();
2292 2383
2293 // go through all smoothlevels, lowest to highest, then draw. 2384 // go through all smoothlevels, lowest to highest, then draw.
2294 // this is basically counting sort 2385 // this is basically counting sort
2295 { 2386 {
2296 int w, b; 2387 int w, b;
2297 2388
2298 glEnable (GL_TEXTURE_2D); 2389 glEnable (GL_TEXTURE_2D);
2299 glBegin (GL_QUADS); 2390 glBegin (GL_QUADS);
2300 for (w = 0; w < 256 / 32; ++w) 2391 for (int level = 0; level < smooth_level.size (); ++level)
2392 if (smooth_level[level])
2393 for (auto &&it = smooth.begin (); it != smooth.end (); ++it)
2301 { 2394 {
2302 uint32_t smask = smooth_level [w]; 2395 smooth_key &skey = it->first;
2303 if (smask) 2396 IV bits = it->second;
2304 for (b = 0; b < 32; ++b) 2397
2305 if (smask & (((uint32_t)1) << b)) 2398 if (!(bits & 0x1000)
2399 && skey.level == level
2400 && level > smooth_max [skey.x][skey.y])
2306 { 2401 {
2307 int level = (w << 5) | b; 2402 maptex tex = self->tex [skey.tile];
2403 int px = (((int)skey.x) - 1) * Tw;
2404 int py = (((int)skey.y) - 1) * Th;
2405 int border = bits & 15;
2406 int corner = (bits >> 8) & ~(bits >> 4) & 15;
2407 float dx = tex.s * .0625f; // 16 images/row
2408 float dy = tex.t * .5f ; // 2 images/column
2409
2308 HE *he; 2410 if (tex.name)
2309
2310 hv_iterinit (smooth);
2311 while ((he = hv_iternext (smooth)))
2312 { 2411 {
2313 smooth_key *skey = (smooth_key *)HeKEY (he); 2412 // this time avoiding texture state changes
2314 IV bits = SvIVX (HeVAL (he)); 2413 // save gobs of state changes.
2315 2414 if (key.texname != tex.name)
2316 if (!(bits & 0x1000)
2317 && skey->level == level
2318 && level > smooth_max [skey->x][skey->y])
2319 { 2415 {
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; 2416 self->tex [skey.tile].unused = 0;
2335 2417
2336 glEnd (); 2418 glEnd ();
2337 glBindTexture (GL_TEXTURE_2D, key.texname = tex.name); 2419 glBindTexture (GL_TEXTURE_2D, key.texname = tex.name);
2338 glBegin (GL_QUADS); 2420 glBegin (GL_QUADS);
2339 } 2421 }
2340 2422
2341 if (border) 2423 if (border)
2342 { 2424 {
2343 float ox = border * dx; 2425 float ox = border * dx;
2344 2426
2345 glTexCoord2f (ox , 0.f ); glVertex2i (px , py ); 2427 glTexCoord2f (ox , 0.f ); glVertex2i (px , py );
2346 glTexCoord2f (ox , dy ); glVertex2i (px , py + T); 2428 glTexCoord2f (ox , dy ); glVertex2i (px , py + Th);
2347 glTexCoord2f (ox + dx, dy ); glVertex2i (px + T, py + T); 2429 glTexCoord2f (ox + dx, dy ); glVertex2i (px + Tw, py + Th);
2348 glTexCoord2f (ox + dx, 0.f ); glVertex2i (px + T, py ); 2430 glTexCoord2f (ox + dx, 0.f ); glVertex2i (px + Tw, py );
2349 } 2431 }
2350 2432
2351 if (corner) 2433 if (corner)
2352 { 2434 {
2353 float ox = corner * dx; 2435 float ox = corner * dx;
2354 2436
2355 glTexCoord2f (ox , dy ); glVertex2i (px , py ); 2437 glTexCoord2f (ox , dy ); glVertex2i (px , py );
2356 glTexCoord2f (ox , dy * 2.f); glVertex2i (px , py + T); 2438 glTexCoord2f (ox , dy * 2.f); glVertex2i (px , py + Th);
2357 glTexCoord2f (ox + dx, dy * 2.f); glVertex2i (px + T, py + T); 2439 glTexCoord2f (ox + dx, dy * 2.f); glVertex2i (px + Tw, py + Th);
2358 glTexCoord2f (ox + dx, dy ); glVertex2i (px + T, py ); 2440 glTexCoord2f (ox + dx, dy ); glVertex2i (px + Tw, py );
2359 }
2360 }
2361 } 2441 }
2362 } 2442 }
2363 } 2443 }
2364 } 2444 }
2365 2445
2366 glEnd (); 2446 glEnd ();
2367 glDisable (GL_TEXTURE_2D); 2447 glDisable (GL_TEXTURE_2D);
2368 key.texname = -1; 2448 key.texname = -1;
2369 } 2449 }
2370
2371 hv_clear (smooth);
2372 } 2450 }
2373 2451
2374 if (pl_tex.name) 2452 if (pl_tex.name)
2375 { 2453 {
2376 maptex tex = pl_tex; 2454 maptex tex = pl_tex;
2377 int px = pl_x + sdx; 2455 int px = pl_x + sdx;
2378 int py = pl_y + sdy; 2456 int py = pl_y + sdy;
2379 2457
2380 key.texname = tex.name; 2458 key.texname = tex.name;
2381 arr = rc_array (rc, &key); 2459 rc_t::array_t &arr = rc.array (key);
2382 2460
2383 rc_t2f_v3f (arr, 0 , 0 , px , py , 0); 2461 arr.t2f_v3f (0 , 0 , px , py , 0);
2384 rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0); 2462 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); 2463 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); 2464 arr.t2f_v3f (tex.s, 0 , px + tex.w, py , 0);
2387 2465
2388 rc_draw (rc); 2466 rc.draw ();
2389 } 2467 }
2390 2468
2391 rc_draw (rc_ov); 2469 rc_ov.draw ();
2392 rc_clear (rc_ov); 2470 rc_ov.clear ();
2393 2471
2394 glDisable (GL_BLEND); 2472 glDisable (GL_BLEND);
2395 rc_free (rc);
2396 rc_free (rc_ov);
2397 2473
2398 // top layer: overlays such as the health bar 2474 // top layer: overlays such as the health bar
2399 for (y = 0; y < sh; y++) 2475 for (y = 0; y < sh; y++)
2400 if (0 <= y + my && y + my < self->rows) 2476 if (0 <= y + my && y + my < self->rows)
2401 { 2477 {
2404 for (x = 0; x < sw; x++) 2480 for (x = 0; x < sw; x++)
2405 if (row->c0 <= x + mx && x + mx < row->c1) 2481 if (row->c0 <= x + mx && x + mx < row->c1)
2406 { 2482 {
2407 mapcell *cell = row->col + (x + mx - row->c0); 2483 mapcell *cell = row->col + (x + mx - row->c0);
2408 2484
2409 int px = x * T; 2485 int px = x * Tw;
2410 int py = y * T; 2486 int py = y * Th;
2411 2487
2412 if (expect_false (cell->player == player)) 2488 if (ecb_expect_false (cell->player == player))
2413 { 2489 {
2414 px += sdx; 2490 px += sdx;
2415 py += sdy; 2491 py += sdy;
2416 } 2492 }
2417 2493
2418 if (cell->stat_hp) 2494 if (cell->stat_hp)
2419 { 2495 {
2420 int width = cell->stat_width * T; 2496 int width = cell->stat_width * Tw;
2421 int thick = (sh * T / 32 + 27) / 28 + 1 + cell->stat_width; 2497 int thick = (sh * Th / 32 + 27) / 28 + 1 + cell->stat_width;
2422 2498
2423 glColor3ub (0, 0, 0); 2499 glColor3ub (0, 0, 0);
2424 glRectf (px + 1, py - thick - 2, 2500 glRectf (px + 1, py - thick - 2,
2425 px + width - 1, py); 2501 px + width - 1, py);
2426 2502
2463 int x, y; 2539 int x, y;
2464 2540
2465 glEnable (GL_TEXTURE_2D); 2541 glEnable (GL_TEXTURE_2D);
2466 /* GL_REPLACE would be correct, as we don't need to modulate alpha, 2542 /* GL_REPLACE would be correct, as we don't need to modulate alpha,
2467 * but the nvidia driver (185.18.14) mishandles alpha textures 2543 * but the nvidia driver (185.18.14) mishandles alpha textures
2468 * ansd takes the colour from god knows where instead of using 2544 * and takes the colour from god knows where instead of using
2469 * Cp. MODULATE results in the same colour, but slightly different 2545 * Cp. MODULATE results in the same colour, but slightly different
2470 * alpha, but atcually gives us the correct colour with nvidia. 2546 * alpha, but atcually gives us the correct colour with nvidia.
2471 */ 2547 */
2472 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 2548 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2473 glEnable (GL_BLEND); 2549 glEnable (GL_BLEND);
2502void 2578void
2503fow_texture (DC::Map self, int mx, int my, int sw, int sh) 2579fow_texture (DC::Map self, int mx, int my, int sw, int sh)
2504 PPCODE: 2580 PPCODE:
2505{ 2581{
2506 int x, y; 2582 int x, y;
2507 int sw1 = sw + 2; 2583 int sw1 = sw + 2;
2508 int sh1 = sh + 2; 2584 int sh1 = sh + 2;
2509 int sh3 = sh * 3; 2585 int sh3 = sh * 3;
2510 int sw34 = (sw * 3 + 3) & ~3; 2586 int sw3 = sw * 3;
2587 SV *darkness3_sv = sv_2mortal (newSV (sw3 * sh3));
2588 uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv);
2511 uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1); 2589 uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1);
2512 SV *darkness3_sv = sv_2mortal (newSV (sw34 * sh3)); 2590 memset (darkness1, 0, sw1*sh1);
2513 uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv);
2514 2591
2515 SvPOK_only (darkness3_sv); 2592 SvPOK_only (darkness3_sv);
2516 SvCUR_set (darkness3_sv, sw34 * sh3); 2593 SvCUR_set (darkness3_sv, sw3 * sh3);
2517 2594
2518 mx += self->x - 1; 2595 mx += self->x - 1;
2519 my += self->y - 1; 2596 my += self->y - 1;
2520
2521 memset (darkness1, DARKNESS_ADJUST (255 - FOW_DARKNESS), sw1 * sh1);
2522 2597
2523 for (y = 0; y < sh1; y++) 2598 for (y = 0; y < sh1; y++)
2524 if (0 <= y + my && y + my < self->rows) 2599 if (0 <= y + my && y + my < self->rows)
2525 { 2600 {
2526 maprow *row = self->row + (y + my); 2601 maprow *row = self->row + (y + my);
2559 2634
2560 uint8_t r13 = (d13 + d23 + d12) / 3; 2635 uint8_t r13 = (d13 + d23 + d12) / 3;
2561 uint8_t r23 = d23; 2636 uint8_t r23 = d23;
2562 uint8_t r33 = (d23 + d33 + d32) / 3; 2637 uint8_t r33 = (d23 + d33 + d32) / 3;
2563 2638
2564 darkness3 [(y * 3 ) * sw34 + (x * 3 )] = MAX (d22, r11); 2639 darkness3 [(y * 3 ) * sw3 + (x * 3 )] = MAX (d22, r11);
2565 darkness3 [(y * 3 ) * sw34 + (x * 3 + 1)] = MAX (d22, r21); 2640 darkness3 [(y * 3 ) * sw3 + (x * 3 + 1)] = MAX (d22, r21);
2566 darkness3 [(y * 3 ) * sw34 + (x * 3 + 2)] = MAX (d22, r31); 2641 darkness3 [(y * 3 ) * sw3 + (x * 3 + 2)] = MAX (d22, r31);
2567 darkness3 [(y * 3 + 1) * sw34 + (x * 3 )] = MAX (d22, r12); 2642 darkness3 [(y * 3 + 1) * sw3 + (x * 3 )] = MAX (d22, r12);
2568 darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 1)] = MAX (d22, r22); 2643 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); 2644 darkness3 [(y * 3 + 1) * sw3 + (x * 3 + 2)] = MAX (d22, r32);
2570 darkness3 [(y * 3 + 2) * sw34 + (x * 3 )] = MAX (d22, r13); 2645 darkness3 [(y * 3 + 2) * sw3 + (x * 3 )] = MAX (d22, r13);
2571 darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 1)] = MAX (d22, r23); 2646 darkness3 [(y * 3 + 2) * sw3 + (x * 3 + 1)] = MAX (d22, r23);
2572 darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 2)] = MAX (d22, r33); 2647 darkness3 [(y * 3 + 2) * sw3 + (x * 3 + 2)] = MAX (d22, r33);
2573 } 2648 }
2574 2649
2575 free (darkness1); 2650 free (darkness1);
2576 2651
2577 EXTEND (SP, 3); 2652 EXTEND (SP, 3);
2578 PUSHs (sv_2mortal (newSViv (sw34))); 2653 PUSHs (sv_2mortal (newSViv (sw3)));
2579 PUSHs (sv_2mortal (newSViv (sh3))); 2654 PUSHs (sv_2mortal (newSViv (sh3)));
2580 PUSHs (darkness3_sv); 2655 PUSHs (darkness3_sv);
2581} 2656}
2582 2657
2583SV * 2658SV *
2646 else 2721 else
2647 *data++ = 0; 2722 *data++ = 0;
2648 } 2723 }
2649 } 2724 }
2650 2725
2651 /* if size is w*h + 5 then no data has been found */ 2726 /* if size is w*h + 5 then no data has been found */
2652 if (data - (uint8_t *)SvPVX (data_sv) != w * h + 5) 2727 if (data - (uint8_t *)SvPVX (data_sv) != w * h + 5)
2653 { 2728 {
2654 SvPOK_only (data_sv); 2729 SvPOK_only (data_sv);
2655 SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv)); 2730 SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
2656 } 2731 }
2657 2732
2658 RETVAL = data_sv; 2733 RETVAL = data_sv;
2659} 2734}
2660 OUTPUT: 2735 OUTPUT:
2661 RETVAL 2736 RETVAL
2662 2737
2663void 2738void
2670 STRLEN len; 2745 STRLEN len;
2671 uint8_t *data, *end; 2746 uint8_t *data, *end;
2672 2747
2673 len = SvLEN (data_sv); 2748 len = SvLEN (data_sv);
2674 SvGROW (data_sv, len + 8); // reserve at least 7+ bytes more 2749 SvGROW (data_sv, len + 8); // reserve at least 7+ bytes more
2675 data = SvPVbyte_nolen (data_sv); 2750 data = (uint8_t *)SvPVbyte_nolen (data_sv);
2676 end = data + len + 8; 2751 end = data + len + 8;
2677 2752
2678 if (len < 5) 2753 if (len < 5)
2679 XSRETURN_EMPTY; 2754 XSRETURN_EMPTY;
2680 2755
2741} 2816}
2742 2817
2743MODULE = Deliantra::Client PACKAGE = DC::RW 2818MODULE = Deliantra::Client PACKAGE = DC::RW
2744 2819
2745DC::RW 2820DC::RW
2746new (SV *class, SV *data_sv) 2821new (SV *klass, SV *data_sv)
2747 CODE: 2822 CODE:
2748{ 2823{
2749 STRLEN datalen; 2824 STRLEN datalen;
2750 char *data = SvPVbyte (data_sv, datalen); 2825 char *data = SvPVbyte (data_sv, datalen);
2751 2826
2753} 2828}
2754 OUTPUT: 2829 OUTPUT:
2755 RETVAL 2830 RETVAL
2756 2831
2757DC::RW 2832DC::RW
2758new_from_file (SV *class, const char *path, const char *mode = "rb") 2833new_from_file (SV *klass, const char *path, const char *mode = "rb")
2759 CODE: 2834 CODE:
2760 RETVAL = SDL_RWFromFile (path, mode); 2835 RETVAL = SDL_RWFromFile (path, mode);
2761 OUTPUT: 2836 OUTPUT:
2762 RETVAL 2837 RETVAL
2763 2838
2781 if (RETVAL < 0) 2856 if (RETVAL < 0)
2782 { 2857 {
2783 RETVAL = Mix_GroupOldest (-1); 2858 RETVAL = Mix_GroupOldest (-1);
2784 2859
2785 if (RETVAL < 0) 2860 if (RETVAL < 0)
2861 {
2862 // happens sometimes, maybe it just stopped playing(?)
2863 RETVAL = Mix_GroupAvailable (-1);
2864
2865 if (RETVAL < 0)
2786 XSRETURN_UNDEF; 2866 XSRETURN_UNDEF;
2787 2867 }
2868 else
2788 Mix_HaltChannel (RETVAL); 2869 Mix_HaltChannel (RETVAL);
2789 } 2870 }
2790 2871
2791 Mix_UnregisterAllEffects (RETVAL); 2872 Mix_UnregisterAllEffects (RETVAL);
2792 Mix_Volume (RETVAL, 128); 2873 Mix_Volume (RETVAL, 128);
2793} 2874}
2853 2934
2854MODULE = Deliantra::Client PACKAGE = DC::MixChunk 2935MODULE = Deliantra::Client PACKAGE = DC::MixChunk
2855 2936
2856PROTOTYPES: DISABLE 2937PROTOTYPES: DISABLE
2857 2938
2939void
2940decoders ()
2941 PPCODE:
2942#if SDL_MIXER_MAJOR_VERSION > 1 || SDL_MIXER_MINOR_VERSION > 2 || SDL_MIXER_PATCHLEVEL >= 10
2943 int i, num = Mix_GetNumChunkDecoders ();
2944 EXTEND (SP, num);
2945 for (i = 0; i < num; ++i)
2946 PUSHs (sv_2mortal (newSVpv (Mix_GetChunkDecoder (i), 0)));
2947#else
2948 XPUSHs (sv_2mortal (newSVpv ("(sdl mixer too old)", 0)));
2949#endif
2950
2858DC::MixChunk 2951DC::MixChunk
2859new (SV *class, DC::RW rwops) 2952new (SV *klass, DC::RW rwops)
2860 CODE: 2953 CODE:
2861 RETVAL = Mix_LoadWAV_RW (rwops, 1); 2954 RETVAL = Mix_LoadWAV_RW (rwops, 1);
2862 OUTPUT: 2955 OUTPUT:
2863 RETVAL 2956 RETVAL
2864 2957
2894 OUTPUT: 2987 OUTPUT:
2895 RETVAL 2988 RETVAL
2896 2989
2897MODULE = Deliantra::Client PACKAGE = DC::MixMusic 2990MODULE = Deliantra::Client PACKAGE = DC::MixMusic
2898 2991
2992void
2993decoders ()
2994 PPCODE:
2995#if SDL_MIXER_MAJOR_VERSION > 1 || SDL_MIXER_MINOR_VERSION > 2 || SDL_MIXER_PATCHLEVEL >= 10
2996 int i, num = Mix_GetNumMusicDecoders ();
2997 EXTEND (SP, num);
2998 for (i = 0; i < num; ++i)
2999 PUSHs (sv_2mortal (newSVpv (Mix_GetMusicDecoder (i), 0)));
3000#else
3001 XPUSHs (sv_2mortal (newSVpv ("(sdl mixer too old)", 0)));
3002#endif
3003
2899int 3004int
2900volume (int volume = -1) 3005volume (int volume = -1)
2901 PROTOTYPE: ;$ 3006 PROTOTYPE: ;$
2902 CODE: 3007 CODE:
2903 if (items > 0) 3008 if (items > 0)
2914void 3019void
2915halt () 3020halt ()
2916 CODE: 3021 CODE:
2917 Mix_HaltMusic (); 3022 Mix_HaltMusic ();
2918 3023
3024int
3025playing ()
3026 CODE:
3027 RETVAL = Mix_PlayingMusic ();
3028 OUTPUT:
3029 RETVAL
3030
2919DC::MixMusic 3031DC::MixMusic
2920new (SV *class, DC::RW rwops) 3032new (SV *klass, DC::RW rwops)
2921 CODE: 3033 CODE:
2922 RETVAL = Mix_LoadMUS_RW (rwops); 3034 RETVAL = Mix_LoadMUS_RW (rwops);
2923 OUTPUT: 3035 OUTPUT:
2924 RETVAL 3036 RETVAL
2925 3037
3062 const_iv (GL_FUNC_SUBTRACT), 3174 const_iv (GL_FUNC_SUBTRACT),
3063 const_iv (GL_FUNC_REVERSE_SUBTRACT), 3175 const_iv (GL_FUNC_REVERSE_SUBTRACT),
3064# undef const_iv 3176# undef const_iv
3065 }; 3177 };
3066 3178
3067 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) 3179 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--)
3068 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 3180 newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv));
3069 3181
3070 texture_av = newAV (); 3182 texture_av = newAV ();
3071 AvREAL_off (texture_av); 3183 AvREAL_off (texture_av);
3072} 3184}
3073 3185
3078 gl.BlendFuncSeparateEXT = 0; 3190 gl.BlendFuncSeparateEXT = 0;
3079 3191
3080void 3192void
3081apple_nvidia_bug (int enable) 3193apple_nvidia_bug (int enable)
3082 3194
3083char * 3195const char *
3084gl_vendor () 3196gl_vendor ()
3085 CODE: 3197 CODE:
3086 RETVAL = (char *)glGetString (GL_VENDOR); 3198 RETVAL = (const char *)glGetString (GL_VENDOR);
3087 OUTPUT: 3199 OUTPUT:
3088 RETVAL 3200 RETVAL
3089 3201
3090char * 3202const char *
3091gl_version () 3203gl_version ()
3092 CODE: 3204 CODE:
3093 RETVAL = (char *)glGetString (GL_VERSION); 3205 RETVAL = (const char *)glGetString (GL_VERSION);
3094 OUTPUT: 3206 OUTPUT:
3095 RETVAL 3207 RETVAL
3096 3208
3097char * 3209const char *
3098gl_extensions () 3210gl_extensions ()
3099 CODE: 3211 CODE:
3100 RETVAL = (char *)glGetString (GL_EXTENSIONS); 3212 RETVAL = (const char *)glGetString (GL_EXTENSIONS);
3101 OUTPUT: 3213 OUTPUT:
3102 RETVAL 3214 RETVAL
3103 3215
3104const char *glGetString (GLenum pname) 3216const char *glGetString (GLenum pname)
3217 CODE:
3218 RETVAL = (const char *)glGetString (pname);
3219 OUTPUT:
3220 RETVAL
3105 3221
3106GLint glGetInteger (GLenum pname) 3222GLint glGetInteger (GLenum pname)
3107 CODE: 3223 CODE:
3108 glGetIntegerv (pname, &RETVAL); 3224 glGetIntegerv (pname, &RETVAL);
3109 OUTPUT: 3225 OUTPUT:
3116 RETVAL 3232 RETVAL
3117 3233
3118int glGetError () 3234int glGetError ()
3119 3235
3120void glFinish () 3236void glFinish ()
3237
3238void glFlush ()
3121 3239
3122void glClear (int mask) 3240void glClear (int mask)
3123 3241
3124void glClearColor (float r, float g, float b, float a = 1.0) 3242void glClearColor (float r, float g, float b, float a = 1.0)
3125 PROTOTYPE: @ 3243 PROTOTYPE: @
3297 3415
3298void glEndList () 3416void glEndList ()
3299 3417
3300void glCallList (int list) 3418void glCallList (int list)
3301 3419
3420void c_init ()
3421 CODE:
3422 glPixelStorei (GL_PACK_ALIGNMENT , 1);
3423 glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
3424
3302MODULE = Deliantra::Client PACKAGE = DC::UI::Base 3425MODULE = Deliantra::Client PACKAGE = DC::UI::Base
3303 3426
3304PROTOTYPES: DISABLE 3427PROTOTYPES: DISABLE
3305 3428
3306void 3429void
3307find_widget (SV *self, NV x, NV y) 3430find_widget (SV *self, NV x, NV y)
3308 PPCODE: 3431 PPCODE:
3309{ 3432{
3310 if (within_widget (self, x, y)) 3433 if (within_widget (self, x, y))
3311 XPUSHs (self); 3434 XPUSHs (self);
3312} 3435}
3313 3436
3314BOOT: 3437BOOT:
3315{ 3438{
3323 3446
3324void 3447void
3325draw (SV *self) 3448draw (SV *self)
3326 CODE: 3449 CODE:
3327{ 3450{
3328 HV *hv; 3451 HV *hv;
3329 SV **svp; 3452 SV **svp;
3330 NV x, y, w, h; 3453 NV x, y, w, h;
3331 SV *draw_x_sv = GvSV (draw_x_gv); 3454 SV *draw_x_sv = GvSV (draw_x_gv);
3332 SV *draw_y_sv = GvSV (draw_y_gv); 3455 SV *draw_y_sv = GvSV (draw_y_gv);
3333 SV *draw_w_sv = GvSV (draw_w_gv); 3456 SV *draw_w_sv = GvSV (draw_w_gv);
3334 SV *draw_h_sv = GvSV (draw_h_gv); 3457 SV *draw_h_sv = GvSV (draw_h_gv);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines