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.276 by root, Sat Aug 30 08:04:01 2008 UTC vs.
Revision 1.323 by root, Sun Nov 18 01:48:39 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 roundf(x) (int)(x)
25# define atan2f(x,y) atan2(x,y) 26# define atan2f(x,y) atan2(x,y)
26# define M_PI 3.14159265f 27# define M_PI 3.14159265f
27#endif 28#endif
28 29
29#include <assert.h> 30#include <cassert>
30#include <math.h> 31#include <cmath>
31#include <string.h> 32#include <cstring>
32#include <stdio.h> 33#include <cstdio>
33#include <stdlib.h> 34#include <cstdlib>
35
36#include <utility>
34 37
35#define USE_RWOPS 1 // for SDL_mixer:LoadMUS_RW 38#define USE_RWOPS 1 // for SDL_mixer:LoadMUS_RW
36 39
37#include <SDL.h> 40#include <SDL.h>
38#include <SDL_thread.h> 41#include <SDL_thread.h>
42#include <SDL_opengl.h> 45#include <SDL_opengl.h>
43 46
44/* work around os x broken headers */ 47/* work around os x broken headers */
45#ifdef __MACOSX__ 48#ifdef __MACOSX__
46typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); 49typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
50typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
51typedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t);
47#endif 52#endif
48 53
49#define PANGO_ENABLE_BACKEND 54#define PANGO_ENABLE_BACKEND
50#define G_DISABLE_CAST_CHECKS 55#define G_DISABLE_CAST_CHECKS
51 56
52#include <glib/gmacros.h> 57#include <glib.h>
53 58
54#include <pango/pango.h> 59#include <pango/pango.h>
55 60
56#ifndef PANGO_VERSION_CHECK 61#ifndef PANGO_VERSION_CHECK
57# define PANGO_VERSION_CHECK(a,b,c) 0 62# define PANGO_VERSION_CHECK(a,b,c) 0
81#define expect_false(expr) expect ((expr) != 0, 0) 86#define expect_false(expr) expect ((expr) != 0, 0)
82#define expect_true(expr) expect ((expr) != 0, 1) 87#define expect_true(expr) expect ((expr) != 0, 1)
83 88
84#define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, object replacement character */ 89#define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, object replacement character */
85 90
91/* this is used as fow flag as well, so has to have a different value */
92/* then anything that is computed by incoming darkness */
86#define FOW_DARKNESS 32 93#define FOW_DARKNESS 50
94#define DARKNESS_ADJUST(n) (n)
87 95
88#define MAP_EXTEND_X 32 96#define MAP_EXTEND_X 32
89#define MAP_EXTEND_Y 512 97#define MAP_EXTEND_Y 512
90 98
91#define MIN_FONT_HEIGHT 10 99#define MIN_FONT_HEIGHT 10
92 100
93/* mask out modifiers we are not interested in */ 101/* mask out modifiers we are not interested in */
94#define MOD_MASK (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_META) 102#define MOD_MASK (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_META)
95 103
96#define KMOD_LRAM 0x10000 // our extension 104#define KMOD_LRAM 0x10000 // our extension
105
106#define TEXID_SPEECH 1
107#define TEXID_NOFACE 2
108
109static char *
110fast_sv_grow (SV *sv, STRLEN need)
111{
112 STRLEN len = SvLEN (sv);
113 STRLEN want = SvCUR (sv) + need;
114
115 if (expect_false (len < want))
116 {
117 do
118 len *= 2;
119 while (len < want);
120
121 sv_grow (sv, len);
122 }
123
124 SvCUR_set (sv, want);
125 return SvEND (sv) - need;
126}
97 127
98static AV *texture_av; 128static AV *texture_av;
99 129
100static struct 130static struct
101{ 131{
158{ 188{
159 GSList *attrs = run->item->analysis.extra_attrs; 189 GSList *attrs = run->item->analysis.extra_attrs;
160 190
161 while (attrs) 191 while (attrs)
162 { 192 {
163 PangoAttribute *attr = attrs->data; 193 PangoAttribute *attr = (PangoAttribute *)attrs->data;
164 194
165 if (attr->klass->type == PANGO_ATTR_SHAPE) 195 if (attr->klass->type == PANGO_ATTR_SHAPE)
166 return 1; 196 return 1;
167 197
168 attrs = attrs->next; 198 attrs = attrs->next;
169 } 199 }
170 200
171 return 0; 201 return 0;
172} 202}
173 203
174typedef struct cf_layout { 204struct cf_layout {
175 PangoLayout *pl; 205 PangoLayout *pl;
176 float r, g, b, a; // default color for rgba mode 206 float r, g, b, a; // default color for rgba mode
177 int base_height; 207 int base_height;
178 DC__Font font; 208 DC__Font font;
179 rc_t *rc; 209 rc_t *rc;
180} *DC__Layout; 210};
211
212typedef cf_layout *DC__Layout;
181 213
182static DC__Font default_font; 214static DC__Font default_font;
183static PangoContext *opengl_context; 215static PangoContext *opengl_context;
184static PangoFontMap *opengl_fontmap; 216static PangoFontMap *opengl_fontmap;
185 217
186static void 218static void
187substitute_func (FcPattern *pattern, gpointer data) 219substitute_func (FcPattern *pattern, gpointer data)
188{ 220{
189 FcPatternAddBool (pattern, FC_HINTING, 1); 221 FcPatternAddBool (pattern, FC_HINTING, 1);
190#ifdef FC_HINT_STYLE 222#ifdef FC_HINT_STYLE
191 FcPatternAddBool (pattern, FC_HINT_STYLE, FC_HINT_FULL); 223 FcPatternAddInteger (pattern, FC_HINT_STYLE, FC_HINT_FULL);
192#endif 224#endif
193 FcPatternAddBool (pattern, FC_AUTOHINT, 0); 225 FcPatternAddBool (pattern, FC_AUTOHINT, 0);
194} 226}
195 227
196static void 228static void
226} 258}
227 259
228typedef uint16_t tileid; 260typedef uint16_t tileid;
229typedef uint16_t faceid; 261typedef uint16_t faceid;
230 262
231typedef struct { 263struct maptex
264{
232 GLuint name; 265 GLuint name;
233 int w, h; 266 int w, h;
234 float s, t; 267 float s, t;
235 uint8_t r, g, b, a; 268 uint8_t r, g, b, a;
236 tileid smoothtile; 269 tileid smoothtile;
237 uint8_t smoothlevel; 270 uint8_t smoothlevel;
238} maptex; 271 uint8_t unused; /* set to zero on use */
272};
239 273
240typedef struct { 274struct mapcell
275{
241 uint32_t player; 276 uint32_t player;
242 tileid tile[3]; 277 tileid tile[3];
243 uint16_t darkness; 278 uint16_t darkness;
244 uint8_t stat_width, stat_hp, flags, smoothmax; 279 uint8_t stat_width, stat_hp, flags, smoothmax;
245} mapcell; 280};
246 281
247typedef struct { 282struct maprow
283{
248 int32_t c0, c1; 284 int32_t c0, c1;
249 mapcell *col; 285 mapcell *col;
250} maprow; 286};
251 287
252typedef struct map { 288struct mapgrid {
253 int x, y, w, h; 289 int x, y, w, h;
254 int ox, oy; /* offset to virtual global coordinate system */ 290 int ox, oy; /* offset to virtual global coordinate system */
255 int faces; tileid *face2tile; // [faceid] 291 int faces; tileid *face2tile; // [faceid]
256 int texs; maptex *tex; // [tileid] 292 int texs; maptex *tex; // [tileid]
257 293
258 int32_t rows; 294 int32_t rows;
259 maprow *row; 295 maprow *row;
260} *DC__Map; 296};
297
298typedef mapgrid *DC__Map;
261 299
262static char * 300static char *
263prepend (char *ptr, int sze, int inc) 301prepend (char *ptr, int sze, int inc)
264{ 302{
265 char *p; 303 char *p;
283 321
284#define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type)) 322#define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
285#define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type)) 323#define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
286 324
287static void 325static void
288need_facenum (struct map *self, faceid face) 326need_facenum (struct mapgrid *self, faceid face)
289{ 327{
290 while (self->faces <= face) 328 while (self->faces <= face)
291 { 329 {
292 Append (tileid, self->face2tile, self->faces, self->faces); 330 Append (tileid, self->face2tile, self->faces, self->faces);
293 self->faces *= 2; 331 self->faces *= 2;
294 } 332 }
295} 333}
296 334
297static void 335static void
298need_texid (struct map *self, int texid) 336need_texid (struct mapgrid *self, int texid)
299{ 337{
300 while (self->texs <= texid) 338 while (self->texs <= texid)
301 { 339 {
302 Append (maptex, self->tex, self->texs, self->texs); 340 Append (maptex, self->tex, self->texs, self->texs);
303 self->texs *= 2; 341 self->texs *= 2;
304 } 342 }
305} 343}
306 344
307static maprow * 345static maprow *
308map_get_row (DC__Map self, int y) 346map_get_row (mapgrid *self, int y)
309{ 347{
310 if (0 > y) 348 if (0 > y)
311 { 349 {
312 int extend = - y + MAP_EXTEND_Y; 350 int extend = - y + MAP_EXTEND_Y;
313 Prepend (maprow, self->row, self->rows, extend); 351 Prepend (maprow, self->row, self->rows, extend);
351 389
352 return row->col + (x - row->c0); 390 return row->col + (x - row->c0);
353} 391}
354 392
355static mapcell * 393static mapcell *
356map_get_cell (DC__Map self, int x, int y) 394map_get_cell (mapgrid *self, int x, int y)
357{ 395{
358 return row_get_cell (map_get_row (self, y), x); 396 return row_get_cell (map_get_row (self, y), x);
359} 397}
360 398
361static void 399static void
362map_clear (DC__Map self) 400map_clear (mapgrid *self)
363{ 401{
364 int r; 402 int r;
365 403
366 for (r = 0; r < self->rows; r++) 404 for (r = 0; r < self->rows; r++)
367 Safefree (self->row[r].col); 405 Safefree (self->row[r].col);
385 (cell)->flags = 0; \ 423 (cell)->flags = 0; \
386 (cell)->player = 0; \ 424 (cell)->player = 0; \
387 } while (0) 425 } while (0)
388 426
389static void 427static void
390map_blank (DC__Map self, int x0, int y0, int w, int h) 428map_blank (mapgrid *self, int x0, int y0, int w, int h)
391{ 429{
392 int x, y; 430 int x, y;
393 maprow *row; 431 maprow *row;
394 mapcell *cell; 432 mapcell *cell;
395 433
412 CELL_CLEAR (cell); 450 CELL_CLEAR (cell);
413 } 451 }
414 } 452 }
415} 453}
416 454
417typedef struct { 455struct smooth_key
456{
418 tileid tile; 457 tileid tile;
419 uint8_t x, y, level; 458 uint8_t x, y, level;
420} smooth_key; 459
460 bool operator == (const smooth_key &o) const
461 {
462 return tile == o.tile && x == o.x && y == o.y && level == o.level;
463 }
464};
465
466typedef ska::flat_hash_map<smooth_key, IV> smooth_hash;
467
468namespace std {
469 template <>
470 struct hash<smooth_key>
471 {
472 size_t operator () (const smooth_key &v) const
473 {
474 return v.tile + (v.x << 8) + (v.y << 16) + (v.level << 24);
475 }
476 };
477}
421 478
422static void 479static void
423smooth_or_bits (HV *hv, smooth_key *key, IV bits) 480smooth_or_bits (smooth_hash &h, smooth_key &key, IV bits)
424{ 481{
425 SV **sv = hv_fetch (hv, (char *)key, sizeof (*key), 1); 482 auto &&it = h.find (key);
426 483
427 if (SvIOK (*sv)) 484 if (it == h.end ())
428 SvIV_set (*sv, SvIVX (*sv) | bits); 485 h.insert (std::make_pair (key, bits));
429 else 486 else
430 sv_setiv (*sv, bits); 487 it->second |= bits;
431} 488}
432 489
433static void 490static void
434music_finished (void) 491music_finished (void)
435{ 492{
452 ev.code = 1; 509 ev.code = 1;
453 ev.data1 = (void *)(long)channel; 510 ev.data1 = (void *)(long)channel;
454 ev.data2 = 0; 511 ev.data2 = 0;
455 512
456 SDL_PushEvent ((SDL_Event *)&ev); 513 SDL_PushEvent ((SDL_Event *)&ev);
514}
515
516// approximately divide by 255
517static unsigned int
518div255 (unsigned int n)
519{
520 return (n + (n >> 8)) >> 8;
457} 521}
458 522
459static unsigned int 523static unsigned int
460minpot (unsigned int n) 524minpot (unsigned int n)
461{ 525{
529 return 0; 593 return 0;
530 594
531 return 1; 595 return 1;
532} 596}
533 597
598/******************************************************************************/
599
534/* process keyboard modifiers */ 600/* process keyboard modifiers */
535static int 601static int
536mod_munge (int mod) 602mod_munge (int mod)
537{ 603{
538 mod &= MOD_MASK; 604 mod &= MOD_MASK;
542 608
543 return mod; 609 return mod;
544} 610}
545 611
546static void 612static void
547deliantra_main () 613deliantra_main (SV *real_main)
548{ 614{
549 char *argv[] = { 0 }; 615 dSP;
550 call_argv ("::main", G_DISCARD | G_VOID, argv); 616
617 PUSHMARK (SP);
618 call_sv (real_main, G_DISCARD | G_VOID);
551} 619}
552 620
553#ifdef __MACOSX__ 621#ifdef __MACOSX__
622 static SV *real_main;
623
554 /* to due surprising braindamage on the side of SDL design, we 624 /* to due surprising braindamage on the side of SDL design, we
555 * do some mind-boggling hack here: SDL requires a custom main() 625 * do some mind-boggling hack here: SDL requires a custom main()
556 * on OS X, so... we provide one and call the original main(), which, 626 * on OS X, so... we provide one and call the original main(), which,
557 * due to share dlibrary magic, calls -lSDLmain's main, not perl's main, 627 * due to shared library magic, calls -lSDLmain's main, not perl's main,
558 * and which calls our main (== SDL_main) back. 628 * and which calls our main (== SDL_main) back.
559 */ 629 */
560 extern C_LINKAGE int 630 extern C_LINKAGE int
561 main (int argc, char *argv[]) 631 main (int argc, char *argv[])
562 { 632 {
563 deliantra_main (); 633 deliantra_main (real_main);
564 } 634 }
565 635
566 #undef main 636 #undef main
567 637
568 extern C_LINKAGE int main (int argc, char *argv[]); 638 extern C_LINKAGE int main (int argc, char *argv[]);
569 639
570 static void 640 static void
571 SDL_braino (void) 641 SDL_main_hack (SV *real_main_)
572 { 642 {
643 real_main = real_main_;
644
573 char *argv[] = { "deliantra client", 0 }; 645 char *argv[] = { "deliantra client", 0 };
574 (main) (1, argv); 646 (main) (1, argv);
575 } 647 }
576#else 648#else
577 static void 649 static void
578 SDL_braino (void) 650 SDL_main_hack (SV *real_main)
579 { 651 {
580 deliantra_main (); 652 deliantra_main (real_main);
581 } 653 }
582#endif 654#endif
583 655
584MODULE = Deliantra::Client PACKAGE = DC 656MODULE = Deliantra::Client PACKAGE = DC
585 657
786 858
787 const_iv (FOW_DARKNESS) 859 const_iv (FOW_DARKNESS)
788# undef const_iv 860# undef const_iv
789 }; 861 };
790 862
791 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) 863 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--)
792 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 864 newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv));
793 865
794 assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK); 866 assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK);
795 assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE); 867 assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE);
796} 868}
797 869
813NV ceil (NV x) 885NV ceil (NV x)
814 886
815IV minpot (UV n) 887IV minpot (UV n)
816 888
817IV popcount (UV n) 889IV popcount (UV n)
890
891NV distance (NV dx, NV dy)
892 CODE:
893 RETVAL = pow (dx * dx + dy * dy, 0.5);
894 OUTPUT:
895 RETVAL
818 896
819void 897void
820pango_init () 898pango_init ()
821 CODE: 899 CODE:
822{ 900{
830#endif 908#endif
831} 909}
832 910
833char *SDL_GetError () 911char *SDL_GetError ()
834 912
835void SDL_braino () 913void SDL_main_hack (SV *real_main)
914 PROTOTYPE: &
836 915
837int SDL_Init (U32 flags) 916int SDL_Init (U32 flags)
838 917
839int SDL_InitSubSystem (U32 flags) 918int SDL_InitSubSystem (U32 flags)
840 919
841void SDL_QuitSubSystem (U32 flags) 920void SDL_QuitSubSystem (U32 flags)
842 921
843void SDL_Quit () 922void SDL_Quit ()
844 923
845int SDL_GL_SetAttribute (int attr, int value) 924int SDL_GL_SetAttribute (int attr, int value)
925 C_ARGS: (SDL_GLattr)attr, value
846 926
847int SDL_GL_GetAttribute (int attr) 927int SDL_GL_GetAttribute (int attr)
848 CODE: 928 CODE:
849 if (SDL_GL_GetAttribute (attr, &RETVAL)) 929 if (SDL_GL_GetAttribute ((SDL_GLattr)attr, &RETVAL))
850 XSRETURN_UNDEF; 930 XSRETURN_UNDEF;
851 OUTPUT: 931 OUTPUT:
852 RETVAL 932 RETVAL
853 933
854void 934void
909 ); 989 );
910 990
911 if (RETVAL) 991 if (RETVAL)
912 { 992 {
913 av_clear (texture_av); 993 av_clear (texture_av);
914
915 SDL_WM_SetCaption ("Deliantra MORPG Client " VERSION, "Deliantra");
916#define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name); 994#define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name);
917#include "glfunc.h" 995#include "glfunc.h"
918#undef GL_FUNC 996#undef GL_FUNC
997 if (!gl.ActiveTexture ) gl.ActiveTexture = gl.ActiveTextureARB;
998 if (!gl.MultiTexCoord2f) gl.MultiTexCoord2f = gl.MultiTexCoord2fARB;
919 } 999 }
920} 1000}
921 OUTPUT: 1001 OUTPUT:
922 RETVAL 1002 RETVAL
1003
1004void
1005SDL_WM_SetCaption (const char *title, const char *icon)
923 1006
924void 1007void
925SDL_GL_SwapBuffers () 1008SDL_GL_SwapBuffers ()
926 1009
927char * 1010char *
928SDL_GetKeyName (int sym) 1011SDL_GetKeyName (int sym)
1012 C_ARGS: (SDLKey)sym
929 1013
930int 1014int
931SDL_GetAppState () 1015SDL_GetAppState ()
932 1016
933int 1017int
934SDL_GetModState () 1018SDL_GetModState ()
935 1019
1020int
1021SDL_WaitEvent ()
1022 C_ARGS: 0
1023
936void 1024void
1025SDL_PumpEvents ()
1026
1027void
937poll_events () 1028peep_events ()
938 PPCODE: 1029 PPCODE:
939{ 1030{
940 SDL_Event ev; 1031 SDL_Event ev;
941 1032
942 SDL_PumpEvents (); 1033 SDL_PumpEvents ();
1008 1099
1009 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("DC::UI::Event", 1)))); 1100 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("DC::UI::Event", 1))));
1010 } 1101 }
1011} 1102}
1012 1103
1104char *
1105SDL_AudioDriverName ()
1106 CODE:
1107{
1108 char buf [256];
1109 if (!SDL_AudioDriverName (buf, sizeof (buf)))
1110 XSRETURN_UNDEF;
1111
1112 RETVAL = buf;
1113}
1114 OUTPUT:
1115 RETVAL
1116
1013int 1117int
1014Mix_OpenAudio (int frequency = 44100, int format = MIX_DEFAULT_FORMAT, int channels = 2, int chunksize = 4096) 1118Mix_OpenAudio (int frequency = 44100, int format = MIX_DEFAULT_FORMAT, int channels = 2, int chunksize = 4096)
1015 POSTCALL: 1119 POSTCALL:
1016 Mix_HookMusicFinished (music_finished); 1120 Mix_HookMusicFinished (music_finished);
1017 Mix_ChannelFinished (channel_finished); 1121 Mix_ChannelFinished (channel_finished);
1018 1122
1019void 1123void
1020Mix_QuerySpec () 1124Mix_QuerySpec ()
1079add_font (char *file) 1183add_font (char *file)
1080 CODE: 1184 CODE:
1081 RETVAL = FcConfigAppFontAddFile (0, (const FcChar8 *)file); 1185 RETVAL = FcConfigAppFontAddFile (0, (const FcChar8 *)file);
1082 OUTPUT: 1186 OUTPUT:
1083 RETVAL 1187 RETVAL
1188
1189void
1190IMG_Init (int flags = IMG_INIT_JPG | IMG_INIT_PNG)
1191
1192# MIX_INIT_MP3 gives smpeg + libstdc++ + libgcc_s
1193void
1194Mix_Init (int flags = MIX_INIT_MOD | MIX_INIT_OGG)
1084 1195
1085void 1196void
1086load_image_inline (SV *image_) 1197load_image_inline (SV *image_)
1087 ALIAS: 1198 ALIAS:
1088 load_image_file = 1 1199 load_image_file = 1
1134 1245
1135 SDL_LockSurface (surface2); 1246 SDL_LockSurface (surface2);
1136 EXTEND (SP, 6); 1247 EXTEND (SP, 6);
1137 PUSHs (sv_2mortal (newSViv (surface2->w))); 1248 PUSHs (sv_2mortal (newSViv (surface2->w)));
1138 PUSHs (sv_2mortal (newSViv (surface2->h))); 1249 PUSHs (sv_2mortal (newSViv (surface2->h)));
1139 PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch))); 1250 PUSHs (sv_2mortal (newSVpvn ((const char *)surface2->pixels, surface2->h * surface2->pitch)));
1140 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB))); 1251 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
1141 PUSHs (sv_2mortal (newSViv (GL_RGBA))); 1252 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
1142 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE))); 1253 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
1143 SDL_UnlockSurface (surface2); 1254 SDL_UnlockSurface (surface2);
1144 1255
1204#if DEBUG 1315#if DEBUG
1205 VALGRIND_DO_LEAK_CHECK; 1316 VALGRIND_DO_LEAK_CHECK;
1206#endif 1317#endif
1207} 1318}
1208 1319
1320int
1321SvREFCNT (SV *sv)
1322 CODE:
1323 RETVAL = SvREFCNT (sv);
1324 OUTPUT:
1325 RETVAL
1326
1209MODULE = Deliantra::Client PACKAGE = DC::Font 1327MODULE = Deliantra::Client PACKAGE = DC::Font
1210 1328
1211PROTOTYPES: DISABLE 1329PROTOTYPES: DISABLE
1212 1330
1213DC::Font 1331DC::Font
1214new_from_file (SV *class, char *path, int id = 0) 1332new_from_file (SV *klass, char *path, int id = 0)
1215 CODE: 1333 CODE:
1216{ 1334{
1217 int count; 1335 int count;
1218 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count); 1336 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count);
1219 RETVAL = pango_fc_font_description_from_pattern (pattern, 0); 1337 RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
1248 PROTOTYPE: 1366 PROTOTYPE:
1249 CODE: 1367 CODE:
1250 tc_restore (); 1368 tc_restore ();
1251 1369
1252DC::Layout 1370DC::Layout
1253new (SV *class) 1371new (SV *klass)
1254 CODE: 1372 CODE:
1255 New (0, RETVAL, 1, struct cf_layout); 1373 New (0, RETVAL, 1, struct cf_layout);
1256 1374
1257 RETVAL->pl = pango_layout_new (opengl_context); 1375 RETVAL->pl = pango_layout_new (opengl_context);
1258 RETVAL->r = 1.; 1376 RETVAL->r = 1.;
1407 1525
1408void 1526void
1409set_height (DC::Layout self, int base_height) 1527set_height (DC::Layout self, int base_height)
1410 CODE: 1528 CODE:
1411 if (self->base_height != base_height) 1529 if (self->base_height != base_height)
1412 { 1530 {
1413 self->base_height = base_height; 1531 self->base_height = base_height;
1414 layout_update_font (self); 1532 layout_update_font (self);
1415 } 1533 }
1416 1534
1417void 1535void
1644 glDisable (GL_ALPHA_TEST); 1762 glDisable (GL_ALPHA_TEST);
1645 glDisable (GL_BLEND); 1763 glDisable (GL_BLEND);
1646 } 1764 }
1647} 1765}
1648 1766
1767void
1768draw_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)
1769 PROTOTYPE: @
1770 CODE:
1771{
1772 glEnable (GL_BLEND);
1773 glBlendFunc (intensity ? GL_SRC_ALPHA : GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1774 glEnable (GL_TEXTURE_2D);
1775 glBindTexture (GL_TEXTURE_2D, name1);
1776
1777 glColor3f (intensity, intensity, intensity);
1778 glPushMatrix ();
1779 glScalef (1./3, 1./3, 1.);
1780
1781 if (blend > 0.f)
1782 {
1783 float dx3 = dx * -3.f / w;
1784 float dy3 = dy * -3.f / h;
1785 GLfloat env_color[4] = { 0., 0., 0., blend };
1786
1787 /* interpolate the two shadow textures */
1788 /* stage 0 == rgb(glcolor) + alpha(t0) */
1789 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1790
1791 /* stage 1 == rgb(glcolor) + alpha(interpolate t0, t1, texenv) */
1792 gl.ActiveTexture (GL_TEXTURE1);
1793 glEnable (GL_TEXTURE_2D);
1794 glBindTexture (GL_TEXTURE_2D, name2);
1795 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
1796
1797 /* rgb == rgb(glcolor) */
1798 glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
1799 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
1800 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
1801
1802 /* alpha = interpolate t0, t1 by env_alpha */
1803 glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, env_color);
1804
1805 glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_INTERPOLATE);
1806 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
1807 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
1808
1809 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS);
1810 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
1811
1812 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_CONSTANT);
1813 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA);
1814
1815 glBegin (GL_QUADS);
1816 gl.MultiTexCoord2f (GL_TEXTURE0, 0, 0); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 , dy3 ); glVertex2i (0, 0);
1817 gl.MultiTexCoord2f (GL_TEXTURE0, 0, t); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 , dy3 + t); glVertex2i (0, h);
1818 gl.MultiTexCoord2f (GL_TEXTURE0, s, t); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 + s, dy3 + t); glVertex2i (w, h);
1819 gl.MultiTexCoord2f (GL_TEXTURE0, s, 0); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 + s, dy3 ); glVertex2i (w, 0);
1820 glEnd ();
1821
1822 glDisable (GL_TEXTURE_2D);
1823 gl.ActiveTexture (GL_TEXTURE0);
1824 }
1825 else
1826 {
1827 /* simple blending of one texture, also opengl <1.3 path */
1828 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1829
1830 glBegin (GL_QUADS);
1831 glTexCoord2f (0, 0); glVertex2f (0, 0);
1832 glTexCoord2f (0, t); glVertex2f (0, h);
1833 glTexCoord2f (s, t); glVertex2f (w, h);
1834 glTexCoord2f (s, 0); glVertex2f (w, 0);
1835 glEnd ();
1836 }
1837
1838 /* draw ?-marks or equivalent, this is very clumsy code :/ */
1839 {
1840 int x, y;
1841 int dx3 = dx * 3;
1842 int dy3 = dy * 3;
1843
1844 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1845 glBindTexture (GL_TEXTURE_2D, hidden_tex);
1846 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1847 glTranslatef (-1., -1., 0);
1848 glBegin (GL_QUADS);
1849
1850 for (y = 1; y < h; y += 3)
1851 {
1852 int y1 = y - dy3;
1853 int y1valid = y1 >= 0 && y1 < h;
1854
1855 for (x = 1; x < w; x += 3)
1856 {
1857 int x1 = x - dx3;
1858 uint8_t h1 = data1 [x + y * w] == DARKNESS_ADJUST (255 - FOW_DARKNESS);
1859 uint8_t h2;
1860
1861 if (y1valid && x1 >= 0 && x1 < w)
1862 h2 = data2 [x1 + y1 * w] == DARKNESS_ADJUST (255 - FOW_DARKNESS);
1863 else
1864 h2 = 1; /* out of range == invisible */
1865
1866 if (h1 || h2)
1867 {
1868 float alpha = h1 == h2 ? 1.f : h1 ? 1.f - blend : blend;
1869 glColor4f (1., 1., 1., alpha);
1870
1871 glTexCoord2f (0, 0.); glVertex2i (x , y );
1872 glTexCoord2f (0, 1.); glVertex2i (x , y + 3);
1873 glTexCoord2f (1, 1.); glVertex2i (x + 3, y + 3);
1874 glTexCoord2f (1, 0.); glVertex2i (x + 3, y );
1875 }
1876 }
1877 }
1878 }
1879
1880 glEnd ();
1881
1882 glPopMatrix ();
1883
1884 glDisable (GL_TEXTURE_2D);
1885 glDisable (GL_BLEND);
1886}
1887
1649IV texture_valid_2d (GLint internalformat, GLsizei w, GLsizei h, GLenum format, GLenum type) 1888IV texture_valid_2d (GLint internalformat, GLsizei w, GLsizei h, GLenum format, GLenum type)
1650 CODE: 1889 CODE:
1651{ 1890{
1652 GLint width; 1891 GLint width;
1653 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, internalformat, w, h, 0, format, type, 0); 1892 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, internalformat, w, h, 0, format, type, 0);
1660MODULE = Deliantra::Client PACKAGE = DC::Map 1899MODULE = Deliantra::Client PACKAGE = DC::Map
1661 1900
1662PROTOTYPES: DISABLE 1901PROTOTYPES: DISABLE
1663 1902
1664DC::Map 1903DC::Map
1665new (SV *class) 1904new (SV *klass)
1666 CODE: 1905 CODE:
1667 New (0, RETVAL, 1, struct map); 1906 New (0, RETVAL, 1, mapgrid);
1668 RETVAL->x = 0; 1907 RETVAL->x = 0;
1669 RETVAL->y = 0; 1908 RETVAL->y = 0;
1670 RETVAL->w = 0; 1909 RETVAL->w = 0;
1671 RETVAL->h = 0; 1910 RETVAL->h = 0;
1672 RETVAL->ox = 0; 1911 RETVAL->ox = 0;
1709 1948
1710void 1949void
1711set_smooth (DC::Map self, int face, int smooth, int level) 1950set_smooth (DC::Map self, int face, int smooth, int level)
1712 CODE: 1951 CODE:
1713{ 1952{
1714 tileid texid; 1953 tileid texid;
1715 maptex *tex; 1954 maptex *tex;
1716 1955
1717 if (face < 0 || face >= self->faces) 1956 if (face < 0 || face >= self->faces)
1718 return; 1957 return;
1719 1958
1720 if (smooth < 0 || smooth >= self->faces) 1959 if (smooth < 0 || smooth >= self->faces)
1721 return; 1960 return;
1722 1961
1723 texid = self->face2tile [face]; 1962 texid = self->face2tile [face];
1724 1963
1725 if (!texid) 1964 if (!texid)
1726 return; 1965 return;
1727 1966
1728 tex = self->tex + texid; 1967 tex = self->tex + texid;
1757 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 1996 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1758 // use uglier nearest interpolation because linear suffers 1997 // use uglier nearest interpolation because linear suffers
1759 // from transparent color bleeding and ugly wrapping effects. 1998 // from transparent color bleeding and ugly wrapping effects.
1760 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1999 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1761} 2000}
2001
2002void
2003expire_textures (DC::Map self, int texid, int count)
2004 PPCODE:
2005 for (; texid < self->texs && count; ++texid, --count)
2006 {
2007 maptex *tex = self->tex + texid;
2008
2009 if (tex->name)
2010 {
2011 if (tex->unused)
2012 {
2013 tex->name = 0;
2014 tex->unused = 0;
2015 XPUSHs (sv_2mortal (newSViv (texid)));
2016 }
2017 else
2018 tex->unused = 1;
2019 }
2020 }
1762 2021
1763int 2022int
1764ox (DC::Map self) 2023ox (DC::Map self)
1765 ALIAS: 2024 ALIAS:
1766 oy = 1 2025 oy = 1
1806 self->y += MAP_EXTEND_Y; 2065 self->y += MAP_EXTEND_Y;
1807 } 2066 }
1808} 2067}
1809 2068
1810SV * 2069SV *
1811map1a_update (DC::Map self, SV *data_, int extmap) 2070map1a_update (DC::Map self, SV *data_)
1812 CODE: 2071 CODE:
1813{ 2072{
1814 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_); 2073 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1815 uint8_t *data_end = (uint8_t *)SvEND (data_); 2074 uint8_t *data_end = (uint8_t *)SvEND (data_);
1816 mapcell *cell; 2075 mapcell *cell;
1837 2096
1838 //TODO: don't trust server data to be in-range(!) 2097 //TODO: don't trust server data to be in-range(!)
1839 2098
1840 if (flags & 8) 2099 if (flags & 8)
1841 { 2100 {
2101 uint8_t ext, cmd;
2102
1842 if (extmap) 2103 do
1843 { 2104 {
1844 uint8_t ext, cmd; 2105 ext = *data++;
2106 cmd = ext & 0x7f;
1845 2107
1846 do 2108 if (cmd < 4)
2109 cell->darkness = 255 - ext * 64 + 1; /* make sure this doesn't collide with FOW_DARKNESS */
2110 else if (cmd == 5) // health
1847 { 2111 {
1848 ext = *data++;
1849 cmd = ext & 0x7f;
1850
1851 if (cmd < 4)
1852 cell->darkness = 255 - ext * 64 + 1;
1853 else if (cmd == 5) // health
1854 {
1855 cell->stat_width = 1; 2112 cell->stat_width = 1;
1856 cell->stat_hp = *data++; 2113 cell->stat_hp = *data++;
1857 }
1858 else if (cmd == 6) // monster width
1859 cell->stat_width = *data++ + 1;
1860 else if (cmd == 0x47)
1861 {
1862 if (*data == 1) cell->player = data [1];
1863 else if (*data == 2) cell->player = data [2] + (data [1] << 8);
1864 else if (*data == 3) cell->player = data [3] + (data [2] << 8) + (data [1] << 16);
1865 else if (*data == 4) cell->player = data [4] + (data [3] << 8) + (data [2] << 16) + (data [1] << 24);
1866
1867 data += *data + 1;
1868 }
1869 else if (cmd == 8) // cell flags
1870 cell->flags = *data++;
1871 else if (ext & 0x40) // unknown, multibyte => skip
1872 data += *data + 1;
1873 else
1874 data++;
1875 } 2114 }
1876 while (ext & 0x80); 2115 else if (cmd == 6) // monster width
2116 cell->stat_width = *data++ + 1;
2117 else if (cmd == 0x47)
2118 {
2119 if (*data == 1) cell->player = data [1];
2120 else if (*data == 2) cell->player = data [2] + (data [1] << 8);
2121 else if (*data == 3) cell->player = data [3] + (data [2] << 8) + (data [1] << 16);
2122 else if (*data == 4) cell->player = data [4] + (data [3] << 8) + (data [2] << 16) + (data [1] << 24);
2123
2124 data += *data + 1;
2125 }
2126 else if (cmd == 8) // cell flags
2127 cell->flags = *data++;
2128 else if (ext & 0x40) // unknown, multibyte => skip
2129 data += *data + 1;
2130 else
2131 data++;
1877 } 2132 }
1878 else 2133 while (ext & 0x80);
1879 cell->darkness = *data++ + 1;
1880 } 2134 }
1881 2135
1882 for (z = 0; z <= 2; ++z) 2136 for (z = 0; z <= 2; ++z)
1883 if (flags & (4 >> z)) 2137 if (flags & (4 >> z))
1884 { 2138 {
1887 cell->tile [z] = self->face2tile [face]; 2141 cell->tile [z] = self->face2tile [face];
1888 2142
1889 if (cell->tile [z]) 2143 if (cell->tile [z])
1890 { 2144 {
1891 maptex *tex = self->tex + cell->tile [z]; 2145 maptex *tex = self->tex + cell->tile [z];
2146 tex->unused = 0;
1892 if (!tex->name) 2147 if (!tex->name)
1893 av_push (missing, newSViv (cell->tile [z])); 2148 av_push (missing, newSViv (cell->tile [z]));
1894 2149
1895 if (tex->smoothtile) 2150 if (tex->smoothtile)
1896 { 2151 {
1897 maptex *smooth = self->tex + tex->smoothtile; 2152 maptex *smooth = self->tex + tex->smoothtile;
2153 smooth->unused = 0;
1898 if (!smooth->name) 2154 if (!smooth->name)
1899 av_push (missing, newSViv (tex->smoothtile)); 2155 av_push (missing, newSViv (tex->smoothtile));
1900 } 2156 }
1901 } 2157 }
1902 } 2158 }
1930 ? self->row + y 2186 ? self->row + y
1931 : 0; 2187 : 0;
1932 2188
1933 for (x = x0; x < x1; x++) 2189 for (x = x0; x < x1; x++)
1934 { 2190 {
1935 int r = 32, g = 32, b = 32, a = 192; 2191 unsigned int r = 32, g = 32, b = 32, a = 192;
1936 2192
1937 if (row && row->c0 <= x && x < row->c1) 2193 if (row && row->c0 <= x && x < row->c1)
1938 { 2194 {
1939 mapcell *cell = row->col + (x - row->c0); 2195 mapcell *cell = row->col + (x - row->c0);
1940 2196
1942 { 2198 {
1943 maptex tex = self->tex [cell->tile [z]]; 2199 maptex tex = self->tex [cell->tile [z]];
1944 int a0 = 255 - tex.a; 2200 int a0 = 255 - tex.a;
1945 int a1 = tex.a; 2201 int a1 = tex.a;
1946 2202
1947 r = (r * a0 + tex.r * a1) / 255; 2203 r = div255 (r * a0 + tex.r * a1);
1948 g = (g * a0 + tex.g * a1) / 255; 2204 g = div255 (g * a0 + tex.g * a1);
1949 b = (b * a0 + tex.b * a1) / 255; 2205 b = div255 (b * a0 + tex.b * a1);
1950 a = (a * a0 + tex.a * a1) / 255; 2206 a = div255 (a * a0 + tex.a * a1);
1951 } 2207 }
1952 } 2208 }
1953 2209
1954 *map++ = (r ) 2210 *map++ = (r )
1955 | (g << 8) 2211 | (g << 8)
1956 | (b << 16) 2212 | (b << 16)
1957 | (a << 24); 2213 | (a << 24);
1958 } 2214 }
1959 } 2215 }
1960 2216
1961 RETVAL = map_sv; 2217 RETVAL = map_sv;
1962} 2218}
1963 OUTPUT: 2219 OUTPUT:
1964 RETVAL 2220 RETVAL
1965 2221
1966void 2222void
1967draw (DC::Map self, int mx, int my, int sw, int sh, int T, U32 player = 0xffffffff, int sdx = 0, int sdy = 0) 2223draw (DC::Map self, int mx, int my, int sw, int sh, int Tw, int Th, U32 player = 0xffffffff, int sdx = 0, int sdy = 0)
1968 CODE: 2224 CODE:
1969{ 2225{
1970 int x, y, z; 2226 int x, y, z;
1971 2227
1972 HV *smooth = (HV *)sv_2mortal ((SV *)newHV ());
1973 uint32_t smooth_level[256 / 32]; // one bit for every possible smooth level 2228 uint32_t smooth_level[256 / 32]; // one bit for every possible smooth level
1974 static uint8_t smooth_max[256][256]; // egad, fast and wasteful on memory (64k) 2229 static uint8_t smooth_max[256][256]; // egad, fast and wasteful on memory (64k)
1975 smooth_key skey; 2230 smooth_key skey;
1976 int pl_x, pl_y; 2231 int pl_x, pl_y;
1977 maptex pl_tex; 2232 maptex pl_tex;
1978 rc_t *rc = rc_alloc (); 2233 rc_t *rc = rc_alloc ();
2234 rc_t *rc_ov = rc_alloc ();
1979 rc_key_t key; 2235 rc_key_t key;
1980 rc_array_t *arr; 2236 rc_array_t *arr;
1981 2237
1982 pl_tex.name = 0; 2238 pl_tex.name = 0;
1983 2239
1984 // thats current max. sorry. 2240 // that's current max. sorry.
1985 if (sw > 255) sw = 255; 2241 if (sw > 255) sw = 255;
1986 if (sh > 255) sh = 255; 2242 if (sh > 255) sh = 255;
1987 2243
1988 // clear key, in case of extra padding 2244 // clear key, in case of extra padding
1989 memset (&skey, 0, sizeof (skey)); 2245 memset (&skey, 0, sizeof (skey));
1993 key.g = 255; 2249 key.g = 255;
1994 key.b = 255; 2250 key.b = 255;
1995 key.a = 255; 2251 key.a = 255;
1996 key.mode = GL_QUADS; 2252 key.mode = GL_QUADS;
1997 key.format = GL_T2F_V3F; 2253 key.format = GL_T2F_V3F;
1998 key.texname = -1;
1999 2254
2000 mx += self->x; 2255 mx += self->x;
2001 my += self->y; 2256 my += self->y;
2002 2257
2003 // first pass: determine smooth_max 2258 // first pass: determine smooth_max
2026 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2281 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2027 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 2282 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2028 2283
2029 for (z = 0; z <= 2; z++) 2284 for (z = 0; z <= 2; z++)
2030 { 2285 {
2286 smooth_hash smooth;
2031 memset (smooth_level, 0, sizeof (smooth_level)); 2287 memset (smooth_level, 0, sizeof (smooth_level));
2288 key.texname = -1;
2032 2289
2033 for (y = 0; y < sh; y++) 2290 for (y = 0; y < sh; y++)
2034 if (0 <= y + my && y + my < self->rows) 2291 if (0 <= y + my && y + my < self->rows)
2035 { 2292 {
2036 maprow *row = self->row + (y + my); 2293 maprow *row = self->row + (y + my);
2042 tileid tile = cell->tile [z]; 2299 tileid tile = cell->tile [z];
2043 2300
2044 if (tile) 2301 if (tile)
2045 { 2302 {
2046 maptex tex = self->tex [tile]; 2303 maptex tex = self->tex [tile];
2047 int px = (x + 1) * T - tex.w; 2304 int px, py;
2048 int py = (y + 1) * T - tex.h;
2049 2305
2050 if (key.texname != tex.name) 2306 if (key.texname != tex.name)
2051 { 2307 {
2308 self->tex [tile].unused = 0;
2309
2052 if (!tex.name) 2310 if (!tex.name)
2053 tex = self->tex [2]; /* missing, replace by noface */ 2311 tex = self->tex [TEXID_NOFACE]; /* missing, replace by noface */
2054 2312
2055 key.texname = tex.name; 2313 key.texname = tex.name;
2056 arr = rc_array (rc, &key); 2314 arr = rc_array (rc, &key);
2057 } 2315 }
2316
2317 px = (x + 1) * Th - tex.w;
2318 py = (y + 1) * Tw - tex.h;
2058 2319
2059 if (expect_false (cell->player == player) && expect_false (z == 2)) 2320 if (expect_false (cell->player == player) && expect_false (z == 2))
2060 { 2321 {
2061 pl_x = px; 2322 pl_x = px;
2062 pl_y = py; 2323 pl_y = py;
2067 rc_t2f_v3f (arr, 0 , 0 , px , py , 0); 2328 rc_t2f_v3f (arr, 0 , 0 , px , py , 0);
2068 rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0); 2329 rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0);
2069 rc_t2f_v3f (arr, tex.s, tex.t, px + tex.w, py + tex.h, 0); 2330 rc_t2f_v3f (arr, tex.s, tex.t, px + tex.w, py + tex.h, 0);
2070 rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0); 2331 rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0);
2071 2332
2072 if (expect_false (cell->flags) && expect_false (z == 2))
2073 {
2074 // overlays such as the speech bubble, probably more to come
2075 if (cell->flags & 1)
2076 {
2077 maptex tex = self->tex [1];
2078 int px = x * T + T * 2 / 32;
2079 int py = y * T - T * 6 / 32;
2080
2081 if (tex.name)
2082 {
2083 if (key.texname != tex.name)
2084 {
2085 key.texname = tex.name;
2086 arr = rc_array (rc, &key);
2087 }
2088
2089 rc_t2f_v3f (arr, 0 , 0 , px , py , 0);
2090 rc_t2f_v3f (arr, 0 , tex.t, px , py + T, 0);
2091 rc_t2f_v3f (arr, tex.s, tex.t, px + T, py + T, 0);
2092 rc_t2f_v3f (arr, tex.s, 0 , px + T, py , 0);
2093 }
2094 }
2095 }
2096
2097 // update smooth hash 2333 // update smooth hash
2098 if (tex.smoothtile) 2334 if (tex.smoothtile)
2099 { 2335 {
2100 skey.tile = tex.smoothtile; 2336 skey.tile = tex.smoothtile;
2101 skey.level = tex.smoothlevel; 2337 skey.level = tex.smoothlevel;
2116 2352
2117 // corners: 1 ┛· 2 ·┗ 4 ·· 8 ·· 2353 // corners: 1 ┛· 2 ·┗ 4 ·· 8 ··
2118 // ·· ·· ·┏ ┓· 2354 // ·· ·· ·┏ ┓·
2119 2355
2120 // full tile 2356 // full tile
2121 skey.x = x + 1; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x1000); 2357 skey.x = x + 1; skey.y = y + 1; smooth_or_bits (smooth, skey, 0x1000);
2122 2358
2123 // borders 2359 // borders
2124 skey.x = x + 2; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0091); 2360 skey.x = x + 2; skey.y = y + 1; smooth_or_bits (smooth, skey, 0x0091);
2125 skey.x = x + 1; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0032); 2361 skey.x = x + 1; skey.y = y + 2; smooth_or_bits (smooth, skey, 0x0032);
2126 skey.x = x ; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0064); 2362 skey.x = x ; skey.y = y + 1; smooth_or_bits (smooth, skey, 0x0064);
2127 skey.x = x + 1; skey.y = y ; smooth_or_bits (smooth, &skey, 0x00c8); 2363 skey.x = x + 1; skey.y = y ; smooth_or_bits (smooth, skey, 0x00c8);
2128 2364
2129 // corners 2365 // corners
2130 skey.x = x + 2; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0100); 2366 skey.x = x + 2; skey.y = y + 2; smooth_or_bits (smooth, skey, 0x0100);
2131 skey.x = x ; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0200); 2367 skey.x = x ; skey.y = y + 2; smooth_or_bits (smooth, skey, 0x0200);
2132 skey.x = x ; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0400); 2368 skey.x = x ; skey.y = y ; smooth_or_bits (smooth, skey, 0x0400);
2133 skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0800); 2369 skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, skey, 0x0800);
2370 }
2371 }
2372
2373 if (expect_false (z == 2) && expect_false (cell->flags))
2374 {
2375 // overlays such as the speech bubble, probably more to come
2376 if (cell->flags & 1)
2377 {
2378 rc_key_t key_ov = key;
2379 maptex tex = self->tex [TEXID_SPEECH];
2380 rc_array_t *arr;
2381 int px = x * Tw + Tw * 2 / 32;
2382 int py = y * Th - Th * 6 / 32;
2383
2384 key_ov.texname = tex.name;
2385 arr = rc_array (rc_ov, &key_ov);
2386
2387 rc_t2f_v3f (arr, 0 , 0 , px , py , 0);
2388 rc_t2f_v3f (arr, 0 , tex.t, px , py + Th, 0);
2389 rc_t2f_v3f (arr, tex.s, tex.t, px + Tw, py + Th, 0);
2390 rc_t2f_v3f (arr, tex.s, 0 , px + Tw, py , 0);
2134 } 2391 }
2135 } 2392 }
2136 } 2393 }
2137 } 2394 }
2138 2395
2154 if (smask & (((uint32_t)1) << b)) 2411 if (smask & (((uint32_t)1) << b))
2155 { 2412 {
2156 int level = (w << 5) | b; 2413 int level = (w << 5) | b;
2157 HE *he; 2414 HE *he;
2158 2415
2159 hv_iterinit (smooth); 2416 for (auto &&it = smooth.begin (); it != smooth.end (); ++it)
2160 while ((he = hv_iternext (smooth)))
2161 { 2417 {
2162 smooth_key *skey = (smooth_key *)HeKEY (he); 2418 smooth_key &skey = it->first;
2163 IV bits = SvIVX (HeVAL (he)); 2419 IV bits = it->second;
2164 2420
2165 if (!(bits & 0x1000) 2421 if (!(bits & 0x1000)
2166 && skey->level == level 2422 && skey.level == level
2167 && level > smooth_max [skey->x][skey->y]) 2423 && level > smooth_max [skey.x][skey.y])
2168 { 2424 {
2169 maptex tex = self->tex [skey->tile]; 2425 maptex tex = self->tex [skey.tile];
2170 int px = (((int)skey->x) - 1) * T; 2426 int px = (((int)skey.x) - 1) * Tw;
2171 int py = (((int)skey->y) - 1) * T; 2427 int py = (((int)skey.y) - 1) * Th;
2172 int border = bits & 15; 2428 int border = bits & 15;
2173 int corner = (bits >> 8) & ~(bits >> 4) & 15; 2429 int corner = (bits >> 8) & ~(bits >> 4) & 15;
2174 float dx = tex.s * .0625f; // 16 images/row 2430 float dx = tex.s * .0625f; // 16 images/row
2175 float dy = tex.t * .5f ; // 2 images/column 2431 float dy = tex.t * .5f ; // 2 images/column
2176 2432
2178 { 2434 {
2179 // this time avoiding texture state changes 2435 // this time avoiding texture state changes
2180 // save gobs of state changes. 2436 // save gobs of state changes.
2181 if (key.texname != tex.name) 2437 if (key.texname != tex.name)
2182 { 2438 {
2439 self->tex [skey.tile].unused = 0;
2440
2183 glEnd (); 2441 glEnd ();
2184 glBindTexture (GL_TEXTURE_2D, key.texname = tex.name); 2442 glBindTexture (GL_TEXTURE_2D, key.texname = tex.name);
2185 glBegin (GL_QUADS); 2443 glBegin (GL_QUADS);
2186 } 2444 }
2187 2445
2188 if (border) 2446 if (border)
2189 { 2447 {
2190 float ox = border * dx; 2448 float ox = border * dx;
2191 2449
2192 glTexCoord2f (ox , 0.f ); glVertex2i (px , py ); 2450 glTexCoord2f (ox , 0.f ); glVertex2i (px , py );
2193 glTexCoord2f (ox , dy ); glVertex2i (px , py + T); 2451 glTexCoord2f (ox , dy ); glVertex2i (px , py + Th);
2194 glTexCoord2f (ox + dx, dy ); glVertex2i (px + T, py + T); 2452 glTexCoord2f (ox + dx, dy ); glVertex2i (px + Tw, py + Th);
2195 glTexCoord2f (ox + dx, 0.f ); glVertex2i (px + T, py ); 2453 glTexCoord2f (ox + dx, 0.f ); glVertex2i (px + Tw, py );
2196 } 2454 }
2197 2455
2198 if (corner) 2456 if (corner)
2199 { 2457 {
2200 float ox = corner * dx; 2458 float ox = corner * dx;
2201 2459
2202 glTexCoord2f (ox , dy ); glVertex2i (px , py ); 2460 glTexCoord2f (ox , dy ); glVertex2i (px , py );
2203 glTexCoord2f (ox , dy * 2.f); glVertex2i (px , py + T); 2461 glTexCoord2f (ox , dy * 2.f); glVertex2i (px , py + Th);
2204 glTexCoord2f (ox + dx, dy * 2.f); glVertex2i (px + T, py + T); 2462 glTexCoord2f (ox + dx, dy * 2.f); glVertex2i (px + Tw, py + Th);
2205 glTexCoord2f (ox + dx, dy ); glVertex2i (px + T, py ); 2463 glTexCoord2f (ox + dx, dy ); glVertex2i (px + Tw, py );
2206 } 2464 }
2207 } 2465 }
2208 } 2466 }
2209 } 2467 }
2210 } 2468 }
2212 2470
2213 glEnd (); 2471 glEnd ();
2214 glDisable (GL_TEXTURE_2D); 2472 glDisable (GL_TEXTURE_2D);
2215 key.texname = -1; 2473 key.texname = -1;
2216 } 2474 }
2217
2218 hv_clear (smooth);
2219 } 2475 }
2220 2476
2221 if (pl_tex.name) 2477 if (pl_tex.name)
2222 { 2478 {
2223 maptex tex = pl_tex; 2479 maptex tex = pl_tex;
2233 rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0); 2489 rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0);
2234 2490
2235 rc_draw (rc); 2491 rc_draw (rc);
2236 } 2492 }
2237 2493
2494 rc_draw (rc_ov);
2495 rc_clear (rc_ov);
2496
2238 glDisable (GL_BLEND); 2497 glDisable (GL_BLEND);
2239 rc_free (rc); 2498 rc_free (rc);
2499 rc_free (rc_ov);
2240 2500
2241 // top layer: overlays such as the health bar 2501 // top layer: overlays such as the health bar
2242 for (y = 0; y < sh; y++) 2502 for (y = 0; y < sh; y++)
2243 if (0 <= y + my && y + my < self->rows) 2503 if (0 <= y + my && y + my < self->rows)
2244 { 2504 {
2247 for (x = 0; x < sw; x++) 2507 for (x = 0; x < sw; x++)
2248 if (row->c0 <= x + mx && x + mx < row->c1) 2508 if (row->c0 <= x + mx && x + mx < row->c1)
2249 { 2509 {
2250 mapcell *cell = row->col + (x + mx - row->c0); 2510 mapcell *cell = row->col + (x + mx - row->c0);
2251 2511
2252 int px = x * T; 2512 int px = x * Tw;
2253 int py = y * T; 2513 int py = y * Th;
2514
2515 if (expect_false (cell->player == player))
2516 {
2517 px += sdx;
2518 py += sdy;
2519 }
2254 2520
2255 if (cell->stat_hp) 2521 if (cell->stat_hp)
2256 { 2522 {
2257 int width = cell->stat_width * T; 2523 int width = cell->stat_width * Tw;
2258 int thick = (sh * T / 32 + 27) / 28 + 1 + cell->stat_width; 2524 int thick = (sh * Th / 32 + 27) / 28 + 1 + cell->stat_width;
2259 2525
2260 glColor3ub (0, 0, 0); 2526 glColor3ub (0, 0, 0);
2261 glRectf (px + 1, py - thick - 2, 2527 glRectf (px + 1, py - thick - 2,
2262 px + width - 1, py); 2528 px + width - 1, py);
2263 2529
2269 } 2535 }
2270 } 2536 }
2271} 2537}
2272 2538
2273void 2539void
2274draw_magicmap (DC::Map self, int dx, int dy, int w, int h, unsigned char *data) 2540draw_magicmap (DC::Map self, int w, int h, unsigned char *data)
2275 CODE: 2541 CODE:
2276{ 2542{
2277 static float color[16][3] = { 2543 static float color[16][3] = {
2278 { 0.00F, 0.00F, 0.00F }, 2544 { 0.00f, 0.00f, 0.00f },
2279 { 1.00F, 1.00F, 1.00F }, 2545 { 1.00f, 1.00f, 1.00f },
2280 { 0.00F, 0.00F, 0.55F }, 2546 { 0.00f, 0.00f, 0.55f },
2281 { 1.00F, 0.00F, 0.00F }, 2547 { 1.00f, 0.00f, 0.00f },
2282 2548
2283 { 1.00F, 0.54F, 0.00F }, 2549 { 1.00f, 0.54f, 0.00f },
2284 { 0.11F, 0.56F, 1.00F }, 2550 { 0.11f, 0.56f, 1.00f },
2285 { 0.93F, 0.46F, 0.00F }, 2551 { 0.93f, 0.46f, 0.00f },
2286 { 0.18F, 0.54F, 0.34F }, 2552 { 0.18f, 0.54f, 0.34f },
2287 2553
2288 { 0.56F, 0.73F, 0.56F }, 2554 { 0.56f, 0.73f, 0.56f },
2289 { 0.80F, 0.80F, 0.80F }, 2555 { 0.80f, 0.80f, 0.80f },
2290 { 0.55F, 0.41F, 0.13F }, 2556 { 0.55f, 0.41f, 0.13f },
2291 { 0.99F, 0.77F, 0.26F }, 2557 { 0.99f, 0.77f, 0.26f },
2292 2558
2293 { 0.74F, 0.65F, 0.41F }, 2559 { 0.74f, 0.65f, 0.41f },
2294 2560
2295 { 0.00F, 1.00F, 1.00F }, 2561 { 0.00f, 1.00f, 1.00f },
2296 { 1.00F, 0.00F, 1.00F }, 2562 { 1.00f, 0.00f, 1.00f },
2297 { 1.00F, 1.00F, 0.00F }, 2563 { 1.00f, 1.00f, 0.00f },
2298 }; 2564 };
2299 2565
2300 int x, y; 2566 int x, y;
2301 2567
2302 glEnable (GL_TEXTURE_2D); 2568 glEnable (GL_TEXTURE_2D);
2569 /* GL_REPLACE would be correct, as we don't need to modulate alpha,
2570 * but the nvidia driver (185.18.14) mishandles alpha textures
2571 * and takes the colour from god knows where instead of using
2572 * Cp. MODULATE results in the same colour, but slightly different
2573 * alpha, but atcually gives us the correct colour with nvidia.
2574 */
2303 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 2575 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2304 glEnable (GL_BLEND); 2576 glEnable (GL_BLEND);
2305 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2577 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2306 glBegin (GL_QUADS); 2578 glBegin (GL_QUADS);
2307 2579
2308 for (y = 0; y < h; y++) 2580 for (y = 0; y < h; y++)
2312 2584
2313 if (m) 2585 if (m)
2314 { 2586 {
2315 float *c = color [m & 15]; 2587 float *c = color [m & 15];
2316 2588
2317 float tx1 = m & 0x40 ? 0.5 : 0.; 2589 float tx1 = m & 0x40 ? 0.5f : 0.f;
2318 float tx2 = tx1 + 0.5; 2590 float tx2 = tx1 + 0.5f;
2319 2591
2320 glColor4f (c[0], c[1], c[2], 0.75); 2592 glColor4f (c[0], c[1], c[2], 1);
2321 glTexCoord2f (tx1, 0.); glVertex2i (x , y ); 2593 glTexCoord2f (tx1, 0.); glVertex2i (x , y );
2322 glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1); 2594 glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
2323 glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1); 2595 glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
2324 glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y ); 2596 glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
2325 } 2597 }
2333void 2605void
2334fow_texture (DC::Map self, int mx, int my, int sw, int sh) 2606fow_texture (DC::Map self, int mx, int my, int sw, int sh)
2335 PPCODE: 2607 PPCODE:
2336{ 2608{
2337 int x, y; 2609 int x, y;
2338 int sw1 = sw + 2; 2610 int sw1 = sw + 2;
2339 int sh1 = sh + 2; 2611 int sh1 = sh + 2;
2340 int sh3 = sh * 3; 2612 int sh3 = sh * 3;
2341 int sw34 = (sw * 3 + 3) & ~3; 2613 int sw3 = sw * 3;
2614 SV *darkness3_sv = sv_2mortal (newSV (sw3 * sh3));
2615 uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv);
2342 uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1); 2616 uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1);
2343 SV *darkness3_sv = sv_2mortal (newSV (sw34 * sh3)); 2617 memset (darkness1, 0, sw1*sh1);
2344 uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv);
2345 2618
2346 SvPOK_only (darkness3_sv); 2619 SvPOK_only (darkness3_sv);
2347 SvCUR_set (darkness3_sv, sw34 * sh3); 2620 SvCUR_set (darkness3_sv, sw3 * sh3);
2348 2621
2349 mx += self->x - 1; 2622 mx += self->x - 1;
2350 my += self->y - 1; 2623 my += self->y - 1;
2351
2352 memset (darkness1, 255 - FOW_DARKNESS, sw1 * sh1);
2353 2624
2354 for (y = 0; y < sh1; y++) 2625 for (y = 0; y < sh1; y++)
2355 if (0 <= y + my && y + my < self->rows) 2626 if (0 <= y + my && y + my < self->rows)
2356 { 2627 {
2357 maprow *row = self->row + (y + my); 2628 maprow *row = self->row + (y + my);
2360 if (row->c0 <= x + mx && x + mx < row->c1) 2631 if (row->c0 <= x + mx && x + mx < row->c1)
2361 { 2632 {
2362 mapcell *cell = row->col + (x + mx - row->c0); 2633 mapcell *cell = row->col + (x + mx - row->c0);
2363 2634
2364 darkness1 [y * sw1 + x] = cell->darkness 2635 darkness1 [y * sw1 + x] = cell->darkness
2365 ? 255 - (cell->darkness - 1) 2636 ? DARKNESS_ADJUST (255 - (cell->darkness - 1))
2366 : 255 - FOW_DARKNESS; 2637 : DARKNESS_ADJUST (255 - FOW_DARKNESS);
2367 } 2638 }
2368 } 2639 }
2369 2640
2370 for (y = 0; y < sh; ++y) 2641 for (y = 0; y < sh; ++y)
2371 for (x = 0; x < sw; ++x) 2642 for (x = 0; x < sw; ++x)
2390 2661
2391 uint8_t r13 = (d13 + d23 + d12) / 3; 2662 uint8_t r13 = (d13 + d23 + d12) / 3;
2392 uint8_t r23 = d23; 2663 uint8_t r23 = d23;
2393 uint8_t r33 = (d23 + d33 + d32) / 3; 2664 uint8_t r33 = (d23 + d33 + d32) / 3;
2394 2665
2395 darkness3 [(y * 3 ) * sw34 + (x * 3 )] = MAX (d22, r11); 2666 darkness3 [(y * 3 ) * sw3 + (x * 3 )] = MAX (d22, r11);
2396 darkness3 [(y * 3 ) * sw34 + (x * 3 + 1)] = MAX (d22, r21); 2667 darkness3 [(y * 3 ) * sw3 + (x * 3 + 1)] = MAX (d22, r21);
2397 darkness3 [(y * 3 ) * sw34 + (x * 3 + 2)] = MAX (d22, r31); 2668 darkness3 [(y * 3 ) * sw3 + (x * 3 + 2)] = MAX (d22, r31);
2398 darkness3 [(y * 3 + 1) * sw34 + (x * 3 )] = MAX (d22, r12); 2669 darkness3 [(y * 3 + 1) * sw3 + (x * 3 )] = MAX (d22, r12);
2399 darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 1)] = MAX (d22, r22); 2670 darkness3 [(y * 3 + 1) * sw3 + (x * 3 + 1)] = MAX (d22, r22); /* this MUST be == d22 */
2400 darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 2)] = MAX (d22, r32); 2671 darkness3 [(y * 3 + 1) * sw3 + (x * 3 + 2)] = MAX (d22, r32);
2401 darkness3 [(y * 3 + 2) * sw34 + (x * 3 )] = MAX (d22, r13); 2672 darkness3 [(y * 3 + 2) * sw3 + (x * 3 )] = MAX (d22, r13);
2402 darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 1)] = MAX (d22, r23); 2673 darkness3 [(y * 3 + 2) * sw3 + (x * 3 + 1)] = MAX (d22, r23);
2403 darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 2)] = MAX (d22, r33); 2674 darkness3 [(y * 3 + 2) * sw3 + (x * 3 + 2)] = MAX (d22, r33);
2404 } 2675 }
2405 2676
2406 free (darkness1); 2677 free (darkness1);
2407 2678
2408 EXTEND (SP, 3); 2679 EXTEND (SP, 3);
2409 PUSHs (sv_2mortal (newSViv (sw34))); 2680 PUSHs (sv_2mortal (newSViv (sw3)));
2410 PUSHs (sv_2mortal (newSViv (sh3))); 2681 PUSHs (sv_2mortal (newSViv (sh3)));
2411 PUSHs (darkness3_sv); 2682 PUSHs (darkness3_sv);
2412} 2683}
2413 2684
2414SV * 2685SV *
2477 else 2748 else
2478 *data++ = 0; 2749 *data++ = 0;
2479 } 2750 }
2480 } 2751 }
2481 2752
2482 /* if size is w*h + 5 then no data has been found */ 2753 /* if size is w*h + 5 then no data has been found */
2483 if (data - (uint8_t *)SvPVX (data_sv) != w * h + 5) 2754 if (data - (uint8_t *)SvPVX (data_sv) != w * h + 5)
2484 { 2755 {
2485 SvPOK_only (data_sv); 2756 SvPOK_only (data_sv);
2486 SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv)); 2757 SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
2487 } 2758 }
2488 2759
2489 RETVAL = data_sv; 2760 RETVAL = data_sv;
2490} 2761}
2491 OUTPUT: 2762 OUTPUT:
2492 RETVAL 2763 RETVAL
2493 2764
2494void 2765void
2501 STRLEN len; 2772 STRLEN len;
2502 uint8_t *data, *end; 2773 uint8_t *data, *end;
2503 2774
2504 len = SvLEN (data_sv); 2775 len = SvLEN (data_sv);
2505 SvGROW (data_sv, len + 8); // reserve at least 7+ bytes more 2776 SvGROW (data_sv, len + 8); // reserve at least 7+ bytes more
2506 data = SvPVbyte_nolen (data_sv); 2777 data = (uint8_t *)SvPVbyte_nolen (data_sv);
2507 end = data + len + 8; 2778 end = data + len + 8;
2508 2779
2509 if (len < 5) 2780 if (len < 5)
2510 XSRETURN_EMPTY; 2781 XSRETURN_EMPTY;
2511 2782
2572} 2843}
2573 2844
2574MODULE = Deliantra::Client PACKAGE = DC::RW 2845MODULE = Deliantra::Client PACKAGE = DC::RW
2575 2846
2576DC::RW 2847DC::RW
2577new (SV *class, SV *data_sv) 2848new (SV *klass, SV *data_sv)
2578 CODE: 2849 CODE:
2579{ 2850{
2580 STRLEN datalen; 2851 STRLEN datalen;
2581 char *data = SvPVbyte (data_sv, datalen); 2852 char *data = SvPVbyte (data_sv, datalen);
2582 2853
2584} 2855}
2585 OUTPUT: 2856 OUTPUT:
2586 RETVAL 2857 RETVAL
2587 2858
2588DC::RW 2859DC::RW
2589new_from_file (SV *class, const char *path, const char *mode = "rb") 2860new_from_file (SV *klass, const char *path, const char *mode = "rb")
2590 CODE: 2861 CODE:
2591 RETVAL = SDL_RWFromFile (path, mode); 2862 RETVAL = SDL_RWFromFile (path, mode);
2592 OUTPUT: 2863 OUTPUT:
2593 RETVAL 2864 RETVAL
2594 2865
2612 if (RETVAL < 0) 2883 if (RETVAL < 0)
2613 { 2884 {
2614 RETVAL = Mix_GroupOldest (-1); 2885 RETVAL = Mix_GroupOldest (-1);
2615 2886
2616 if (RETVAL < 0) 2887 if (RETVAL < 0)
2888 {
2889 // happens sometimes, maybe it just stopped playing(?)
2890 RETVAL = Mix_GroupAvailable (-1);
2891
2892 if (RETVAL < 0)
2617 XSRETURN_UNDEF; 2893 XSRETURN_UNDEF;
2618 2894 }
2895 else
2619 Mix_HaltChannel (RETVAL); 2896 Mix_HaltChannel (RETVAL);
2620 } 2897 }
2621 2898
2622 Mix_UnregisterAllEffects (RETVAL); 2899 Mix_UnregisterAllEffects (RETVAL);
2623 Mix_Volume (RETVAL, 128); 2900 Mix_Volume (RETVAL, 128);
2624} 2901}
2671void 2948void
2672set_position_r (DC::Channel self, int dx, int dy, int maxdistance) 2949set_position_r (DC::Channel self, int dx, int dy, int maxdistance)
2673 CODE: 2950 CODE:
2674{ 2951{
2675 int distance = sqrtf (dx * dx + dy * dy) * (255.f / sqrtf (maxdistance * maxdistance)); 2952 int distance = sqrtf (dx * dx + dy * dy) * (255.f / sqrtf (maxdistance * maxdistance));
2676 int angle = 360 + (int)roundf (atan2f (dx, -dy) * 180.f / (float)M_PI); 2953 int angle = atan2f (dx, -dy) * 180.f / (float)M_PI + 360.f;
2677 Mix_SetPosition (self, angle, CLAMP (distance, 0, 255)); 2954 Mix_SetPosition (self, angle, CLAMP (distance, 0, 255));
2678} 2955}
2679 2956
2680void 2957void
2681set_reverse_stereo (DC::Channel self, int flip) 2958set_reverse_stereo (DC::Channel self, int flip)
2684 2961
2685MODULE = Deliantra::Client PACKAGE = DC::MixChunk 2962MODULE = Deliantra::Client PACKAGE = DC::MixChunk
2686 2963
2687PROTOTYPES: DISABLE 2964PROTOTYPES: DISABLE
2688 2965
2966void
2967decoders ()
2968 PPCODE:
2969#if SDL_MIXER_MAJOR_VERSION > 1 || SDL_MIXER_MINOR_VERSION > 2 || SDL_MIXER_PATCHLEVEL >= 10
2970 int i, num = Mix_GetNumChunkDecoders ();
2971 EXTEND (SP, num);
2972 for (i = 0; i < num; ++i)
2973 PUSHs (sv_2mortal (newSVpv (Mix_GetChunkDecoder (i), 0)));
2974#else
2975 XPUSHs (sv_2mortal (newSVpv ("(sdl mixer too old)", 0)));
2976#endif
2977
2689DC::MixChunk 2978DC::MixChunk
2690new (SV *class, DC::RW rwops) 2979new (SV *klass, DC::RW rwops)
2691 CODE: 2980 CODE:
2692 RETVAL = Mix_LoadWAV_RW (rwops, 1); 2981 RETVAL = Mix_LoadWAV_RW (rwops, 1);
2693 OUTPUT: 2982 OUTPUT:
2694 RETVAL 2983 RETVAL
2695 2984
2725 OUTPUT: 3014 OUTPUT:
2726 RETVAL 3015 RETVAL
2727 3016
2728MODULE = Deliantra::Client PACKAGE = DC::MixMusic 3017MODULE = Deliantra::Client PACKAGE = DC::MixMusic
2729 3018
3019void
3020decoders ()
3021 PPCODE:
3022#if SDL_MIXER_MAJOR_VERSION > 1 || SDL_MIXER_MINOR_VERSION > 2 || SDL_MIXER_PATCHLEVEL >= 10
3023 int i, num = Mix_GetNumMusicDecoders ();
3024 EXTEND (SP, num);
3025 for (i = 0; i < num; ++i)
3026 PUSHs (sv_2mortal (newSVpv (Mix_GetMusicDecoder (i), 0)));
3027#else
3028 XPUSHs (sv_2mortal (newSVpv ("(sdl mixer too old)", 0)));
3029#endif
3030
2730int 3031int
2731volume (int volume = -1) 3032volume (int volume = -1)
2732 PROTOTYPE: ;$ 3033 PROTOTYPE: ;$
2733 CODE: 3034 CODE:
2734 if (items > 0) 3035 if (items > 0)
2745void 3046void
2746halt () 3047halt ()
2747 CODE: 3048 CODE:
2748 Mix_HaltMusic (); 3049 Mix_HaltMusic ();
2749 3050
3051int
3052playing ()
3053 CODE:
3054 RETVAL = Mix_PlayingMusic ();
3055 OUTPUT:
3056 RETVAL
3057
2750DC::MixMusic 3058DC::MixMusic
2751new (SV *class, DC::RW rwops) 3059new (SV *klass, DC::RW rwops)
2752 CODE: 3060 CODE:
2753 RETVAL = Mix_LoadMUS_RW (rwops); 3061 RETVAL = Mix_LoadMUS_RW (rwops);
2754 OUTPUT: 3062 OUTPUT:
2755 RETVAL 3063 RETVAL
2756 3064
2784 } *civ, const_iv[] = { 3092 } *civ, const_iv[] = {
2785# define const_iv(name) { # name, (IV)name } 3093# define const_iv(name) { # name, (IV)name }
2786 const_iv (GL_VENDOR), 3094 const_iv (GL_VENDOR),
2787 const_iv (GL_VERSION), 3095 const_iv (GL_VERSION),
2788 const_iv (GL_EXTENSIONS), 3096 const_iv (GL_EXTENSIONS),
3097 const_iv (GL_MAX_TEXTURE_UNITS),
2789 const_iv (GL_COLOR_MATERIAL), 3098 const_iv (GL_COLOR_MATERIAL),
2790 const_iv (GL_SMOOTH), 3099 const_iv (GL_SMOOTH),
2791 const_iv (GL_FLAT), 3100 const_iv (GL_FLAT),
2792 const_iv (GL_DITHER), 3101 const_iv (GL_DITHER),
2793 const_iv (GL_BLEND), 3102 const_iv (GL_BLEND),
2805 const_iv (GL_ZERO), 3114 const_iv (GL_ZERO),
2806 const_iv (GL_SRC_ALPHA), 3115 const_iv (GL_SRC_ALPHA),
2807 const_iv (GL_DST_ALPHA), 3116 const_iv (GL_DST_ALPHA),
2808 const_iv (GL_ONE_MINUS_SRC_ALPHA), 3117 const_iv (GL_ONE_MINUS_SRC_ALPHA),
2809 const_iv (GL_ONE_MINUS_DST_ALPHA), 3118 const_iv (GL_ONE_MINUS_DST_ALPHA),
3119 const_iv (GL_SRC_COLOR),
3120 const_iv (GL_DST_COLOR),
3121 const_iv (GL_ONE_MINUS_SRC_COLOR),
3122 const_iv (GL_ONE_MINUS_DST_COLOR),
2810 const_iv (GL_SRC_ALPHA_SATURATE), 3123 const_iv (GL_SRC_ALPHA_SATURATE),
2811 const_iv (GL_RGB), 3124 const_iv (GL_RGB),
2812 const_iv (GL_RGBA), 3125 const_iv (GL_RGBA),
2813 const_iv (GL_RGBA4), 3126 const_iv (GL_RGBA4),
2814 const_iv (GL_RGBA8), 3127 const_iv (GL_RGBA8),
2882 const_iv (GL_NICEST), 3195 const_iv (GL_NICEST),
2883 const_iv (GL_V2F), 3196 const_iv (GL_V2F),
2884 const_iv (GL_V3F), 3197 const_iv (GL_V3F),
2885 const_iv (GL_T2F_V3F), 3198 const_iv (GL_T2F_V3F),
2886 const_iv (GL_T2F_N3F_V3F), 3199 const_iv (GL_T2F_N3F_V3F),
3200 const_iv (GL_FUNC_ADD),
3201 const_iv (GL_FUNC_SUBTRACT),
3202 const_iv (GL_FUNC_REVERSE_SUBTRACT),
2887# undef const_iv 3203# undef const_iv
2888 }; 3204 };
2889 3205
2890 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) 3206 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--)
2891 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 3207 newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv));
2892 3208
2893 texture_av = newAV (); 3209 texture_av = newAV ();
2894 AvREAL_off (texture_av); 3210 AvREAL_off (texture_av);
2895} 3211}
2896 3212
2898disable_GL_EXT_blend_func_separate () 3214disable_GL_EXT_blend_func_separate ()
2899 CODE: 3215 CODE:
2900 gl.BlendFuncSeparate = 0; 3216 gl.BlendFuncSeparate = 0;
2901 gl.BlendFuncSeparateEXT = 0; 3217 gl.BlendFuncSeparateEXT = 0;
2902 3218
2903char * 3219void
3220apple_nvidia_bug (int enable)
3221
3222const char *
2904gl_vendor () 3223gl_vendor ()
2905 CODE: 3224 CODE:
2906 RETVAL = (char *)glGetString (GL_VENDOR); 3225 RETVAL = (const char *)glGetString (GL_VENDOR);
2907 OUTPUT: 3226 OUTPUT:
2908 RETVAL 3227 RETVAL
2909 3228
2910char * 3229const char *
2911gl_version () 3230gl_version ()
2912 CODE: 3231 CODE:
2913 RETVAL = (char *)glGetString (GL_VERSION); 3232 RETVAL = (const char *)glGetString (GL_VERSION);
2914 OUTPUT: 3233 OUTPUT:
2915 RETVAL 3234 RETVAL
2916 3235
2917char * 3236const char *
2918gl_extensions () 3237gl_extensions ()
2919 CODE: 3238 CODE:
2920 RETVAL = (char *)glGetString (GL_EXTENSIONS); 3239 RETVAL = (const char *)glGetString (GL_EXTENSIONS);
2921 OUTPUT: 3240 OUTPUT:
2922 RETVAL 3241 RETVAL
2923 3242
2924const char *glGetString (GLenum pname) 3243const char *glGetString (GLenum pname)
3244 CODE:
3245 RETVAL = (const char *)glGetString (pname);
3246 OUTPUT:
3247 RETVAL
2925 3248
2926GLint glGetInteger (GLenum pname) 3249GLint glGetInteger (GLenum pname)
2927 CODE: 3250 CODE:
2928 glGetIntegerv (pname, &RETVAL); 3251 glGetIntegerv (pname, &RETVAL);
2929 OUTPUT: 3252 OUTPUT:
2937 3260
2938int glGetError () 3261int glGetError ()
2939 3262
2940void glFinish () 3263void glFinish ()
2941 3264
3265void glFlush ()
3266
2942void glClear (int mask) 3267void glClear (int mask)
2943 3268
2944void glClearColor (float r, float g, float b, float a = 1.0) 3269void glClearColor (float r, float g, float b, float a = 1.0)
2945 PROTOTYPE: @ 3270 PROTOTYPE: @
2946 3271
2955void glBlendFunc (int sfactor, int dfactor) 3280void glBlendFunc (int sfactor, int dfactor)
2956 3281
2957void glBlendFuncSeparate (int sa, int da, int saa, int daa) 3282void glBlendFuncSeparate (int sa, int da, int saa, int daa)
2958 CODE: 3283 CODE:
2959 gl_BlendFuncSeparate (sa, da, saa, daa); 3284 gl_BlendFuncSeparate (sa, da, saa, daa);
3285
3286# void glBlendEquation (int se)
2960 3287
2961void glDepthMask (int flag) 3288void glDepthMask (int flag)
2962 3289
2963void glLogicOp (int opcode) 3290void glLogicOp (int opcode)
2964 3291
2999void glRotate (float angle, float x, float y, float z) 3326void glRotate (float angle, float x, float y, float z)
3000 CODE: 3327 CODE:
3001 glRotatef (angle, x, y, z); 3328 glRotatef (angle, x, y, z);
3002 3329
3003void glColor (float r, float g, float b, float a = 1.0) 3330void glColor (float r, float g, float b, float a = 1.0)
3331 PROTOTYPE: @
3004 ALIAS: 3332 ALIAS:
3005 glColor_premultiply = 1 3333 glColor_premultiply = 1
3006 CODE: 3334 CODE:
3007 if (ix) 3335 if (ix)
3008 { 3336 {
3114 3442
3115void glEndList () 3443void glEndList ()
3116 3444
3117void glCallList (int list) 3445void glCallList (int list)
3118 3446
3447void c_init ()
3448 CODE:
3449 glPixelStorei (GL_PACK_ALIGNMENT , 1);
3450 glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
3451
3119MODULE = Deliantra::Client PACKAGE = DC::UI::Base 3452MODULE = Deliantra::Client PACKAGE = DC::UI::Base
3120 3453
3121PROTOTYPES: DISABLE 3454PROTOTYPES: DISABLE
3122 3455
3123void 3456void
3124find_widget (SV *self, NV x, NV y) 3457find_widget (SV *self, NV x, NV y)
3125 PPCODE: 3458 PPCODE:
3126{ 3459{
3127 if (within_widget (self, x, y)) 3460 if (within_widget (self, x, y))
3128 XPUSHs (self); 3461 XPUSHs (self);
3129} 3462}
3130 3463
3131BOOT: 3464BOOT:
3132{ 3465{
3140 3473
3141void 3474void
3142draw (SV *self) 3475draw (SV *self)
3143 CODE: 3476 CODE:
3144{ 3477{
3145 HV *hv; 3478 HV *hv;
3146 SV **svp; 3479 SV **svp;
3147 NV x, y, w, h; 3480 NV x, y, w, h;
3148 SV *draw_x_sv = GvSV (draw_x_gv); 3481 SV *draw_x_sv = GvSV (draw_x_gv);
3149 SV *draw_y_sv = GvSV (draw_y_gv); 3482 SV *draw_y_sv = GvSV (draw_y_gv);
3150 SV *draw_w_sv = GvSV (draw_w_gv); 3483 SV *draw_w_sv = GvSV (draw_w_gv);
3151 SV *draw_h_sv = GvSV (draw_h_gv); 3484 SV *draw_h_sv = GvSV (draw_h_gv);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines