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.279 by root, Thu Oct 2 15:59:40 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{
544 608
545 return mod; 609 return mod;
546} 610}
547 611
548static void 612static void
549deliantra_main () 613deliantra_main (SV *real_main)
550{ 614{
551 char *argv[] = { 0 }; 615 dSP;
552 call_argv ("::main", G_DISCARD | G_VOID, argv); 616
617 PUSHMARK (SP);
618 call_sv (real_main, G_DISCARD | G_VOID);
553} 619}
554 620
555#ifdef __MACOSX__ 621#ifdef __MACOSX__
622 static SV *real_main;
623
556 /* to due surprising braindamage on the side of SDL design, we 624 /* to due surprising braindamage on the side of SDL design, we
557 * do some mind-boggling hack here: SDL requires a custom main() 625 * do some mind-boggling hack here: SDL requires a custom main()
558 * 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,
559 * 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,
560 * and which calls our main (== SDL_main) back. 628 * and which calls our main (== SDL_main) back.
561 */ 629 */
562 extern C_LINKAGE int 630 extern C_LINKAGE int
563 main (int argc, char *argv[]) 631 main (int argc, char *argv[])
564 { 632 {
565 deliantra_main (); 633 deliantra_main (real_main);
566 } 634 }
567 635
568 #undef main 636 #undef main
569 637
570 extern C_LINKAGE int main (int argc, char *argv[]); 638 extern C_LINKAGE int main (int argc, char *argv[]);
571 639
572 static void 640 static void
573 SDL_braino (void) 641 SDL_main_hack (SV *real_main_)
574 { 642 {
643 real_main = real_main_;
644
575 char *argv[] = { "deliantra client", 0 }; 645 char *argv[] = { "deliantra client", 0 };
576 (main) (1, argv); 646 (main) (1, argv);
577 } 647 }
578#else 648#else
579 static void 649 static void
580 SDL_braino (void) 650 SDL_main_hack (SV *real_main)
581 { 651 {
582 deliantra_main (); 652 deliantra_main (real_main);
583 } 653 }
584#endif 654#endif
585 655
586MODULE = Deliantra::Client PACKAGE = DC 656MODULE = Deliantra::Client PACKAGE = DC
587 657
788 858
789 const_iv (FOW_DARKNESS) 859 const_iv (FOW_DARKNESS)
790# undef const_iv 860# undef const_iv
791 }; 861 };
792 862
793 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--)
794 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 864 newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv));
795 865
796 assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK); 866 assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK);
797 assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE); 867 assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE);
798} 868}
799 869
815NV ceil (NV x) 885NV ceil (NV x)
816 886
817IV minpot (UV n) 887IV minpot (UV n)
818 888
819IV 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
820 896
821void 897void
822pango_init () 898pango_init ()
823 CODE: 899 CODE:
824{ 900{
832#endif 908#endif
833} 909}
834 910
835char *SDL_GetError () 911char *SDL_GetError ()
836 912
837void SDL_braino () 913void SDL_main_hack (SV *real_main)
914 PROTOTYPE: &
838 915
839int SDL_Init (U32 flags) 916int SDL_Init (U32 flags)
840 917
841int SDL_InitSubSystem (U32 flags) 918int SDL_InitSubSystem (U32 flags)
842 919
843void SDL_QuitSubSystem (U32 flags) 920void SDL_QuitSubSystem (U32 flags)
844 921
845void SDL_Quit () 922void SDL_Quit ()
846 923
847int SDL_GL_SetAttribute (int attr, int value) 924int SDL_GL_SetAttribute (int attr, int value)
925 C_ARGS: (SDL_GLattr)attr, value
848 926
849int SDL_GL_GetAttribute (int attr) 927int SDL_GL_GetAttribute (int attr)
850 CODE: 928 CODE:
851 if (SDL_GL_GetAttribute (attr, &RETVAL)) 929 if (SDL_GL_GetAttribute ((SDL_GLattr)attr, &RETVAL))
852 XSRETURN_UNDEF; 930 XSRETURN_UNDEF;
853 OUTPUT: 931 OUTPUT:
854 RETVAL 932 RETVAL
855 933
856void 934void
911 ); 989 );
912 990
913 if (RETVAL) 991 if (RETVAL)
914 { 992 {
915 av_clear (texture_av); 993 av_clear (texture_av);
916
917 SDL_WM_SetCaption ("Deliantra MORPG Client " VERSION, "Deliantra");
918#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);
919#include "glfunc.h" 995#include "glfunc.h"
920#undef GL_FUNC 996#undef GL_FUNC
997 if (!gl.ActiveTexture ) gl.ActiveTexture = gl.ActiveTextureARB;
998 if (!gl.MultiTexCoord2f) gl.MultiTexCoord2f = gl.MultiTexCoord2fARB;
921 } 999 }
922} 1000}
923 OUTPUT: 1001 OUTPUT:
924 RETVAL 1002 RETVAL
1003
1004void
1005SDL_WM_SetCaption (const char *title, const char *icon)
925 1006
926void 1007void
927SDL_GL_SwapBuffers () 1008SDL_GL_SwapBuffers ()
928 1009
929char * 1010char *
930SDL_GetKeyName (int sym) 1011SDL_GetKeyName (int sym)
1012 C_ARGS: (SDLKey)sym
931 1013
932int 1014int
933SDL_GetAppState () 1015SDL_GetAppState ()
934 1016
935int 1017int
936SDL_GetModState () 1018SDL_GetModState ()
937 1019
1020int
1021SDL_WaitEvent ()
1022 C_ARGS: 0
1023
938void 1024void
1025SDL_PumpEvents ()
1026
1027void
939poll_events () 1028peep_events ()
940 PPCODE: 1029 PPCODE:
941{ 1030{
942 SDL_Event ev; 1031 SDL_Event ev;
943 1032
944 SDL_PumpEvents (); 1033 SDL_PumpEvents ();
1010 1099
1011 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))));
1012 } 1101 }
1013} 1102}
1014 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
1015int 1117int
1016Mix_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)
1017 POSTCALL: 1119 POSTCALL:
1018 Mix_HookMusicFinished (music_finished); 1120 Mix_HookMusicFinished (music_finished);
1019 Mix_ChannelFinished (channel_finished); 1121 Mix_ChannelFinished (channel_finished);
1020 1122
1021void 1123void
1022Mix_QuerySpec () 1124Mix_QuerySpec ()
1081add_font (char *file) 1183add_font (char *file)
1082 CODE: 1184 CODE:
1083 RETVAL = FcConfigAppFontAddFile (0, (const FcChar8 *)file); 1185 RETVAL = FcConfigAppFontAddFile (0, (const FcChar8 *)file);
1084 OUTPUT: 1186 OUTPUT:
1085 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)
1086 1195
1087void 1196void
1088load_image_inline (SV *image_) 1197load_image_inline (SV *image_)
1089 ALIAS: 1198 ALIAS:
1090 load_image_file = 1 1199 load_image_file = 1
1136 1245
1137 SDL_LockSurface (surface2); 1246 SDL_LockSurface (surface2);
1138 EXTEND (SP, 6); 1247 EXTEND (SP, 6);
1139 PUSHs (sv_2mortal (newSViv (surface2->w))); 1248 PUSHs (sv_2mortal (newSViv (surface2->w)));
1140 PUSHs (sv_2mortal (newSViv (surface2->h))); 1249 PUSHs (sv_2mortal (newSViv (surface2->h)));
1141 PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch))); 1250 PUSHs (sv_2mortal (newSVpvn ((const char *)surface2->pixels, surface2->h * surface2->pitch)));
1142 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)));
1143 PUSHs (sv_2mortal (newSViv (GL_RGBA))); 1252 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
1144 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE))); 1253 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
1145 SDL_UnlockSurface (surface2); 1254 SDL_UnlockSurface (surface2);
1146 1255
1206#if DEBUG 1315#if DEBUG
1207 VALGRIND_DO_LEAK_CHECK; 1316 VALGRIND_DO_LEAK_CHECK;
1208#endif 1317#endif
1209} 1318}
1210 1319
1320int
1321SvREFCNT (SV *sv)
1322 CODE:
1323 RETVAL = SvREFCNT (sv);
1324 OUTPUT:
1325 RETVAL
1326
1211MODULE = Deliantra::Client PACKAGE = DC::Font 1327MODULE = Deliantra::Client PACKAGE = DC::Font
1212 1328
1213PROTOTYPES: DISABLE 1329PROTOTYPES: DISABLE
1214 1330
1215DC::Font 1331DC::Font
1216new_from_file (SV *class, char *path, int id = 0) 1332new_from_file (SV *klass, char *path, int id = 0)
1217 CODE: 1333 CODE:
1218{ 1334{
1219 int count; 1335 int count;
1220 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count); 1336 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count);
1221 RETVAL = pango_fc_font_description_from_pattern (pattern, 0); 1337 RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
1250 PROTOTYPE: 1366 PROTOTYPE:
1251 CODE: 1367 CODE:
1252 tc_restore (); 1368 tc_restore ();
1253 1369
1254DC::Layout 1370DC::Layout
1255new (SV *class) 1371new (SV *klass)
1256 CODE: 1372 CODE:
1257 New (0, RETVAL, 1, struct cf_layout); 1373 New (0, RETVAL, 1, struct cf_layout);
1258 1374
1259 RETVAL->pl = pango_layout_new (opengl_context); 1375 RETVAL->pl = pango_layout_new (opengl_context);
1260 RETVAL->r = 1.; 1376 RETVAL->r = 1.;
1409 1525
1410void 1526void
1411set_height (DC::Layout self, int base_height) 1527set_height (DC::Layout self, int base_height)
1412 CODE: 1528 CODE:
1413 if (self->base_height != base_height) 1529 if (self->base_height != base_height)
1414 { 1530 {
1415 self->base_height = base_height; 1531 self->base_height = base_height;
1416 layout_update_font (self); 1532 layout_update_font (self);
1417 } 1533 }
1418 1534
1419void 1535void
1646 glDisable (GL_ALPHA_TEST); 1762 glDisable (GL_ALPHA_TEST);
1647 glDisable (GL_BLEND); 1763 glDisable (GL_BLEND);
1648 } 1764 }
1649} 1765}
1650 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
1651IV 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)
1652 CODE: 1889 CODE:
1653{ 1890{
1654 GLint width; 1891 GLint width;
1655 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);
1662MODULE = Deliantra::Client PACKAGE = DC::Map 1899MODULE = Deliantra::Client PACKAGE = DC::Map
1663 1900
1664PROTOTYPES: DISABLE 1901PROTOTYPES: DISABLE
1665 1902
1666DC::Map 1903DC::Map
1667new (SV *class) 1904new (SV *klass)
1668 CODE: 1905 CODE:
1669 New (0, RETVAL, 1, struct map); 1906 New (0, RETVAL, 1, mapgrid);
1670 RETVAL->x = 0; 1907 RETVAL->x = 0;
1671 RETVAL->y = 0; 1908 RETVAL->y = 0;
1672 RETVAL->w = 0; 1909 RETVAL->w = 0;
1673 RETVAL->h = 0; 1910 RETVAL->h = 0;
1674 RETVAL->ox = 0; 1911 RETVAL->ox = 0;
1711 1948
1712void 1949void
1713set_smooth (DC::Map self, int face, int smooth, int level) 1950set_smooth (DC::Map self, int face, int smooth, int level)
1714 CODE: 1951 CODE:
1715{ 1952{
1716 tileid texid; 1953 tileid texid;
1717 maptex *tex; 1954 maptex *tex;
1718 1955
1719 if (face < 0 || face >= self->faces) 1956 if (face < 0 || face >= self->faces)
1720 return; 1957 return;
1721 1958
1722 if (smooth < 0 || smooth >= self->faces) 1959 if (smooth < 0 || smooth >= self->faces)
1723 return; 1960 return;
1724 1961
1725 texid = self->face2tile [face]; 1962 texid = self->face2tile [face];
1726 1963
1727 if (!texid) 1964 if (!texid)
1728 return; 1965 return;
1729 1966
1730 tex = self->tex + texid; 1967 tex = self->tex + texid;
1759 //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);
1760 // use uglier nearest interpolation because linear suffers 1997 // use uglier nearest interpolation because linear suffers
1761 // from transparent color bleeding and ugly wrapping effects. 1998 // from transparent color bleeding and ugly wrapping effects.
1762 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1999 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1763} 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 }
1764 2021
1765int 2022int
1766ox (DC::Map self) 2023ox (DC::Map self)
1767 ALIAS: 2024 ALIAS:
1768 oy = 1 2025 oy = 1
1808 self->y += MAP_EXTEND_Y; 2065 self->y += MAP_EXTEND_Y;
1809 } 2066 }
1810} 2067}
1811 2068
1812SV * 2069SV *
1813map1a_update (DC::Map self, SV *data_, int extmap) 2070map1a_update (DC::Map self, SV *data_)
1814 CODE: 2071 CODE:
1815{ 2072{
1816 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_); 2073 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1817 uint8_t *data_end = (uint8_t *)SvEND (data_); 2074 uint8_t *data_end = (uint8_t *)SvEND (data_);
1818 mapcell *cell; 2075 mapcell *cell;
1839 2096
1840 //TODO: don't trust server data to be in-range(!) 2097 //TODO: don't trust server data to be in-range(!)
1841 2098
1842 if (flags & 8) 2099 if (flags & 8)
1843 { 2100 {
2101 uint8_t ext, cmd;
2102
1844 if (extmap) 2103 do
1845 { 2104 {
1846 uint8_t ext, cmd; 2105 ext = *data++;
2106 cmd = ext & 0x7f;
1847 2107
1848 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
1849 { 2111 {
1850 ext = *data++;
1851 cmd = ext & 0x7f;
1852
1853 if (cmd < 4)
1854 cell->darkness = 255 - ext * 64 + 1;
1855 else if (cmd == 5) // health
1856 {
1857 cell->stat_width = 1; 2112 cell->stat_width = 1;
1858 cell->stat_hp = *data++; 2113 cell->stat_hp = *data++;
1859 }
1860 else if (cmd == 6) // monster width
1861 cell->stat_width = *data++ + 1;
1862 else if (cmd == 0x47)
1863 {
1864 if (*data == 1) cell->player = data [1];
1865 else if (*data == 2) cell->player = data [2] + (data [1] << 8);
1866 else if (*data == 3) cell->player = data [3] + (data [2] << 8) + (data [1] << 16);
1867 else if (*data == 4) cell->player = data [4] + (data [3] << 8) + (data [2] << 16) + (data [1] << 24);
1868
1869 data += *data + 1;
1870 }
1871 else if (cmd == 8) // cell flags
1872 cell->flags = *data++;
1873 else if (ext & 0x40) // unknown, multibyte => skip
1874 data += *data + 1;
1875 else
1876 data++;
1877 } 2114 }
1878 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++;
1879 } 2132 }
1880 else 2133 while (ext & 0x80);
1881 cell->darkness = *data++ + 1;
1882 } 2134 }
1883 2135
1884 for (z = 0; z <= 2; ++z) 2136 for (z = 0; z <= 2; ++z)
1885 if (flags & (4 >> z)) 2137 if (flags & (4 >> z))
1886 { 2138 {
1889 cell->tile [z] = self->face2tile [face]; 2141 cell->tile [z] = self->face2tile [face];
1890 2142
1891 if (cell->tile [z]) 2143 if (cell->tile [z])
1892 { 2144 {
1893 maptex *tex = self->tex + cell->tile [z]; 2145 maptex *tex = self->tex + cell->tile [z];
2146 tex->unused = 0;
1894 if (!tex->name) 2147 if (!tex->name)
1895 av_push (missing, newSViv (cell->tile [z])); 2148 av_push (missing, newSViv (cell->tile [z]));
1896 2149
1897 if (tex->smoothtile) 2150 if (tex->smoothtile)
1898 { 2151 {
1899 maptex *smooth = self->tex + tex->smoothtile; 2152 maptex *smooth = self->tex + tex->smoothtile;
2153 smooth->unused = 0;
1900 if (!smooth->name) 2154 if (!smooth->name)
1901 av_push (missing, newSViv (tex->smoothtile)); 2155 av_push (missing, newSViv (tex->smoothtile));
1902 } 2156 }
1903 } 2157 }
1904 } 2158 }
1932 ? self->row + y 2186 ? self->row + y
1933 : 0; 2187 : 0;
1934 2188
1935 for (x = x0; x < x1; x++) 2189 for (x = x0; x < x1; x++)
1936 { 2190 {
1937 int r = 32, g = 32, b = 32, a = 192; 2191 unsigned int r = 32, g = 32, b = 32, a = 192;
1938 2192
1939 if (row && row->c0 <= x && x < row->c1) 2193 if (row && row->c0 <= x && x < row->c1)
1940 { 2194 {
1941 mapcell *cell = row->col + (x - row->c0); 2195 mapcell *cell = row->col + (x - row->c0);
1942 2196
1944 { 2198 {
1945 maptex tex = self->tex [cell->tile [z]]; 2199 maptex tex = self->tex [cell->tile [z]];
1946 int a0 = 255 - tex.a; 2200 int a0 = 255 - tex.a;
1947 int a1 = tex.a; 2201 int a1 = tex.a;
1948 2202
1949 r = (r * a0 + tex.r * a1) / 255; 2203 r = div255 (r * a0 + tex.r * a1);
1950 g = (g * a0 + tex.g * a1) / 255; 2204 g = div255 (g * a0 + tex.g * a1);
1951 b = (b * a0 + tex.b * a1) / 255; 2205 b = div255 (b * a0 + tex.b * a1);
1952 a = (a * a0 + tex.a * a1) / 255; 2206 a = div255 (a * a0 + tex.a * a1);
1953 } 2207 }
1954 } 2208 }
1955 2209
1956 *map++ = (r ) 2210 *map++ = (r )
1957 | (g << 8) 2211 | (g << 8)
1958 | (b << 16) 2212 | (b << 16)
1959 | (a << 24); 2213 | (a << 24);
1960 } 2214 }
1961 } 2215 }
1962 2216
1963 RETVAL = map_sv; 2217 RETVAL = map_sv;
1964} 2218}
1965 OUTPUT: 2219 OUTPUT:
1966 RETVAL 2220 RETVAL
1967 2221
1968void 2222void
1969draw (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)
1970 CODE: 2224 CODE:
1971{ 2225{
1972 int x, y, z; 2226 int x, y, z;
1973 2227
1974 HV *smooth = (HV *)sv_2mortal ((SV *)newHV ());
1975 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
1976 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)
1977 smooth_key skey; 2230 smooth_key skey;
1978 int pl_x, pl_y; 2231 int pl_x, pl_y;
1979 maptex pl_tex; 2232 maptex pl_tex;
1980 rc_t *rc = rc_alloc (); 2233 rc_t *rc = rc_alloc ();
2234 rc_t *rc_ov = rc_alloc ();
1981 rc_key_t key; 2235 rc_key_t key;
1982 rc_array_t *arr; 2236 rc_array_t *arr;
1983 2237
1984 pl_tex.name = 0; 2238 pl_tex.name = 0;
1985 2239
1986 // thats current max. sorry. 2240 // that's current max. sorry.
1987 if (sw > 255) sw = 255; 2241 if (sw > 255) sw = 255;
1988 if (sh > 255) sh = 255; 2242 if (sh > 255) sh = 255;
1989 2243
1990 // clear key, in case of extra padding 2244 // clear key, in case of extra padding
1991 memset (&skey, 0, sizeof (skey)); 2245 memset (&skey, 0, sizeof (skey));
1995 key.g = 255; 2249 key.g = 255;
1996 key.b = 255; 2250 key.b = 255;
1997 key.a = 255; 2251 key.a = 255;
1998 key.mode = GL_QUADS; 2252 key.mode = GL_QUADS;
1999 key.format = GL_T2F_V3F; 2253 key.format = GL_T2F_V3F;
2000 key.texname = -1;
2001 2254
2002 mx += self->x; 2255 mx += self->x;
2003 my += self->y; 2256 my += self->y;
2004 2257
2005 // first pass: determine smooth_max 2258 // first pass: determine smooth_max
2028 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2281 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2029 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 2282 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2030 2283
2031 for (z = 0; z <= 2; z++) 2284 for (z = 0; z <= 2; z++)
2032 { 2285 {
2286 smooth_hash smooth;
2033 memset (smooth_level, 0, sizeof (smooth_level)); 2287 memset (smooth_level, 0, sizeof (smooth_level));
2288 key.texname = -1;
2034 2289
2035 for (y = 0; y < sh; y++) 2290 for (y = 0; y < sh; y++)
2036 if (0 <= y + my && y + my < self->rows) 2291 if (0 <= y + my && y + my < self->rows)
2037 { 2292 {
2038 maprow *row = self->row + (y + my); 2293 maprow *row = self->row + (y + my);
2044 tileid tile = cell->tile [z]; 2299 tileid tile = cell->tile [z];
2045 2300
2046 if (tile) 2301 if (tile)
2047 { 2302 {
2048 maptex tex = self->tex [tile]; 2303 maptex tex = self->tex [tile];
2049 int px = (x + 1) * T - tex.w; 2304 int px, py;
2050 int py = (y + 1) * T - tex.h;
2051 2305
2052 if (key.texname != tex.name) 2306 if (key.texname != tex.name)
2053 { 2307 {
2308 self->tex [tile].unused = 0;
2309
2054 if (!tex.name) 2310 if (!tex.name)
2055 tex = self->tex [2]; /* missing, replace by noface */ 2311 tex = self->tex [TEXID_NOFACE]; /* missing, replace by noface */
2056 2312
2057 key.texname = tex.name; 2313 key.texname = tex.name;
2058 arr = rc_array (rc, &key); 2314 arr = rc_array (rc, &key);
2059 } 2315 }
2316
2317 px = (x + 1) * Th - tex.w;
2318 py = (y + 1) * Tw - tex.h;
2060 2319
2061 if (expect_false (cell->player == player) && expect_false (z == 2)) 2320 if (expect_false (cell->player == player) && expect_false (z == 2))
2062 { 2321 {
2063 pl_x = px; 2322 pl_x = px;
2064 pl_y = py; 2323 pl_y = py;
2069 rc_t2f_v3f (arr, 0 , 0 , px , py , 0); 2328 rc_t2f_v3f (arr, 0 , 0 , px , py , 0);
2070 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);
2071 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);
2072 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);
2073 2332
2074 if (expect_false (cell->flags) && expect_false (z == 2))
2075 {
2076 // overlays such as the speech bubble, probably more to come
2077 if (cell->flags & 1)
2078 {
2079 maptex tex = self->tex [1];
2080 int px = x * T + T * 2 / 32;
2081 int py = y * T - T * 6 / 32;
2082
2083 if (tex.name)
2084 {
2085 if (key.texname != tex.name)
2086 {
2087 key.texname = tex.name;
2088 arr = rc_array (rc, &key);
2089 }
2090
2091 rc_t2f_v3f (arr, 0 , 0 , px , py , 0);
2092 rc_t2f_v3f (arr, 0 , tex.t, px , py + T, 0);
2093 rc_t2f_v3f (arr, tex.s, tex.t, px + T, py + T, 0);
2094 rc_t2f_v3f (arr, tex.s, 0 , px + T, py , 0);
2095 }
2096 }
2097 }
2098
2099 // update smooth hash 2333 // update smooth hash
2100 if (tex.smoothtile) 2334 if (tex.smoothtile)
2101 { 2335 {
2102 skey.tile = tex.smoothtile; 2336 skey.tile = tex.smoothtile;
2103 skey.level = tex.smoothlevel; 2337 skey.level = tex.smoothlevel;
2118 2352
2119 // corners: 1 ┛· 2 ·┗ 4 ·· 8 ·· 2353 // corners: 1 ┛· 2 ·┗ 4 ·· 8 ··
2120 // ·· ·· ·┏ ┓· 2354 // ·· ·· ·┏ ┓·
2121 2355
2122 // full tile 2356 // full tile
2123 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);
2124 2358
2125 // borders 2359 // borders
2126 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);
2127 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);
2128 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);
2129 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);
2130 2364
2131 // corners 2365 // corners
2132 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);
2133 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);
2134 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);
2135 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);
2136 } 2391 }
2137 } 2392 }
2138 } 2393 }
2139 } 2394 }
2140 2395
2156 if (smask & (((uint32_t)1) << b)) 2411 if (smask & (((uint32_t)1) << b))
2157 { 2412 {
2158 int level = (w << 5) | b; 2413 int level = (w << 5) | b;
2159 HE *he; 2414 HE *he;
2160 2415
2161 hv_iterinit (smooth); 2416 for (auto &&it = smooth.begin (); it != smooth.end (); ++it)
2162 while ((he = hv_iternext (smooth)))
2163 { 2417 {
2164 smooth_key *skey = (smooth_key *)HeKEY (he); 2418 smooth_key &skey = it->first;
2165 IV bits = SvIVX (HeVAL (he)); 2419 IV bits = it->second;
2166 2420
2167 if (!(bits & 0x1000) 2421 if (!(bits & 0x1000)
2168 && skey->level == level 2422 && skey.level == level
2169 && level > smooth_max [skey->x][skey->y]) 2423 && level > smooth_max [skey.x][skey.y])
2170 { 2424 {
2171 maptex tex = self->tex [skey->tile]; 2425 maptex tex = self->tex [skey.tile];
2172 int px = (((int)skey->x) - 1) * T; 2426 int px = (((int)skey.x) - 1) * Tw;
2173 int py = (((int)skey->y) - 1) * T; 2427 int py = (((int)skey.y) - 1) * Th;
2174 int border = bits & 15; 2428 int border = bits & 15;
2175 int corner = (bits >> 8) & ~(bits >> 4) & 15; 2429 int corner = (bits >> 8) & ~(bits >> 4) & 15;
2176 float dx = tex.s * .0625f; // 16 images/row 2430 float dx = tex.s * .0625f; // 16 images/row
2177 float dy = tex.t * .5f ; // 2 images/column 2431 float dy = tex.t * .5f ; // 2 images/column
2178 2432
2180 { 2434 {
2181 // this time avoiding texture state changes 2435 // this time avoiding texture state changes
2182 // save gobs of state changes. 2436 // save gobs of state changes.
2183 if (key.texname != tex.name) 2437 if (key.texname != tex.name)
2184 { 2438 {
2439 self->tex [skey.tile].unused = 0;
2440
2185 glEnd (); 2441 glEnd ();
2186 glBindTexture (GL_TEXTURE_2D, key.texname = tex.name); 2442 glBindTexture (GL_TEXTURE_2D, key.texname = tex.name);
2187 glBegin (GL_QUADS); 2443 glBegin (GL_QUADS);
2188 } 2444 }
2189 2445
2190 if (border) 2446 if (border)
2191 { 2447 {
2192 float ox = border * dx; 2448 float ox = border * dx;
2193 2449
2194 glTexCoord2f (ox , 0.f ); glVertex2i (px , py ); 2450 glTexCoord2f (ox , 0.f ); glVertex2i (px , py );
2195 glTexCoord2f (ox , dy ); glVertex2i (px , py + T); 2451 glTexCoord2f (ox , dy ); glVertex2i (px , py + Th);
2196 glTexCoord2f (ox + dx, dy ); glVertex2i (px + T, py + T); 2452 glTexCoord2f (ox + dx, dy ); glVertex2i (px + Tw, py + Th);
2197 glTexCoord2f (ox + dx, 0.f ); glVertex2i (px + T, py ); 2453 glTexCoord2f (ox + dx, 0.f ); glVertex2i (px + Tw, py );
2198 } 2454 }
2199 2455
2200 if (corner) 2456 if (corner)
2201 { 2457 {
2202 float ox = corner * dx; 2458 float ox = corner * dx;
2203 2459
2204 glTexCoord2f (ox , dy ); glVertex2i (px , py ); 2460 glTexCoord2f (ox , dy ); glVertex2i (px , py );
2205 glTexCoord2f (ox , dy * 2.f); glVertex2i (px , py + T); 2461 glTexCoord2f (ox , dy * 2.f); glVertex2i (px , py + Th);
2206 glTexCoord2f (ox + dx, dy * 2.f); glVertex2i (px + T, py + T); 2462 glTexCoord2f (ox + dx, dy * 2.f); glVertex2i (px + Tw, py + Th);
2207 glTexCoord2f (ox + dx, dy ); glVertex2i (px + T, py ); 2463 glTexCoord2f (ox + dx, dy ); glVertex2i (px + Tw, py );
2208 } 2464 }
2209 } 2465 }
2210 } 2466 }
2211 } 2467 }
2212 } 2468 }
2214 2470
2215 glEnd (); 2471 glEnd ();
2216 glDisable (GL_TEXTURE_2D); 2472 glDisable (GL_TEXTURE_2D);
2217 key.texname = -1; 2473 key.texname = -1;
2218 } 2474 }
2219
2220 hv_clear (smooth);
2221 } 2475 }
2222 2476
2223 if (pl_tex.name) 2477 if (pl_tex.name)
2224 { 2478 {
2225 maptex tex = pl_tex; 2479 maptex tex = pl_tex;
2235 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);
2236 2490
2237 rc_draw (rc); 2491 rc_draw (rc);
2238 } 2492 }
2239 2493
2494 rc_draw (rc_ov);
2495 rc_clear (rc_ov);
2496
2240 glDisable (GL_BLEND); 2497 glDisable (GL_BLEND);
2241 rc_free (rc); 2498 rc_free (rc);
2499 rc_free (rc_ov);
2242 2500
2243 // top layer: overlays such as the health bar 2501 // top layer: overlays such as the health bar
2244 for (y = 0; y < sh; y++) 2502 for (y = 0; y < sh; y++)
2245 if (0 <= y + my && y + my < self->rows) 2503 if (0 <= y + my && y + my < self->rows)
2246 { 2504 {
2249 for (x = 0; x < sw; x++) 2507 for (x = 0; x < sw; x++)
2250 if (row->c0 <= x + mx && x + mx < row->c1) 2508 if (row->c0 <= x + mx && x + mx < row->c1)
2251 { 2509 {
2252 mapcell *cell = row->col + (x + mx - row->c0); 2510 mapcell *cell = row->col + (x + mx - row->c0);
2253 2511
2254 int px = x * T; 2512 int px = x * Tw;
2255 int py = y * T; 2513 int py = y * Th;
2256 2514
2257 if (expect_false (cell->player == player)) 2515 if (expect_false (cell->player == player))
2258 { 2516 {
2259 px += sdx; 2517 px += sdx;
2260 py += sdy; 2518 py += sdy;
2261 } 2519 }
2262 2520
2263 if (cell->stat_hp) 2521 if (cell->stat_hp)
2264 { 2522 {
2265 int width = cell->stat_width * T; 2523 int width = cell->stat_width * Tw;
2266 int thick = (sh * T / 32 + 27) / 28 + 1 + cell->stat_width; 2524 int thick = (sh * Th / 32 + 27) / 28 + 1 + cell->stat_width;
2267 2525
2268 glColor3ub (0, 0, 0); 2526 glColor3ub (0, 0, 0);
2269 glRectf (px + 1, py - thick - 2, 2527 glRectf (px + 1, py - thick - 2,
2270 px + width - 1, py); 2528 px + width - 1, py);
2271 2529
2277 } 2535 }
2278 } 2536 }
2279} 2537}
2280 2538
2281void 2539void
2282draw_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)
2283 CODE: 2541 CODE:
2284{ 2542{
2285 static float color[16][3] = { 2543 static float color[16][3] = {
2286 { 0.00F, 0.00F, 0.00F }, 2544 { 0.00f, 0.00f, 0.00f },
2287 { 1.00F, 1.00F, 1.00F }, 2545 { 1.00f, 1.00f, 1.00f },
2288 { 0.00F, 0.00F, 0.55F }, 2546 { 0.00f, 0.00f, 0.55f },
2289 { 1.00F, 0.00F, 0.00F }, 2547 { 1.00f, 0.00f, 0.00f },
2290 2548
2291 { 1.00F, 0.54F, 0.00F }, 2549 { 1.00f, 0.54f, 0.00f },
2292 { 0.11F, 0.56F, 1.00F }, 2550 { 0.11f, 0.56f, 1.00f },
2293 { 0.93F, 0.46F, 0.00F }, 2551 { 0.93f, 0.46f, 0.00f },
2294 { 0.18F, 0.54F, 0.34F }, 2552 { 0.18f, 0.54f, 0.34f },
2295 2553
2296 { 0.56F, 0.73F, 0.56F }, 2554 { 0.56f, 0.73f, 0.56f },
2297 { 0.80F, 0.80F, 0.80F }, 2555 { 0.80f, 0.80f, 0.80f },
2298 { 0.55F, 0.41F, 0.13F }, 2556 { 0.55f, 0.41f, 0.13f },
2299 { 0.99F, 0.77F, 0.26F }, 2557 { 0.99f, 0.77f, 0.26f },
2300 2558
2301 { 0.74F, 0.65F, 0.41F }, 2559 { 0.74f, 0.65f, 0.41f },
2302 2560
2303 { 0.00F, 1.00F, 1.00F }, 2561 { 0.00f, 1.00f, 1.00f },
2304 { 1.00F, 0.00F, 1.00F }, 2562 { 1.00f, 0.00f, 1.00f },
2305 { 1.00F, 1.00F, 0.00F }, 2563 { 1.00f, 1.00f, 0.00f },
2306 }; 2564 };
2307 2565
2308 int x, y; 2566 int x, y;
2309 2567
2310 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 */
2311 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 2575 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2312 glEnable (GL_BLEND); 2576 glEnable (GL_BLEND);
2313 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2577 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2314 glBegin (GL_QUADS); 2578 glBegin (GL_QUADS);
2315 2579
2316 for (y = 0; y < h; y++) 2580 for (y = 0; y < h; y++)
2320 2584
2321 if (m) 2585 if (m)
2322 { 2586 {
2323 float *c = color [m & 15]; 2587 float *c = color [m & 15];
2324 2588
2325 float tx1 = m & 0x40 ? 0.5 : 0.; 2589 float tx1 = m & 0x40 ? 0.5f : 0.f;
2326 float tx2 = tx1 + 0.5; 2590 float tx2 = tx1 + 0.5f;
2327 2591
2328 glColor4f (c[0], c[1], c[2], 0.75); 2592 glColor4f (c[0], c[1], c[2], 1);
2329 glTexCoord2f (tx1, 0.); glVertex2i (x , y ); 2593 glTexCoord2f (tx1, 0.); glVertex2i (x , y );
2330 glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1); 2594 glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
2331 glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1); 2595 glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
2332 glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y ); 2596 glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
2333 } 2597 }
2341void 2605void
2342fow_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)
2343 PPCODE: 2607 PPCODE:
2344{ 2608{
2345 int x, y; 2609 int x, y;
2346 int sw1 = sw + 2; 2610 int sw1 = sw + 2;
2347 int sh1 = sh + 2; 2611 int sh1 = sh + 2;
2348 int sh3 = sh * 3; 2612 int sh3 = sh * 3;
2349 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);
2350 uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1); 2616 uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1);
2351 SV *darkness3_sv = sv_2mortal (newSV (sw34 * sh3)); 2617 memset (darkness1, 0, sw1*sh1);
2352 uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv);
2353 2618
2354 SvPOK_only (darkness3_sv); 2619 SvPOK_only (darkness3_sv);
2355 SvCUR_set (darkness3_sv, sw34 * sh3); 2620 SvCUR_set (darkness3_sv, sw3 * sh3);
2356 2621
2357 mx += self->x - 1; 2622 mx += self->x - 1;
2358 my += self->y - 1; 2623 my += self->y - 1;
2359
2360 memset (darkness1, 255 - FOW_DARKNESS, sw1 * sh1);
2361 2624
2362 for (y = 0; y < sh1; y++) 2625 for (y = 0; y < sh1; y++)
2363 if (0 <= y + my && y + my < self->rows) 2626 if (0 <= y + my && y + my < self->rows)
2364 { 2627 {
2365 maprow *row = self->row + (y + my); 2628 maprow *row = self->row + (y + my);
2368 if (row->c0 <= x + mx && x + mx < row->c1) 2631 if (row->c0 <= x + mx && x + mx < row->c1)
2369 { 2632 {
2370 mapcell *cell = row->col + (x + mx - row->c0); 2633 mapcell *cell = row->col + (x + mx - row->c0);
2371 2634
2372 darkness1 [y * sw1 + x] = cell->darkness 2635 darkness1 [y * sw1 + x] = cell->darkness
2373 ? 255 - (cell->darkness - 1) 2636 ? DARKNESS_ADJUST (255 - (cell->darkness - 1))
2374 : 255 - FOW_DARKNESS; 2637 : DARKNESS_ADJUST (255 - FOW_DARKNESS);
2375 } 2638 }
2376 } 2639 }
2377 2640
2378 for (y = 0; y < sh; ++y) 2641 for (y = 0; y < sh; ++y)
2379 for (x = 0; x < sw; ++x) 2642 for (x = 0; x < sw; ++x)
2398 2661
2399 uint8_t r13 = (d13 + d23 + d12) / 3; 2662 uint8_t r13 = (d13 + d23 + d12) / 3;
2400 uint8_t r23 = d23; 2663 uint8_t r23 = d23;
2401 uint8_t r33 = (d23 + d33 + d32) / 3; 2664 uint8_t r33 = (d23 + d33 + d32) / 3;
2402 2665
2403 darkness3 [(y * 3 ) * sw34 + (x * 3 )] = MAX (d22, r11); 2666 darkness3 [(y * 3 ) * sw3 + (x * 3 )] = MAX (d22, r11);
2404 darkness3 [(y * 3 ) * sw34 + (x * 3 + 1)] = MAX (d22, r21); 2667 darkness3 [(y * 3 ) * sw3 + (x * 3 + 1)] = MAX (d22, r21);
2405 darkness3 [(y * 3 ) * sw34 + (x * 3 + 2)] = MAX (d22, r31); 2668 darkness3 [(y * 3 ) * sw3 + (x * 3 + 2)] = MAX (d22, r31);
2406 darkness3 [(y * 3 + 1) * sw34 + (x * 3 )] = MAX (d22, r12); 2669 darkness3 [(y * 3 + 1) * sw3 + (x * 3 )] = MAX (d22, r12);
2407 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 */
2408 darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 2)] = MAX (d22, r32); 2671 darkness3 [(y * 3 + 1) * sw3 + (x * 3 + 2)] = MAX (d22, r32);
2409 darkness3 [(y * 3 + 2) * sw34 + (x * 3 )] = MAX (d22, r13); 2672 darkness3 [(y * 3 + 2) * sw3 + (x * 3 )] = MAX (d22, r13);
2410 darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 1)] = MAX (d22, r23); 2673 darkness3 [(y * 3 + 2) * sw3 + (x * 3 + 1)] = MAX (d22, r23);
2411 darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 2)] = MAX (d22, r33); 2674 darkness3 [(y * 3 + 2) * sw3 + (x * 3 + 2)] = MAX (d22, r33);
2412 } 2675 }
2413 2676
2414 free (darkness1); 2677 free (darkness1);
2415 2678
2416 EXTEND (SP, 3); 2679 EXTEND (SP, 3);
2417 PUSHs (sv_2mortal (newSViv (sw34))); 2680 PUSHs (sv_2mortal (newSViv (sw3)));
2418 PUSHs (sv_2mortal (newSViv (sh3))); 2681 PUSHs (sv_2mortal (newSViv (sh3)));
2419 PUSHs (darkness3_sv); 2682 PUSHs (darkness3_sv);
2420} 2683}
2421 2684
2422SV * 2685SV *
2485 else 2748 else
2486 *data++ = 0; 2749 *data++ = 0;
2487 } 2750 }
2488 } 2751 }
2489 2752
2490 /* 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 */
2491 if (data - (uint8_t *)SvPVX (data_sv) != w * h + 5) 2754 if (data - (uint8_t *)SvPVX (data_sv) != w * h + 5)
2492 { 2755 {
2493 SvPOK_only (data_sv); 2756 SvPOK_only (data_sv);
2494 SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv)); 2757 SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
2495 } 2758 }
2496 2759
2497 RETVAL = data_sv; 2760 RETVAL = data_sv;
2498} 2761}
2499 OUTPUT: 2762 OUTPUT:
2500 RETVAL 2763 RETVAL
2501 2764
2502void 2765void
2509 STRLEN len; 2772 STRLEN len;
2510 uint8_t *data, *end; 2773 uint8_t *data, *end;
2511 2774
2512 len = SvLEN (data_sv); 2775 len = SvLEN (data_sv);
2513 SvGROW (data_sv, len + 8); // reserve at least 7+ bytes more 2776 SvGROW (data_sv, len + 8); // reserve at least 7+ bytes more
2514 data = SvPVbyte_nolen (data_sv); 2777 data = (uint8_t *)SvPVbyte_nolen (data_sv);
2515 end = data + len + 8; 2778 end = data + len + 8;
2516 2779
2517 if (len < 5) 2780 if (len < 5)
2518 XSRETURN_EMPTY; 2781 XSRETURN_EMPTY;
2519 2782
2580} 2843}
2581 2844
2582MODULE = Deliantra::Client PACKAGE = DC::RW 2845MODULE = Deliantra::Client PACKAGE = DC::RW
2583 2846
2584DC::RW 2847DC::RW
2585new (SV *class, SV *data_sv) 2848new (SV *klass, SV *data_sv)
2586 CODE: 2849 CODE:
2587{ 2850{
2588 STRLEN datalen; 2851 STRLEN datalen;
2589 char *data = SvPVbyte (data_sv, datalen); 2852 char *data = SvPVbyte (data_sv, datalen);
2590 2853
2592} 2855}
2593 OUTPUT: 2856 OUTPUT:
2594 RETVAL 2857 RETVAL
2595 2858
2596DC::RW 2859DC::RW
2597new_from_file (SV *class, const char *path, const char *mode = "rb") 2860new_from_file (SV *klass, const char *path, const char *mode = "rb")
2598 CODE: 2861 CODE:
2599 RETVAL = SDL_RWFromFile (path, mode); 2862 RETVAL = SDL_RWFromFile (path, mode);
2600 OUTPUT: 2863 OUTPUT:
2601 RETVAL 2864 RETVAL
2602 2865
2620 if (RETVAL < 0) 2883 if (RETVAL < 0)
2621 { 2884 {
2622 RETVAL = Mix_GroupOldest (-1); 2885 RETVAL = Mix_GroupOldest (-1);
2623 2886
2624 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)
2625 XSRETURN_UNDEF; 2893 XSRETURN_UNDEF;
2626 2894 }
2895 else
2627 Mix_HaltChannel (RETVAL); 2896 Mix_HaltChannel (RETVAL);
2628 } 2897 }
2629 2898
2630 Mix_UnregisterAllEffects (RETVAL); 2899 Mix_UnregisterAllEffects (RETVAL);
2631 Mix_Volume (RETVAL, 128); 2900 Mix_Volume (RETVAL, 128);
2632} 2901}
2679void 2948void
2680set_position_r (DC::Channel self, int dx, int dy, int maxdistance) 2949set_position_r (DC::Channel self, int dx, int dy, int maxdistance)
2681 CODE: 2950 CODE:
2682{ 2951{
2683 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));
2684 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;
2685 Mix_SetPosition (self, angle, CLAMP (distance, 0, 255)); 2954 Mix_SetPosition (self, angle, CLAMP (distance, 0, 255));
2686} 2955}
2687 2956
2688void 2957void
2689set_reverse_stereo (DC::Channel self, int flip) 2958set_reverse_stereo (DC::Channel self, int flip)
2692 2961
2693MODULE = Deliantra::Client PACKAGE = DC::MixChunk 2962MODULE = Deliantra::Client PACKAGE = DC::MixChunk
2694 2963
2695PROTOTYPES: DISABLE 2964PROTOTYPES: DISABLE
2696 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
2697DC::MixChunk 2978DC::MixChunk
2698new (SV *class, DC::RW rwops) 2979new (SV *klass, DC::RW rwops)
2699 CODE: 2980 CODE:
2700 RETVAL = Mix_LoadWAV_RW (rwops, 1); 2981 RETVAL = Mix_LoadWAV_RW (rwops, 1);
2701 OUTPUT: 2982 OUTPUT:
2702 RETVAL 2983 RETVAL
2703 2984
2733 OUTPUT: 3014 OUTPUT:
2734 RETVAL 3015 RETVAL
2735 3016
2736MODULE = Deliantra::Client PACKAGE = DC::MixMusic 3017MODULE = Deliantra::Client PACKAGE = DC::MixMusic
2737 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
2738int 3031int
2739volume (int volume = -1) 3032volume (int volume = -1)
2740 PROTOTYPE: ;$ 3033 PROTOTYPE: ;$
2741 CODE: 3034 CODE:
2742 if (items > 0) 3035 if (items > 0)
2753void 3046void
2754halt () 3047halt ()
2755 CODE: 3048 CODE:
2756 Mix_HaltMusic (); 3049 Mix_HaltMusic ();
2757 3050
3051int
3052playing ()
3053 CODE:
3054 RETVAL = Mix_PlayingMusic ();
3055 OUTPUT:
3056 RETVAL
3057
2758DC::MixMusic 3058DC::MixMusic
2759new (SV *class, DC::RW rwops) 3059new (SV *klass, DC::RW rwops)
2760 CODE: 3060 CODE:
2761 RETVAL = Mix_LoadMUS_RW (rwops); 3061 RETVAL = Mix_LoadMUS_RW (rwops);
2762 OUTPUT: 3062 OUTPUT:
2763 RETVAL 3063 RETVAL
2764 3064
2792 } *civ, const_iv[] = { 3092 } *civ, const_iv[] = {
2793# define const_iv(name) { # name, (IV)name } 3093# define const_iv(name) { # name, (IV)name }
2794 const_iv (GL_VENDOR), 3094 const_iv (GL_VENDOR),
2795 const_iv (GL_VERSION), 3095 const_iv (GL_VERSION),
2796 const_iv (GL_EXTENSIONS), 3096 const_iv (GL_EXTENSIONS),
3097 const_iv (GL_MAX_TEXTURE_UNITS),
2797 const_iv (GL_COLOR_MATERIAL), 3098 const_iv (GL_COLOR_MATERIAL),
2798 const_iv (GL_SMOOTH), 3099 const_iv (GL_SMOOTH),
2799 const_iv (GL_FLAT), 3100 const_iv (GL_FLAT),
2800 const_iv (GL_DITHER), 3101 const_iv (GL_DITHER),
2801 const_iv (GL_BLEND), 3102 const_iv (GL_BLEND),
2813 const_iv (GL_ZERO), 3114 const_iv (GL_ZERO),
2814 const_iv (GL_SRC_ALPHA), 3115 const_iv (GL_SRC_ALPHA),
2815 const_iv (GL_DST_ALPHA), 3116 const_iv (GL_DST_ALPHA),
2816 const_iv (GL_ONE_MINUS_SRC_ALPHA), 3117 const_iv (GL_ONE_MINUS_SRC_ALPHA),
2817 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),
2818 const_iv (GL_SRC_ALPHA_SATURATE), 3123 const_iv (GL_SRC_ALPHA_SATURATE),
2819 const_iv (GL_RGB), 3124 const_iv (GL_RGB),
2820 const_iv (GL_RGBA), 3125 const_iv (GL_RGBA),
2821 const_iv (GL_RGBA4), 3126 const_iv (GL_RGBA4),
2822 const_iv (GL_RGBA8), 3127 const_iv (GL_RGBA8),
2890 const_iv (GL_NICEST), 3195 const_iv (GL_NICEST),
2891 const_iv (GL_V2F), 3196 const_iv (GL_V2F),
2892 const_iv (GL_V3F), 3197 const_iv (GL_V3F),
2893 const_iv (GL_T2F_V3F), 3198 const_iv (GL_T2F_V3F),
2894 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),
2895# undef const_iv 3203# undef const_iv
2896 }; 3204 };
2897 3205
2898 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--)
2899 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 3207 newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv));
2900 3208
2901 texture_av = newAV (); 3209 texture_av = newAV ();
2902 AvREAL_off (texture_av); 3210 AvREAL_off (texture_av);
2903} 3211}
2904 3212
2906disable_GL_EXT_blend_func_separate () 3214disable_GL_EXT_blend_func_separate ()
2907 CODE: 3215 CODE:
2908 gl.BlendFuncSeparate = 0; 3216 gl.BlendFuncSeparate = 0;
2909 gl.BlendFuncSeparateEXT = 0; 3217 gl.BlendFuncSeparateEXT = 0;
2910 3218
2911char * 3219void
3220apple_nvidia_bug (int enable)
3221
3222const char *
2912gl_vendor () 3223gl_vendor ()
2913 CODE: 3224 CODE:
2914 RETVAL = (char *)glGetString (GL_VENDOR); 3225 RETVAL = (const char *)glGetString (GL_VENDOR);
2915 OUTPUT: 3226 OUTPUT:
2916 RETVAL 3227 RETVAL
2917 3228
2918char * 3229const char *
2919gl_version () 3230gl_version ()
2920 CODE: 3231 CODE:
2921 RETVAL = (char *)glGetString (GL_VERSION); 3232 RETVAL = (const char *)glGetString (GL_VERSION);
2922 OUTPUT: 3233 OUTPUT:
2923 RETVAL 3234 RETVAL
2924 3235
2925char * 3236const char *
2926gl_extensions () 3237gl_extensions ()
2927 CODE: 3238 CODE:
2928 RETVAL = (char *)glGetString (GL_EXTENSIONS); 3239 RETVAL = (const char *)glGetString (GL_EXTENSIONS);
2929 OUTPUT: 3240 OUTPUT:
2930 RETVAL 3241 RETVAL
2931 3242
2932const char *glGetString (GLenum pname) 3243const char *glGetString (GLenum pname)
3244 CODE:
3245 RETVAL = (const char *)glGetString (pname);
3246 OUTPUT:
3247 RETVAL
2933 3248
2934GLint glGetInteger (GLenum pname) 3249GLint glGetInteger (GLenum pname)
2935 CODE: 3250 CODE:
2936 glGetIntegerv (pname, &RETVAL); 3251 glGetIntegerv (pname, &RETVAL);
2937 OUTPUT: 3252 OUTPUT:
2945 3260
2946int glGetError () 3261int glGetError ()
2947 3262
2948void glFinish () 3263void glFinish ()
2949 3264
3265void glFlush ()
3266
2950void glClear (int mask) 3267void glClear (int mask)
2951 3268
2952void glClearColor (float r, float g, float b, float a = 1.0) 3269void glClearColor (float r, float g, float b, float a = 1.0)
2953 PROTOTYPE: @ 3270 PROTOTYPE: @
2954 3271
2963void glBlendFunc (int sfactor, int dfactor) 3280void glBlendFunc (int sfactor, int dfactor)
2964 3281
2965void glBlendFuncSeparate (int sa, int da, int saa, int daa) 3282void glBlendFuncSeparate (int sa, int da, int saa, int daa)
2966 CODE: 3283 CODE:
2967 gl_BlendFuncSeparate (sa, da, saa, daa); 3284 gl_BlendFuncSeparate (sa, da, saa, daa);
3285
3286# void glBlendEquation (int se)
2968 3287
2969void glDepthMask (int flag) 3288void glDepthMask (int flag)
2970 3289
2971void glLogicOp (int opcode) 3290void glLogicOp (int opcode)
2972 3291
3123 3442
3124void glEndList () 3443void glEndList ()
3125 3444
3126void glCallList (int list) 3445void glCallList (int list)
3127 3446
3447void c_init ()
3448 CODE:
3449 glPixelStorei (GL_PACK_ALIGNMENT , 1);
3450 glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
3451
3128MODULE = Deliantra::Client PACKAGE = DC::UI::Base 3452MODULE = Deliantra::Client PACKAGE = DC::UI::Base
3129 3453
3130PROTOTYPES: DISABLE 3454PROTOTYPES: DISABLE
3131 3455
3132void 3456void
3133find_widget (SV *self, NV x, NV y) 3457find_widget (SV *self, NV x, NV y)
3134 PPCODE: 3458 PPCODE:
3135{ 3459{
3136 if (within_widget (self, x, y)) 3460 if (within_widget (self, x, y))
3137 XPUSHs (self); 3461 XPUSHs (self);
3138} 3462}
3139 3463
3140BOOT: 3464BOOT:
3141{ 3465{
3149 3473
3150void 3474void
3151draw (SV *self) 3475draw (SV *self)
3152 CODE: 3476 CODE:
3153{ 3477{
3154 HV *hv; 3478 HV *hv;
3155 SV **svp; 3479 SV **svp;
3156 NV x, y, w, h; 3480 NV x, y, w, h;
3157 SV *draw_x_sv = GvSV (draw_x_gv); 3481 SV *draw_x_sv = GvSV (draw_x_gv);
3158 SV *draw_y_sv = GvSV (draw_y_gv); 3482 SV *draw_y_sv = GvSV (draw_y_gv);
3159 SV *draw_w_sv = GvSV (draw_w_gv); 3483 SV *draw_w_sv = GvSV (draw_w_gv);
3160 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