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.327 by root, Sun Nov 18 12:01:50 2018 UTC

15 15
16#include "EXTERN.h" 16#include "EXTERN.h"
17#include "perl.h" 17#include "perl.h"
18#include "XSUB.h" 18#include "XSUB.h"
19 19
20#include "flat_hash_map.hpp"
21
20#ifdef _WIN32 22#ifdef _WIN32
21# undef pipe 23# undef pipe
22// microsoft vs. C 24// microsoft vs. C
23# define sqrtf(x) sqrt(x) 25# define sqrtf(x) sqrt(x)
24# define 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>
37#include <bitset>
34 38
35#define USE_RWOPS 1 // for SDL_mixer:LoadMUS_RW 39#define USE_RWOPS 1 // for SDL_mixer:LoadMUS_RW
36 40
37#include <SDL.h> 41#include <SDL.h>
38#include <SDL_thread.h> 42#include <SDL_thread.h>
42#include <SDL_opengl.h> 46#include <SDL_opengl.h>
43 47
44/* work around os x broken headers */ 48/* work around os x broken headers */
45#ifdef __MACOSX__ 49#ifdef __MACOSX__
46typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); 50typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
51typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
52typedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t);
47#endif 53#endif
48 54
49#define PANGO_ENABLE_BACKEND 55#define PANGO_ENABLE_BACKEND
50#define G_DISABLE_CAST_CHECKS 56#define G_DISABLE_CAST_CHECKS
51 57
52#include <glib/gmacros.h> 58#include <glib.h>
53 59
54#include <pango/pango.h> 60#include <pango/pango.h>
55 61
56#ifndef PANGO_VERSION_CHECK 62#ifndef PANGO_VERSION_CHECK
57# define PANGO_VERSION_CHECK(a,b,c) 0 63# define PANGO_VERSION_CHECK(a,b,c) 0
81#define expect_false(expr) expect ((expr) != 0, 0) 87#define expect_false(expr) expect ((expr) != 0, 0)
82#define expect_true(expr) expect ((expr) != 0, 1) 88#define expect_true(expr) expect ((expr) != 0, 1)
83 89
84#define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, object replacement character */ 90#define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, object replacement character */
85 91
92/* this is used as fow flag as well, so has to have a different value */
93/* then anything that is computed by incoming darkness */
86#define FOW_DARKNESS 32 94#define FOW_DARKNESS 50
95#define DARKNESS_ADJUST(n) (n)
87 96
88#define MAP_EXTEND_X 32 97#define MAP_EXTEND_X 32
89#define MAP_EXTEND_Y 512 98#define MAP_EXTEND_Y 512
90 99
91#define MIN_FONT_HEIGHT 10 100#define MIN_FONT_HEIGHT 10
92 101
93/* mask out modifiers we are not interested in */ 102/* mask out modifiers we are not interested in */
94#define MOD_MASK (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_META) 103#define MOD_MASK (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_META)
95 104
96#define KMOD_LRAM 0x10000 // our extension 105#define KMOD_LRAM 0x10000 // our extension
106
107#define TEXID_SPEECH 1
108#define TEXID_NOFACE 2
109
110static char *
111fast_sv_grow (SV *sv, STRLEN need)
112{
113 STRLEN len = SvLEN (sv);
114 STRLEN want = SvCUR (sv) + need;
115
116 if (expect_false (len < want))
117 {
118 do
119 len *= 2;
120 while (len < want);
121
122 sv_grow (sv, len);
123 }
124
125 SvCUR_set (sv, want);
126 return SvEND (sv) - need;
127}
97 128
98static AV *texture_av; 129static AV *texture_av;
99 130
100static struct 131static struct
101{ 132{
158{ 189{
159 GSList *attrs = run->item->analysis.extra_attrs; 190 GSList *attrs = run->item->analysis.extra_attrs;
160 191
161 while (attrs) 192 while (attrs)
162 { 193 {
163 PangoAttribute *attr = attrs->data; 194 PangoAttribute *attr = (PangoAttribute *)attrs->data;
164 195
165 if (attr->klass->type == PANGO_ATTR_SHAPE) 196 if (attr->klass->type == PANGO_ATTR_SHAPE)
166 return 1; 197 return 1;
167 198
168 attrs = attrs->next; 199 attrs = attrs->next;
169 } 200 }
170 201
171 return 0; 202 return 0;
172} 203}
173 204
174typedef struct cf_layout { 205struct cf_layout {
175 PangoLayout *pl; 206 PangoLayout *pl;
176 float r, g, b, a; // default color for rgba mode 207 float r, g, b, a; // default color for rgba mode
177 int base_height; 208 int base_height;
178 DC__Font font; 209 DC__Font font;
179 rc_t *rc; 210 rc_t rc;
180} *DC__Layout; 211};
212
213typedef cf_layout *DC__Layout;
181 214
182static DC__Font default_font; 215static DC__Font default_font;
183static PangoContext *opengl_context; 216static PangoContext *opengl_context;
184static PangoFontMap *opengl_fontmap; 217static PangoFontMap *opengl_fontmap;
185 218
186static void 219static void
187substitute_func (FcPattern *pattern, gpointer data) 220substitute_func (FcPattern *pattern, gpointer data)
188{ 221{
189 FcPatternAddBool (pattern, FC_HINTING, 1); 222 FcPatternAddBool (pattern, FC_HINTING, 1);
190#ifdef FC_HINT_STYLE 223#ifdef FC_HINT_STYLE
191 FcPatternAddBool (pattern, FC_HINT_STYLE, FC_HINT_FULL); 224 FcPatternAddInteger (pattern, FC_HINT_STYLE, FC_HINT_FULL);
192#endif 225#endif
193 FcPatternAddBool (pattern, FC_AUTOHINT, 0); 226 FcPatternAddBool (pattern, FC_AUTOHINT, 0);
194} 227}
195 228
196static void 229static void
226} 259}
227 260
228typedef uint16_t tileid; 261typedef uint16_t tileid;
229typedef uint16_t faceid; 262typedef uint16_t faceid;
230 263
231typedef struct { 264struct maptex
265{
232 GLuint name; 266 GLuint name;
233 int w, h; 267 int w, h;
234 float s, t; 268 float s, t;
235 uint8_t r, g, b, a; 269 uint8_t r, g, b, a;
236 tileid smoothtile; 270 tileid smoothtile;
237 uint8_t smoothlevel; 271 uint8_t smoothlevel;
238} maptex; 272 uint8_t unused; /* set to zero on use */
273};
239 274
240typedef struct { 275struct mapcell
276{
241 uint32_t player; 277 uint32_t player;
242 tileid tile[3]; 278 tileid tile[3];
243 uint16_t darkness; 279 uint16_t darkness;
244 uint8_t stat_width, stat_hp, flags, smoothmax; 280 uint8_t stat_width, stat_hp, flags, smoothmax;
245} mapcell; 281};
246 282
247typedef struct { 283struct maprow
284{
248 int32_t c0, c1; 285 int32_t c0, c1;
249 mapcell *col; 286 mapcell *col;
250} maprow; 287};
251 288
252typedef struct map { 289struct mapgrid {
253 int x, y, w, h; 290 int x, y, w, h;
254 int ox, oy; /* offset to virtual global coordinate system */ 291 int ox, oy; /* offset to virtual global coordinate system */
255 int faces; tileid *face2tile; // [faceid] 292 std::vector<tileid> tile;
256 int texs; maptex *tex; // [tileid] 293 std::vector<maptex> tex;
257 294
258 int32_t rows; 295 int32_t rows;
259 maprow *row; 296 maprow *row;
260} *DC__Map; 297
298 ~mapgrid ()
299 {
300 clear_cells ();
301 }
302
303 void clear_cells ();
304};
305
306typedef mapgrid *DC__Map;
261 307
262static char * 308static char *
263prepend (char *ptr, int sze, int inc) 309prepend (char *ptr, int sze, int inc)
264{ 310{
265 char *p; 311 char *p;
282} 328}
283 329
284#define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type)) 330#define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
285#define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type)) 331#define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
286 332
287static void
288need_facenum (struct map *self, faceid face)
289{
290 while (self->faces <= face)
291 {
292 Append (tileid, self->face2tile, self->faces, self->faces);
293 self->faces *= 2;
294 }
295}
296
297static void
298need_texid (struct map *self, int texid)
299{
300 while (self->texs <= texid)
301 {
302 Append (maptex, self->tex, self->texs, self->texs);
303 self->texs *= 2;
304 }
305}
306
307static maprow * 333static maprow *
308map_get_row (DC__Map self, int y) 334map_get_row (mapgrid *self, int y)
309{ 335{
310 if (0 > y) 336 if (0 > y)
311 { 337 {
312 int extend = - y + MAP_EXTEND_Y; 338 int extend = - y + MAP_EXTEND_Y;
313 Prepend (maprow, self->row, self->rows, extend); 339 Prepend (maprow, self->row, self->rows, extend);
351 377
352 return row->col + (x - row->c0); 378 return row->col + (x - row->c0);
353} 379}
354 380
355static mapcell * 381static mapcell *
356map_get_cell (DC__Map self, int x, int y) 382map_get_cell (mapgrid *self, int x, int y)
357{ 383{
358 return row_get_cell (map_get_row (self, y), x); 384 return row_get_cell (map_get_row (self, y), x);
359} 385}
360 386
361static void 387void mapgrid::clear_cells ()
362map_clear (DC__Map self)
363{ 388{
364 int r; 389 int r;
365 390
366 for (r = 0; r < self->rows; r++) 391 for (r = 0; r < rows; r++)
367 Safefree (self->row[r].col); 392 Safefree (row[r].col);
368 393
369 Safefree (self->row); 394 Safefree (row);
370 395
371 self->x = 0; 396 x = 0;
372 self->y = 0; 397 y = 0;
373 self->ox = 0; 398 ox = 0;
374 self->oy = 0; 399 oy = 0;
375 self->row = 0; 400 row = 0;
376 self->rows = 0; 401 rows = 0;
377} 402}
378 403
379#define CELL_CLEAR(cell) \ 404#define CELL_CLEAR(cell) \
380 do { \ 405 do { \
381 if ((cell)->player) \ 406 if ((cell)->player) \
385 (cell)->flags = 0; \ 410 (cell)->flags = 0; \
386 (cell)->player = 0; \ 411 (cell)->player = 0; \
387 } while (0) 412 } while (0)
388 413
389static void 414static void
390map_blank (DC__Map self, int x0, int y0, int w, int h) 415map_blank (mapgrid *self, int x0, int y0, int w, int h)
391{ 416{
392 int x, y; 417 int x, y;
393 maprow *row; 418 maprow *row;
394 mapcell *cell; 419 mapcell *cell;
395 420
412 CELL_CLEAR (cell); 437 CELL_CLEAR (cell);
413 } 438 }
414 } 439 }
415} 440}
416 441
417typedef struct { 442struct smooth_key
443{
418 tileid tile; 444 tileid tile;
419 uint8_t x, y, level; 445 uint8_t x, y, level;
420} smooth_key; 446
447 bool operator == (const smooth_key &o) const
448 {
449 return tile == o.tile && x == o.x && y == o.y && level == o.level;
450 }
451};
452
453typedef ska::flat_hash_map<smooth_key, IV> smooth_hash;
454
455namespace std {
456 template <>
457 struct hash<smooth_key>
458 {
459 size_t operator () (const smooth_key &v) const
460 {
461 return v.tile + (v.x << 8) + (v.y << 16) + (v.level << 24);
462 }
463 };
464}
421 465
422static void 466static void
423smooth_or_bits (HV *hv, smooth_key *key, IV bits) 467smooth_or_bits (smooth_hash &h, smooth_key &key, IV bits)
424{ 468{
425 SV **sv = hv_fetch (hv, (char *)key, sizeof (*key), 1); 469 auto &&it = h.find (key);
426 470
427 if (SvIOK (*sv)) 471 if (it == h.end ())
428 SvIV_set (*sv, SvIVX (*sv) | bits); 472 h.insert (std::make_pair (key, bits));
429 else 473 else
430 sv_setiv (*sv, bits); 474 it->second |= bits;
431} 475}
432 476
433static void 477static void
434music_finished (void) 478music_finished (void)
435{ 479{
452 ev.code = 1; 496 ev.code = 1;
453 ev.data1 = (void *)(long)channel; 497 ev.data1 = (void *)(long)channel;
454 ev.data2 = 0; 498 ev.data2 = 0;
455 499
456 SDL_PushEvent ((SDL_Event *)&ev); 500 SDL_PushEvent ((SDL_Event *)&ev);
501}
502
503// approximately divide by 255
504static unsigned int
505div255 (unsigned int n)
506{
507 return (n + (n >> 8)) >> 8;
457} 508}
458 509
459static unsigned int 510static unsigned int
460minpot (unsigned int n) 511minpot (unsigned int n)
461{ 512{
544 595
545 return mod; 596 return mod;
546} 597}
547 598
548static void 599static void
549deliantra_main () 600deliantra_main (SV *real_main)
550{ 601{
551 char *argv[] = { 0 }; 602 dSP;
552 call_argv ("::main", G_DISCARD | G_VOID, argv); 603
604 PUSHMARK (SP);
605 call_sv (real_main, G_DISCARD | G_VOID);
553} 606}
554 607
555#ifdef __MACOSX__ 608#ifdef __MACOSX__
609 static SV *real_main;
610
556 /* to due surprising braindamage on the side of SDL design, we 611 /* to due surprising braindamage on the side of SDL design, we
557 * do some mind-boggling hack here: SDL requires a custom main() 612 * 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, 613 * 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, 614 * due to shared library magic, calls -lSDLmain's main, not perl's main,
560 * and which calls our main (== SDL_main) back. 615 * and which calls our main (== SDL_main) back.
561 */ 616 */
562 extern C_LINKAGE int 617 extern C_LINKAGE int
563 main (int argc, char *argv[]) 618 main (int argc, char *argv[])
564 { 619 {
565 deliantra_main (); 620 deliantra_main (real_main);
566 } 621 }
567 622
568 #undef main 623 #undef main
569 624
570 extern C_LINKAGE int main (int argc, char *argv[]); 625 extern C_LINKAGE int main (int argc, char *argv[]);
571 626
572 static void 627 static void
573 SDL_braino (void) 628 SDL_main_hack (SV *real_main_)
574 { 629 {
630 real_main = real_main_;
631
575 char *argv[] = { "deliantra client", 0 }; 632 char *argv[] = { "deliantra client", 0 };
576 (main) (1, argv); 633 (main) (1, argv);
577 } 634 }
578#else 635#else
579 static void 636 static void
580 SDL_braino (void) 637 SDL_main_hack (SV *real_main)
581 { 638 {
582 deliantra_main (); 639 deliantra_main (real_main);
583 } 640 }
584#endif 641#endif
585 642
586MODULE = Deliantra::Client PACKAGE = DC 643MODULE = Deliantra::Client PACKAGE = DC
587 644
788 845
789 const_iv (FOW_DARKNESS) 846 const_iv (FOW_DARKNESS)
790# undef const_iv 847# undef const_iv
791 }; 848 };
792 849
793 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) 850 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--)
794 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 851 newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv));
795 852
796 assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK); 853 assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK);
797 assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE); 854 assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE);
798} 855}
799 856
815NV ceil (NV x) 872NV ceil (NV x)
816 873
817IV minpot (UV n) 874IV minpot (UV n)
818 875
819IV popcount (UV n) 876IV popcount (UV n)
877
878NV distance (NV dx, NV dy)
879 CODE:
880 RETVAL = pow (dx * dx + dy * dy, 0.5);
881 OUTPUT:
882 RETVAL
820 883
821void 884void
822pango_init () 885pango_init ()
823 CODE: 886 CODE:
824{ 887{
832#endif 895#endif
833} 896}
834 897
835char *SDL_GetError () 898char *SDL_GetError ()
836 899
837void SDL_braino () 900void SDL_main_hack (SV *real_main)
901 PROTOTYPE: &
838 902
839int SDL_Init (U32 flags) 903int SDL_Init (U32 flags)
840 904
841int SDL_InitSubSystem (U32 flags) 905int SDL_InitSubSystem (U32 flags)
842 906
843void SDL_QuitSubSystem (U32 flags) 907void SDL_QuitSubSystem (U32 flags)
844 908
845void SDL_Quit () 909void SDL_Quit ()
846 910
847int SDL_GL_SetAttribute (int attr, int value) 911int SDL_GL_SetAttribute (int attr, int value)
912 C_ARGS: (SDL_GLattr)attr, value
848 913
849int SDL_GL_GetAttribute (int attr) 914int SDL_GL_GetAttribute (int attr)
850 CODE: 915 CODE:
851 if (SDL_GL_GetAttribute (attr, &RETVAL)) 916 if (SDL_GL_GetAttribute ((SDL_GLattr)attr, &RETVAL))
852 XSRETURN_UNDEF; 917 XSRETURN_UNDEF;
853 OUTPUT: 918 OUTPUT:
854 RETVAL 919 RETVAL
855 920
856void 921void
911 ); 976 );
912 977
913 if (RETVAL) 978 if (RETVAL)
914 { 979 {
915 av_clear (texture_av); 980 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); 981#define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name);
919#include "glfunc.h" 982#include "glfunc.h"
920#undef GL_FUNC 983#undef GL_FUNC
984 if (!gl.ActiveTexture ) gl.ActiveTexture = gl.ActiveTextureARB;
985 if (!gl.MultiTexCoord2f) gl.MultiTexCoord2f = gl.MultiTexCoord2fARB;
921 } 986 }
922} 987}
923 OUTPUT: 988 OUTPUT:
924 RETVAL 989 RETVAL
990
991void
992SDL_WM_SetCaption (const char *title, const char *icon)
925 993
926void 994void
927SDL_GL_SwapBuffers () 995SDL_GL_SwapBuffers ()
928 996
929char * 997char *
930SDL_GetKeyName (int sym) 998SDL_GetKeyName (int sym)
999 C_ARGS: (SDLKey)sym
931 1000
932int 1001int
933SDL_GetAppState () 1002SDL_GetAppState ()
934 1003
935int 1004int
936SDL_GetModState () 1005SDL_GetModState ()
937 1006
1007int
1008SDL_WaitEvent ()
1009 C_ARGS: 0
1010
938void 1011void
1012SDL_PumpEvents ()
1013
1014void
939poll_events () 1015peep_events ()
940 PPCODE: 1016 PPCODE:
941{ 1017{
942 SDL_Event ev; 1018 SDL_Event ev;
943 1019
944 SDL_PumpEvents (); 1020 SDL_PumpEvents ();
1010 1086
1011 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("DC::UI::Event", 1)))); 1087 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("DC::UI::Event", 1))));
1012 } 1088 }
1013} 1089}
1014 1090
1091char *
1092SDL_AudioDriverName ()
1093 CODE:
1094{
1095 char buf [256];
1096 if (!SDL_AudioDriverName (buf, sizeof (buf)))
1097 XSRETURN_UNDEF;
1098
1099 RETVAL = buf;
1100}
1101 OUTPUT:
1102 RETVAL
1103
1015int 1104int
1016Mix_OpenAudio (int frequency = 44100, int format = MIX_DEFAULT_FORMAT, int channels = 2, int chunksize = 4096) 1105Mix_OpenAudio (int frequency = 44100, int format = MIX_DEFAULT_FORMAT, int channels = 2, int chunksize = 4096)
1017 POSTCALL: 1106 POSTCALL:
1018 Mix_HookMusicFinished (music_finished); 1107 Mix_HookMusicFinished (music_finished);
1019 Mix_ChannelFinished (channel_finished); 1108 Mix_ChannelFinished (channel_finished);
1020 1109
1021void 1110void
1022Mix_QuerySpec () 1111Mix_QuerySpec ()
1081add_font (char *file) 1170add_font (char *file)
1082 CODE: 1171 CODE:
1083 RETVAL = FcConfigAppFontAddFile (0, (const FcChar8 *)file); 1172 RETVAL = FcConfigAppFontAddFile (0, (const FcChar8 *)file);
1084 OUTPUT: 1173 OUTPUT:
1085 RETVAL 1174 RETVAL
1175
1176void
1177IMG_Init (int flags = IMG_INIT_JPG | IMG_INIT_PNG)
1178
1179# MIX_INIT_MP3 gives smpeg + libstdc++ + libgcc_s
1180void
1181Mix_Init (int flags = MIX_INIT_MOD | MIX_INIT_OGG)
1086 1182
1087void 1183void
1088load_image_inline (SV *image_) 1184load_image_inline (SV *image_)
1089 ALIAS: 1185 ALIAS:
1090 load_image_file = 1 1186 load_image_file = 1
1136 1232
1137 SDL_LockSurface (surface2); 1233 SDL_LockSurface (surface2);
1138 EXTEND (SP, 6); 1234 EXTEND (SP, 6);
1139 PUSHs (sv_2mortal (newSViv (surface2->w))); 1235 PUSHs (sv_2mortal (newSViv (surface2->w)));
1140 PUSHs (sv_2mortal (newSViv (surface2->h))); 1236 PUSHs (sv_2mortal (newSViv (surface2->h)));
1141 PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch))); 1237 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))); 1238 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
1143 PUSHs (sv_2mortal (newSViv (GL_RGBA))); 1239 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
1144 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE))); 1240 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
1145 SDL_UnlockSurface (surface2); 1241 SDL_UnlockSurface (surface2);
1146 1242
1206#if DEBUG 1302#if DEBUG
1207 VALGRIND_DO_LEAK_CHECK; 1303 VALGRIND_DO_LEAK_CHECK;
1208#endif 1304#endif
1209} 1305}
1210 1306
1307int
1308SvREFCNT (SV *sv)
1309 CODE:
1310 RETVAL = SvREFCNT (sv);
1311 OUTPUT:
1312 RETVAL
1313
1211MODULE = Deliantra::Client PACKAGE = DC::Font 1314MODULE = Deliantra::Client PACKAGE = DC::Font
1212 1315
1213PROTOTYPES: DISABLE 1316PROTOTYPES: DISABLE
1214 1317
1215DC::Font 1318DC::Font
1216new_from_file (SV *class, char *path, int id = 0) 1319new_from_file (SV *klass, char *path, int id = 0)
1217 CODE: 1320 CODE:
1218{ 1321{
1219 int count; 1322 int count;
1220 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count); 1323 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count);
1221 RETVAL = pango_fc_font_description_from_pattern (pattern, 0); 1324 RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
1250 PROTOTYPE: 1353 PROTOTYPE:
1251 CODE: 1354 CODE:
1252 tc_restore (); 1355 tc_restore ();
1253 1356
1254DC::Layout 1357DC::Layout
1255new (SV *class) 1358new (SV *klass)
1256 CODE: 1359 CODE:
1257 New (0, RETVAL, 1, struct cf_layout); 1360 RETVAL = new cf_layout;
1258 1361
1259 RETVAL->pl = pango_layout_new (opengl_context); 1362 RETVAL->pl = pango_layout_new (opengl_context);
1260 RETVAL->r = 1.; 1363 RETVAL->r = 1.;
1261 RETVAL->g = 1.; 1364 RETVAL->g = 1.;
1262 RETVAL->b = 1.; 1365 RETVAL->b = 1.;
1263 RETVAL->a = 1.; 1366 RETVAL->a = 1.;
1264 RETVAL->base_height = MIN_FONT_HEIGHT; 1367 RETVAL->base_height = MIN_FONT_HEIGHT;
1265 RETVAL->font = 0; 1368 RETVAL->font = 0;
1266 RETVAL->rc = rc_alloc ();
1267 1369
1268 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR); 1370 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
1269 layout_update_font (RETVAL); 1371 layout_update_font (RETVAL);
1270 OUTPUT: 1372 OUTPUT:
1271 RETVAL 1373 RETVAL
1272 1374
1273void 1375void
1274DESTROY (DC::Layout self) 1376DESTROY (DC::Layout self)
1275 CODE: 1377 CODE:
1276 g_object_unref (self->pl); 1378 g_object_unref (self->pl);
1277 rc_free (self->rc);
1278 Safefree (self); 1379 delete self;
1279 1380
1280void 1381void
1281set_text (DC::Layout self, SV *text_) 1382set_text (DC::Layout self, SV *text_)
1282 CODE: 1383 CODE:
1283{ 1384{
1409 1510
1410void 1511void
1411set_height (DC::Layout self, int base_height) 1512set_height (DC::Layout self, int base_height)
1412 CODE: 1513 CODE:
1413 if (self->base_height != base_height) 1514 if (self->base_height != base_height)
1414 { 1515 {
1415 self->base_height = base_height; 1516 self->base_height = base_height;
1416 layout_update_font (self); 1517 layout_update_font (self);
1417 } 1518 }
1418 1519
1419void 1520void
1537} 1638}
1538 1639
1539void 1640void
1540render (DC::Layout self, float x, float y, int flags = 0) 1641render (DC::Layout self, float x, float y, int flags = 0)
1541 CODE: 1642 CODE:
1542 rc_clear (self->rc); 1643 self->rc.clear ();
1543 pango_opengl_render_layout_subpixel ( 1644 pango_opengl_render_layout_subpixel (
1544 self->pl, 1645 self->pl,
1545 self->rc, 1646 &self->rc,
1546 x * PANGO_SCALE, y * PANGO_SCALE, 1647 x * PANGO_SCALE, y * PANGO_SCALE,
1547 self->r, self->g, self->b, self->a, 1648 self->r, self->g, self->b, self->a,
1548 flags 1649 flags
1549 ); 1650 );
1550 // we assume that context_change actually clears/frees stuff 1651 // we assume that context_change actually clears/frees stuff
1561 gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 1662 gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1562 GL_ONE , GL_ONE_MINUS_SRC_ALPHA); 1663 GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1563 glEnable (GL_ALPHA_TEST); 1664 glEnable (GL_ALPHA_TEST);
1564 glAlphaFunc (GL_GREATER, 7.f / 255.f); 1665 glAlphaFunc (GL_GREATER, 7.f / 255.f);
1565 1666
1566 rc_draw (self->rc); 1667 self->rc.draw ();
1567 1668
1568 glDisable (GL_ALPHA_TEST); 1669 glDisable (GL_ALPHA_TEST);
1569 glDisable (GL_BLEND); 1670 glDisable (GL_BLEND);
1570 glDisable (GL_TEXTURE_2D); 1671 glDisable (GL_TEXTURE_2D);
1571} 1672}
1646 glDisable (GL_ALPHA_TEST); 1747 glDisable (GL_ALPHA_TEST);
1647 glDisable (GL_BLEND); 1748 glDisable (GL_BLEND);
1648 } 1749 }
1649} 1750}
1650 1751
1752void
1753draw_fow_texture (float intensity, int hidden_tex, int name1, uint8_t *data1, float s, float t, int w, int h, float blend = 0.f, int dx = 0, int dy = 0, int name2 = 0, uint8_t *data2 = data1)
1754 PROTOTYPE: @
1755 CODE:
1756{
1757 glEnable (GL_BLEND);
1758 glBlendFunc (intensity ? GL_SRC_ALPHA : GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1759 glEnable (GL_TEXTURE_2D);
1760 glBindTexture (GL_TEXTURE_2D, name1);
1761
1762 glColor3f (intensity, intensity, intensity);
1763 glPushMatrix ();
1764 glScalef (1./3, 1./3, 1.);
1765
1766 if (blend > 0.f)
1767 {
1768 float dx3 = dx * -3.f / w;
1769 float dy3 = dy * -3.f / h;
1770 GLfloat env_color[4] = { 0., 0., 0., blend };
1771
1772 /* interpolate the two shadow textures */
1773 /* stage 0 == rgb(glcolor) + alpha(t0) */
1774 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1775
1776 /* stage 1 == rgb(glcolor) + alpha(interpolate t0, t1, texenv) */
1777 gl.ActiveTexture (GL_TEXTURE1);
1778 glEnable (GL_TEXTURE_2D);
1779 glBindTexture (GL_TEXTURE_2D, name2);
1780 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
1781
1782 /* rgb == rgb(glcolor) */
1783 glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
1784 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
1785 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
1786
1787 /* alpha = interpolate t0, t1 by env_alpha */
1788 glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, env_color);
1789
1790 glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_INTERPOLATE);
1791 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
1792 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
1793
1794 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS);
1795 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
1796
1797 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_CONSTANT);
1798 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA);
1799
1800 glBegin (GL_QUADS);
1801 gl.MultiTexCoord2f (GL_TEXTURE0, 0, 0); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 , dy3 ); glVertex2i (0, 0);
1802 gl.MultiTexCoord2f (GL_TEXTURE0, 0, t); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 , dy3 + t); glVertex2i (0, h);
1803 gl.MultiTexCoord2f (GL_TEXTURE0, s, t); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 + s, dy3 + t); glVertex2i (w, h);
1804 gl.MultiTexCoord2f (GL_TEXTURE0, s, 0); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 + s, dy3 ); glVertex2i (w, 0);
1805 glEnd ();
1806
1807 glDisable (GL_TEXTURE_2D);
1808 gl.ActiveTexture (GL_TEXTURE0);
1809 }
1810 else
1811 {
1812 /* simple blending of one texture, also opengl <1.3 path */
1813 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1814
1815 glBegin (GL_QUADS);
1816 glTexCoord2f (0, 0); glVertex2f (0, 0);
1817 glTexCoord2f (0, t); glVertex2f (0, h);
1818 glTexCoord2f (s, t); glVertex2f (w, h);
1819 glTexCoord2f (s, 0); glVertex2f (w, 0);
1820 glEnd ();
1821 }
1822
1823 /* draw ?-marks or equivalent, this is very clumsy code :/ */
1824 {
1825 int x, y;
1826 int dx3 = dx * 3;
1827 int dy3 = dy * 3;
1828
1829 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1830 glBindTexture (GL_TEXTURE_2D, hidden_tex);
1831 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1832 glTranslatef (-1., -1., 0);
1833 glBegin (GL_QUADS);
1834
1835 for (y = 1; y < h; y += 3)
1836 {
1837 int y1 = y - dy3;
1838 int y1valid = y1 >= 0 && y1 < h;
1839
1840 for (x = 1; x < w; x += 3)
1841 {
1842 int x1 = x - dx3;
1843 uint8_t h1 = data1 [x + y * w] == DARKNESS_ADJUST (255 - FOW_DARKNESS);
1844 uint8_t h2;
1845
1846 if (y1valid && x1 >= 0 && x1 < w)
1847 h2 = data2 [x1 + y1 * w] == DARKNESS_ADJUST (255 - FOW_DARKNESS);
1848 else
1849 h2 = 1; /* out of range == invisible */
1850
1851 if (h1 || h2)
1852 {
1853 float alpha = h1 == h2 ? 1.f : h1 ? 1.f - blend : blend;
1854 glColor4f (1., 1., 1., alpha);
1855
1856 glTexCoord2f (0, 0.); glVertex2i (x , y );
1857 glTexCoord2f (0, 1.); glVertex2i (x , y + 3);
1858 glTexCoord2f (1, 1.); glVertex2i (x + 3, y + 3);
1859 glTexCoord2f (1, 0.); glVertex2i (x + 3, y );
1860 }
1861 }
1862 }
1863 }
1864
1865 glEnd ();
1866
1867 glPopMatrix ();
1868
1869 glDisable (GL_TEXTURE_2D);
1870 glDisable (GL_BLEND);
1871}
1872
1651IV texture_valid_2d (GLint internalformat, GLsizei w, GLsizei h, GLenum format, GLenum type) 1873IV texture_valid_2d (GLint internalformat, GLsizei w, GLsizei h, GLenum format, GLenum type)
1652 CODE: 1874 CODE:
1653{ 1875{
1654 GLint width; 1876 GLint width;
1655 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, internalformat, w, h, 0, format, type, 0); 1877 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, internalformat, w, h, 0, format, type, 0);
1662MODULE = Deliantra::Client PACKAGE = DC::Map 1884MODULE = Deliantra::Client PACKAGE = DC::Map
1663 1885
1664PROTOTYPES: DISABLE 1886PROTOTYPES: DISABLE
1665 1887
1666DC::Map 1888DC::Map
1667new (SV *class) 1889new (SV *klass)
1668 CODE: 1890 CODE:
1669 New (0, RETVAL, 1, struct map); 1891 RETVAL = new mapgrid;
1670 RETVAL->x = 0; 1892 RETVAL->x = 0;
1671 RETVAL->y = 0; 1893 RETVAL->y = 0;
1672 RETVAL->w = 0; 1894 RETVAL->w = 0;
1673 RETVAL->h = 0; 1895 RETVAL->h = 0;
1674 RETVAL->ox = 0; 1896 RETVAL->ox = 0;
1675 RETVAL->oy = 0; 1897 RETVAL->oy = 0;
1676 RETVAL->faces = 8192; Newz (0, RETVAL->face2tile, RETVAL->faces, tileid);
1677 RETVAL->texs = 8192; Newz (0, RETVAL->tex , RETVAL->texs , maptex);
1678 RETVAL->rows = 0; 1898 RETVAL->rows = 0;
1679 RETVAL->row = 0; 1899 RETVAL->row = 0;
1680 OUTPUT: 1900 OUTPUT:
1681 RETVAL 1901 RETVAL
1682 1902
1683void 1903void
1684DESTROY (DC::Map self) 1904DESTROY (DC::Map self)
1685 CODE: 1905 CODE:
1686{ 1906{
1687 map_clear (self);
1688 Safefree (self->face2tile);
1689 Safefree (self->tex);
1690 Safefree (self); 1907 delete self;
1691} 1908}
1692 1909
1693void 1910void
1694resize (DC::Map self, int map_width, int map_height) 1911resize (DC::Map self, int map_width, int map_height)
1695 CODE: 1912 CODE:
1697 self->h = map_height; 1914 self->h = map_height;
1698 1915
1699void 1916void
1700clear (DC::Map self) 1917clear (DC::Map self)
1701 CODE: 1918 CODE:
1702 map_clear (self); 1919 self->clear_cells ();
1703 1920
1704void 1921void
1705set_tileid (DC::Map self, int face, int tile) 1922set_tileid (DC::Map self, int face, int tile)
1706 CODE: 1923 CODE:
1707{ 1924{
1708 need_facenum (self, face); self->face2tile [face] = tile; 1925 if (self->tile.size () <= face) self->tile.resize (face + 1);
1709 need_texid (self, tile); 1926 self->tile[face] = tile;
1927 if (self->tex.size () <= tile) self->tex .resize (tile + 1);
1710} 1928}
1711 1929
1712void 1930void
1713set_smooth (DC::Map self, int face, int smooth, int level) 1931set_smooth (DC::Map self, int face, int smooth, int level)
1714 CODE: 1932 CODE:
1715{ 1933{
1716 tileid texid;
1717 maptex *tex;
1718
1719 if (face < 0 || face >= self->faces) 1934 if (face < 0 || face >= self->tile.size ())
1720 return; 1935 return;
1721 1936
1722 if (smooth < 0 || smooth >= self->faces) 1937 if (smooth < 0 || smooth >= self->tile.size ())
1723 return; 1938 return;
1724 1939
1725 texid = self->face2tile [face]; 1940 tileid texid = self->tile[face];
1726 1941
1727 if (!texid) 1942 if (!texid)
1728 return; 1943 return;
1729 1944
1730 tex = self->tex + texid; 1945 maptex &tex = self->tex[texid];
1731 tex->smoothtile = self->face2tile [smooth]; 1946 tex.smoothtile = self->tile[smooth];
1732 tex->smoothlevel = level; 1947 tex.smoothlevel = level;
1733} 1948}
1734 1949
1735void 1950void
1736set_texture (DC::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a) 1951set_texture (DC::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a)
1737 CODE: 1952 CODE:
1738{ 1953{
1739 need_texid (self, texid); 1954 if (self->tex.size () < texid) self->tex.resize (texid + 1);
1740 1955
1741 { 1956 {
1742 maptex *tex = self->tex + texid; 1957 maptex &tex = self->tex[texid];
1743 1958
1744 tex->name = name; 1959 tex.name = name;
1745 tex->w = w; 1960 tex.w = w;
1746 tex->h = h; 1961 tex.h = h;
1747 tex->s = s; 1962 tex.s = s;
1748 tex->t = t; 1963 tex.t = t;
1749 tex->r = r; 1964 tex.r = r;
1750 tex->g = g; 1965 tex.g = g;
1751 tex->b = b; 1966 tex.b = b;
1752 tex->a = a; 1967 tex.a = a;
1753 } 1968 }
1754 1969
1755 // somewhat hackish, but for textures that require it, it really 1970 // somewhat hackish, but for textures that require it, it really
1756 // improves the look, and most others don't suffer. 1971 // improves the look, and most others don't suffer.
1757 glBindTexture (GL_TEXTURE_2D, name); 1972 glBindTexture (GL_TEXTURE_2D, name);
1759 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 1974 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1760 // use uglier nearest interpolation because linear suffers 1975 // use uglier nearest interpolation because linear suffers
1761 // from transparent color bleeding and ugly wrapping effects. 1976 // from transparent color bleeding and ugly wrapping effects.
1762 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1977 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1763} 1978}
1979
1980void
1981expire_textures (DC::Map self, int texid, int count)
1982 PPCODE:
1983 for (; texid < self->tex.size () && count; ++texid, --count)
1984 {
1985 maptex &tex = self->tex[texid];
1986
1987 if (tex.name)
1988 {
1989 if (tex.unused)
1990 {
1991 tex.name = 0;
1992 tex.unused = 0;
1993 XPUSHs (sv_2mortal (newSViv (texid)));
1994 }
1995 else
1996 tex.unused = 1;
1997 }
1998 }
1764 1999
1765int 2000int
1766ox (DC::Map self) 2001ox (DC::Map self)
1767 ALIAS: 2002 ALIAS:
1768 oy = 1 2003 oy = 1
1808 self->y += MAP_EXTEND_Y; 2043 self->y += MAP_EXTEND_Y;
1809 } 2044 }
1810} 2045}
1811 2046
1812SV * 2047SV *
1813map1a_update (DC::Map self, SV *data_, int extmap) 2048map1a_update (DC::Map self, SV *data_)
1814 CODE: 2049 CODE:
1815{ 2050{
1816 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_); 2051 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1817 uint8_t *data_end = (uint8_t *)SvEND (data_); 2052 uint8_t *data_end = (uint8_t *)SvEND (data_);
1818 mapcell *cell; 2053 mapcell *cell;
1839 2074
1840 //TODO: don't trust server data to be in-range(!) 2075 //TODO: don't trust server data to be in-range(!)
1841 2076
1842 if (flags & 8) 2077 if (flags & 8)
1843 { 2078 {
2079 uint8_t ext, cmd;
2080
1844 if (extmap) 2081 do
1845 { 2082 {
1846 uint8_t ext, cmd; 2083 ext = *data++;
2084 cmd = ext & 0x7f;
1847 2085
1848 do 2086 if (cmd < 4)
2087 cell->darkness = 255 - ext * 64 + 1; /* make sure this doesn't collide with FOW_DARKNESS */
2088 else if (cmd == 5) // health
1849 { 2089 {
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; 2090 cell->stat_width = 1;
1858 cell->stat_hp = *data++; 2091 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 } 2092 }
1878 while (ext & 0x80); 2093 else if (cmd == 6) // monster width
2094 cell->stat_width = *data++ + 1;
2095 else if (cmd == 0x47)
2096 {
2097 if (*data == 1) cell->player = data [1];
2098 else if (*data == 2) cell->player = data [2] + (data [1] << 8);
2099 else if (*data == 3) cell->player = data [3] + (data [2] << 8) + (data [1] << 16);
2100 else if (*data == 4) cell->player = data [4] + (data [3] << 8) + (data [2] << 16) + (data [1] << 24);
2101
2102 data += *data + 1;
2103 }
2104 else if (cmd == 8) // cell flags
2105 cell->flags = *data++;
2106 else if (ext & 0x40) // unknown, multibyte => skip
2107 data += *data + 1;
2108 else
2109 data++;
1879 } 2110 }
1880 else 2111 while (ext & 0x80);
1881 cell->darkness = *data++ + 1;
1882 } 2112 }
1883 2113
1884 for (z = 0; z <= 2; ++z) 2114 for (z = 0; z <= 2; ++z)
1885 if (flags & (4 >> z)) 2115 if (flags & (4 >> z))
1886 { 2116 {
1887 faceid face = (data [0] << 8) + data [1]; data += 2; 2117 faceid face = (data[0] << 8) + data[1]; data += 2;
1888 need_facenum (self, face); 2118 if (self->tile.size () <= face) self->tile.resize (face + 1);
1889 cell->tile [z] = self->face2tile [face]; 2119 cell->tile[z] = self->tile[face];
1890 2120
1891 if (cell->tile [z]) 2121 if (cell->tile[z])
1892 { 2122 {
1893 maptex *tex = self->tex + cell->tile [z]; 2123 maptex &tex = self->tex[cell->tile[z]];
2124 tex.unused = 0;
1894 if (!tex->name) 2125 if (!tex.name)
1895 av_push (missing, newSViv (cell->tile [z])); 2126 av_push (missing, newSViv (cell->tile [z]));
1896 2127
1897 if (tex->smoothtile) 2128 if (tex.smoothtile)
1898 { 2129 {
1899 maptex *smooth = self->tex + tex->smoothtile; 2130 maptex &smooth = self->tex[tex.smoothtile];
2131 smooth.unused = 0;
1900 if (!smooth->name) 2132 if (!smooth.name)
1901 av_push (missing, newSViv (tex->smoothtile)); 2133 av_push (missing, newSViv (tex.smoothtile));
1902 } 2134 }
1903 } 2135 }
1904 } 2136 }
1905 } 2137 }
1906 else 2138 else
1932 ? self->row + y 2164 ? self->row + y
1933 : 0; 2165 : 0;
1934 2166
1935 for (x = x0; x < x1; x++) 2167 for (x = x0; x < x1; x++)
1936 { 2168 {
1937 int r = 32, g = 32, b = 32, a = 192; 2169 unsigned int r = 32, g = 32, b = 32, a = 192;
1938 2170
1939 if (row && row->c0 <= x && x < row->c1) 2171 if (row && row->c0 <= x && x < row->c1)
1940 { 2172 {
1941 mapcell *cell = row->col + (x - row->c0); 2173 mapcell *cell = row->col + (x - row->c0);
1942 2174
1944 { 2176 {
1945 maptex tex = self->tex [cell->tile [z]]; 2177 maptex tex = self->tex [cell->tile [z]];
1946 int a0 = 255 - tex.a; 2178 int a0 = 255 - tex.a;
1947 int a1 = tex.a; 2179 int a1 = tex.a;
1948 2180
1949 r = (r * a0 + tex.r * a1) / 255; 2181 r = div255 (r * a0 + tex.r * a1);
1950 g = (g * a0 + tex.g * a1) / 255; 2182 g = div255 (g * a0 + tex.g * a1);
1951 b = (b * a0 + tex.b * a1) / 255; 2183 b = div255 (b * a0 + tex.b * a1);
1952 a = (a * a0 + tex.a * a1) / 255; 2184 a = div255 (a * a0 + tex.a * a1);
1953 } 2185 }
1954 } 2186 }
1955 2187
1956 *map++ = (r ) 2188 *map++ = (r )
1957 | (g << 8) 2189 | (g << 8)
1958 | (b << 16) 2190 | (b << 16)
1959 | (a << 24); 2191 | (a << 24);
1960 } 2192 }
1961 } 2193 }
1962 2194
1963 RETVAL = map_sv; 2195 RETVAL = map_sv;
1964} 2196}
1965 OUTPUT: 2197 OUTPUT:
1966 RETVAL 2198 RETVAL
1967 2199
1968void 2200void
1969draw (DC::Map self, int mx, int my, int sw, int sh, int T, U32 player = 0xffffffff, int sdx = 0, int sdy = 0) 2201draw (DC::Map self, int mx, int my, int sw, int sh, int Tw, int Th, U32 player = 0xffffffff, int sdx = 0, int sdy = 0)
1970 CODE: 2202 CODE:
1971{ 2203{
1972 int x, y, z; 2204 int x, y, z;
1973 2205
1974 HV *smooth = (HV *)sv_2mortal ((SV *)newHV ());
1975 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) 2206 static uint8_t smooth_max[256][256]; // egad, fast and wasteful on memory (64k), also, static!
1977 smooth_key skey;
1978 int pl_x, pl_y; 2207 int pl_x, pl_y;
1979 maptex pl_tex; 2208 maptex pl_tex;
1980 rc_t *rc = rc_alloc (); 2209 rc_t rc;
2210 rc_t rc_ov;
1981 rc_key_t key; 2211 rc_key_t key;
1982 rc_array_t *arr; 2212 rc_t::array_t *arr;
1983 2213
1984 pl_tex.name = 0; 2214 pl_tex.name = 0;
1985 2215
1986 // thats current max. sorry. 2216 // that's current max. sorry.
1987 if (sw > 255) sw = 255; 2217 if (sw > 255) sw = 255;
1988 if (sh > 255) sh = 255; 2218 if (sh > 255) sh = 255;
1989
1990 // clear key, in case of extra padding
1991 memset (&skey, 0, sizeof (skey));
1992 2219
1993 memset (&key, 0, sizeof (key)); 2220 memset (&key, 0, sizeof (key));
1994 key.r = 255; 2221 key.r = 255;
1995 key.g = 255; 2222 key.g = 255;
1996 key.b = 255; 2223 key.b = 255;
1997 key.a = 255; 2224 key.a = 255;
1998 key.mode = GL_QUADS; 2225 key.mode = GL_QUADS;
1999 key.format = GL_T2F_V3F; 2226 key.format = GL_T2F_V3F;
2000 key.texname = -1;
2001 2227
2002 mx += self->x; 2228 mx += self->x;
2003 my += self->y; 2229 my += self->y;
2004 2230
2005 // first pass: determine smooth_max 2231 // first pass: determine smooth_max
2006 // rather ugly, if you ask me 2232 // rather ugly, if you ask me
2007 // could also be stored inside mapcell and updated on change 2233 // could also be stored inside mapcell and updated on change
2008 memset (smooth_max, 0, sizeof (smooth_max)); 2234 memset (smooth_max, 0, sizeof (smooth_max[0]) * (sh + 1));
2009 2235
2010 for (y = 0; y < sh; y++) 2236 for (y = 0; y < sh; y++)
2011 if (0 <= y + my && y + my < self->rows) 2237 if (0 <= y + my && y + my < self->rows)
2012 { 2238 {
2013 maprow *row = self->row + (y + my); 2239 maprow *row = self->row + (y + my);
2028 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2254 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2029 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 2255 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2030 2256
2031 for (z = 0; z <= 2; z++) 2257 for (z = 0; z <= 2; z++)
2032 { 2258 {
2033 memset (smooth_level, 0, sizeof (smooth_level)); 2259 std::bitset<256> smooth_level; // one bit for every possible smooth level
2260 smooth_key skey;
2261 smooth_hash smooth;
2262 key.texname = -1;
2034 2263
2035 for (y = 0; y < sh; y++) 2264 for (y = 0; y < sh; y++)
2036 if (0 <= y + my && y + my < self->rows) 2265 if (0 <= y + my && y + my < self->rows)
2037 { 2266 {
2038 maprow *row = self->row + (y + my); 2267 maprow *row = self->row + (y + my);
2044 tileid tile = cell->tile [z]; 2273 tileid tile = cell->tile [z];
2045 2274
2046 if (tile) 2275 if (tile)
2047 { 2276 {
2048 maptex tex = self->tex [tile]; 2277 maptex tex = self->tex [tile];
2049 int px = (x + 1) * T - tex.w; 2278 int px, py;
2050 int py = (y + 1) * T - tex.h;
2051 2279
2052 if (key.texname != tex.name) 2280 if (key.texname != tex.name)
2053 { 2281 {
2282 self->tex [tile].unused = 0;
2283
2054 if (!tex.name) 2284 if (!tex.name)
2055 tex = self->tex [2]; /* missing, replace by noface */ 2285 tex = self->tex [TEXID_NOFACE]; /* missing, replace by noface */
2056 2286
2057 key.texname = tex.name; 2287 key.texname = tex.name;
2058 arr = rc_array (rc, &key); 2288 arr = &rc.array (key);
2059 } 2289 }
2290
2291 px = (x + 1) * Th - tex.w;
2292 py = (y + 1) * Tw - tex.h;
2060 2293
2061 if (expect_false (cell->player == player) && expect_false (z == 2)) 2294 if (expect_false (cell->player == player) && expect_false (z == 2))
2062 { 2295 {
2063 pl_x = px; 2296 pl_x = px;
2064 pl_y = py; 2297 pl_y = py;
2065 pl_tex = tex; 2298 pl_tex = tex;
2066 continue; 2299 continue;
2067 } 2300 }
2068 2301
2069 rc_t2f_v3f (arr, 0 , 0 , px , py , 0); 2302 arr->t2f_v3f (0 , 0 , px , py , 0);
2070 rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0); 2303 arr->t2f_v3f (0 , tex.t, px , py + tex.h, 0);
2071 rc_t2f_v3f (arr, tex.s, tex.t, px + tex.w, py + tex.h, 0); 2304 arr->t2f_v3f (tex.s, tex.t, px + tex.w, py + tex.h, 0);
2072 rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0); 2305 arr->t2f_v3f (tex.s, 0 , px + tex.w, py , 0);
2073
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 2306
2099 // update smooth hash 2307 // update smooth hash
2100 if (tex.smoothtile) 2308 if (tex.smoothtile)
2101 { 2309 {
2102 skey.tile = tex.smoothtile; 2310 skey.tile = tex.smoothtile;
2103 skey.level = tex.smoothlevel; 2311 skey.level = tex.smoothlevel;
2104 2312
2105 smooth_level [tex.smoothlevel >> 5] |= ((uint32_t)1) << (tex.smoothlevel & 31); 2313 smooth_level[tex.smoothlevel] = 1;
2106 2314
2107 // add bits to current tile and all neighbours. skey.x|y is 2315 // add bits to current tile and all neighbours. skey.x|y is
2108 // shifted +1|+1 so we always stay positive. 2316 // shifted +1|+1 so we always stay positive.
2109 2317
2110 // bits is ___n cccc CCCC bbbb 2318 // bits is ___n cccc CCCC bbbb
2118 2326
2119 // corners: 1 ┛· 2 ·┗ 4 ·· 8 ·· 2327 // corners: 1 ┛· 2 ·┗ 4 ·· 8 ··
2120 // ·· ·· ·┏ ┓· 2328 // ·· ·· ·┏ ┓·
2121 2329
2122 // full tile 2330 // full tile
2123 skey.x = x + 1; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x1000); 2331 skey.x = x + 1; skey.y = y + 1; smooth_or_bits (smooth, skey, 0x1000);
2124 2332
2125 // borders 2333 // borders
2126 skey.x = x + 2; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0091); 2334 skey.x = x + 2; skey.y = y + 1; smooth_or_bits (smooth, skey, 0x0091);
2127 skey.x = x + 1; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0032); 2335 skey.x = x + 1; skey.y = y + 2; smooth_or_bits (smooth, skey, 0x0032);
2128 skey.x = x ; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0064); 2336 skey.x = x ; skey.y = y + 1; smooth_or_bits (smooth, skey, 0x0064);
2129 skey.x = x + 1; skey.y = y ; smooth_or_bits (smooth, &skey, 0x00c8); 2337 skey.x = x + 1; skey.y = y ; smooth_or_bits (smooth, skey, 0x00c8);
2130 2338
2131 // corners 2339 // corners
2132 skey.x = x + 2; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0100); 2340 skey.x = x + 2; skey.y = y + 2; smooth_or_bits (smooth, skey, 0x0100);
2133 skey.x = x ; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0200); 2341 skey.x = x ; skey.y = y + 2; smooth_or_bits (smooth, skey, 0x0200);
2134 skey.x = x ; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0400); 2342 skey.x = x ; skey.y = y ; smooth_or_bits (smooth, skey, 0x0400);
2135 skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0800); 2343 skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, skey, 0x0800);
2344 }
2345 }
2346
2347 if (expect_false (z == 2) && expect_false (cell->flags))
2348 {
2349 // overlays such as the speech bubble, probably more to come
2350 if (cell->flags & 1)
2351 {
2352 rc_key_t key_ov = key;
2353 maptex tex = self->tex[TEXID_SPEECH];
2354 int px = x * Tw + Tw * 2 / 32;
2355 int py = y * Th - Th * 6 / 32;
2356
2357 key_ov.texname = tex.name;
2358 rc_t::array_t &arr = rc_ov.array (key_ov);
2359
2360 arr.t2f_v3f (0 , 0 , px , py , 0);
2361 arr.t2f_v3f (0 , tex.t, px , py + Th, 0);
2362 arr.t2f_v3f (tex.s, tex.t, px + Tw, py + Th, 0);
2363 arr.t2f_v3f (tex.s, 0 , px + Tw, py , 0);
2136 } 2364 }
2137 } 2365 }
2138 } 2366 }
2139 } 2367 }
2140 2368
2141 rc_draw (rc); 2369 rc.draw ();
2142 rc_clear (rc); 2370 rc.clear ();
2143 2371
2144 // go through all smoothlevels, lowest to highest, then draw. 2372 // go through all smoothlevels, lowest to highest, then draw.
2145 // this is basically counting sort 2373 // this is basically counting sort
2146 { 2374 {
2147 int w, b; 2375 int w, b;
2148 2376
2149 glEnable (GL_TEXTURE_2D); 2377 glEnable (GL_TEXTURE_2D);
2150 glBegin (GL_QUADS); 2378 glBegin (GL_QUADS);
2151 for (w = 0; w < 256 / 32; ++w) 2379 for (int level = 0; level < smooth_level.size (); ++level)
2380 if (smooth_level[level])
2381 for (auto &&it = smooth.begin (); it != smooth.end (); ++it)
2152 { 2382 {
2153 uint32_t smask = smooth_level [w]; 2383 smooth_key &skey = it->first;
2154 if (smask) 2384 IV bits = it->second;
2155 for (b = 0; b < 32; ++b) 2385
2156 if (smask & (((uint32_t)1) << b)) 2386 if (!(bits & 0x1000)
2387 && skey.level == level
2388 && level > smooth_max [skey.x][skey.y])
2157 { 2389 {
2158 int level = (w << 5) | b; 2390 maptex tex = self->tex [skey.tile];
2391 int px = (((int)skey.x) - 1) * Tw;
2392 int py = (((int)skey.y) - 1) * Th;
2393 int border = bits & 15;
2394 int corner = (bits >> 8) & ~(bits >> 4) & 15;
2395 float dx = tex.s * .0625f; // 16 images/row
2396 float dy = tex.t * .5f ; // 2 images/column
2397
2159 HE *he; 2398 if (tex.name)
2160
2161 hv_iterinit (smooth);
2162 while ((he = hv_iternext (smooth)))
2163 { 2399 {
2164 smooth_key *skey = (smooth_key *)HeKEY (he); 2400 // this time avoiding texture state changes
2165 IV bits = SvIVX (HeVAL (he)); 2401 // save gobs of state changes.
2166 2402 if (key.texname != tex.name)
2167 if (!(bits & 0x1000)
2168 && skey->level == level
2169 && level > smooth_max [skey->x][skey->y])
2170 { 2403 {
2171 maptex tex = self->tex [skey->tile]; 2404 self->tex [skey.tile].unused = 0;
2172 int px = (((int)skey->x) - 1) * T;
2173 int py = (((int)skey->y) - 1) * T;
2174 int border = bits & 15;
2175 int corner = (bits >> 8) & ~(bits >> 4) & 15;
2176 float dx = tex.s * .0625f; // 16 images/row
2177 float dy = tex.t * .5f ; // 2 images/column
2178 2405
2179 if (tex.name)
2180 {
2181 // this time avoiding texture state changes
2182 // save gobs of state changes.
2183 if (key.texname != tex.name)
2184 {
2185 glEnd (); 2406 glEnd ();
2186 glBindTexture (GL_TEXTURE_2D, key.texname = tex.name); 2407 glBindTexture (GL_TEXTURE_2D, key.texname = tex.name);
2187 glBegin (GL_QUADS); 2408 glBegin (GL_QUADS);
2188 } 2409 }
2189 2410
2190 if (border) 2411 if (border)
2191 { 2412 {
2192 float ox = border * dx; 2413 float ox = border * dx;
2193 2414
2194 glTexCoord2f (ox , 0.f ); glVertex2i (px , py ); 2415 glTexCoord2f (ox , 0.f ); glVertex2i (px , py );
2195 glTexCoord2f (ox , dy ); glVertex2i (px , py + T); 2416 glTexCoord2f (ox , dy ); glVertex2i (px , py + Th);
2196 glTexCoord2f (ox + dx, dy ); glVertex2i (px + T, py + T); 2417 glTexCoord2f (ox + dx, dy ); glVertex2i (px + Tw, py + Th);
2197 glTexCoord2f (ox + dx, 0.f ); glVertex2i (px + T, py ); 2418 glTexCoord2f (ox + dx, 0.f ); glVertex2i (px + Tw, py );
2198 } 2419 }
2199 2420
2200 if (corner) 2421 if (corner)
2201 { 2422 {
2202 float ox = corner * dx; 2423 float ox = corner * dx;
2203 2424
2204 glTexCoord2f (ox , dy ); glVertex2i (px , py ); 2425 glTexCoord2f (ox , dy ); glVertex2i (px , py );
2205 glTexCoord2f (ox , dy * 2.f); glVertex2i (px , py + T); 2426 glTexCoord2f (ox , dy * 2.f); glVertex2i (px , py + Th);
2206 glTexCoord2f (ox + dx, dy * 2.f); glVertex2i (px + T, py + T); 2427 glTexCoord2f (ox + dx, dy * 2.f); glVertex2i (px + Tw, py + Th);
2207 glTexCoord2f (ox + dx, dy ); glVertex2i (px + T, py ); 2428 glTexCoord2f (ox + dx, dy ); glVertex2i (px + Tw, py );
2208 }
2209 }
2210 } 2429 }
2211 } 2430 }
2212 } 2431 }
2213 } 2432 }
2214 2433
2215 glEnd (); 2434 glEnd ();
2216 glDisable (GL_TEXTURE_2D); 2435 glDisable (GL_TEXTURE_2D);
2217 key.texname = -1; 2436 key.texname = -1;
2218 } 2437 }
2219
2220 hv_clear (smooth);
2221 } 2438 }
2222 2439
2223 if (pl_tex.name) 2440 if (pl_tex.name)
2224 { 2441 {
2225 maptex tex = pl_tex; 2442 maptex tex = pl_tex;
2226 int px = pl_x + sdx; 2443 int px = pl_x + sdx;
2227 int py = pl_y + sdy; 2444 int py = pl_y + sdy;
2228 2445
2229 key.texname = tex.name; 2446 key.texname = tex.name;
2230 arr = rc_array (rc, &key); 2447 rc_t::array_t &arr = rc.array (key);
2231 2448
2232 rc_t2f_v3f (arr, 0 , 0 , px , py , 0); 2449 arr.t2f_v3f (0 , 0 , px , py , 0);
2233 rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0); 2450 arr.t2f_v3f (0 , tex.t, px , py + tex.h, 0);
2234 rc_t2f_v3f (arr, tex.s, tex.t, px + tex.w, py + tex.h, 0); 2451 arr.t2f_v3f (tex.s, tex.t, px + tex.w, py + tex.h, 0);
2235 rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0); 2452 arr.t2f_v3f (tex.s, 0 , px + tex.w, py , 0);
2236 2453
2237 rc_draw (rc); 2454 rc.draw ();
2238 } 2455 }
2239 2456
2457 rc_ov.draw ();
2458 rc_ov.clear ();
2459
2240 glDisable (GL_BLEND); 2460 glDisable (GL_BLEND);
2241 rc_free (rc);
2242 2461
2243 // top layer: overlays such as the health bar 2462 // top layer: overlays such as the health bar
2244 for (y = 0; y < sh; y++) 2463 for (y = 0; y < sh; y++)
2245 if (0 <= y + my && y + my < self->rows) 2464 if (0 <= y + my && y + my < self->rows)
2246 { 2465 {
2249 for (x = 0; x < sw; x++) 2468 for (x = 0; x < sw; x++)
2250 if (row->c0 <= x + mx && x + mx < row->c1) 2469 if (row->c0 <= x + mx && x + mx < row->c1)
2251 { 2470 {
2252 mapcell *cell = row->col + (x + mx - row->c0); 2471 mapcell *cell = row->col + (x + mx - row->c0);
2253 2472
2254 int px = x * T; 2473 int px = x * Tw;
2255 int py = y * T; 2474 int py = y * Th;
2256 2475
2257 if (expect_false (cell->player == player)) 2476 if (expect_false (cell->player == player))
2258 { 2477 {
2259 px += sdx; 2478 px += sdx;
2260 py += sdy; 2479 py += sdy;
2261 } 2480 }
2262 2481
2263 if (cell->stat_hp) 2482 if (cell->stat_hp)
2264 { 2483 {
2265 int width = cell->stat_width * T; 2484 int width = cell->stat_width * Tw;
2266 int thick = (sh * T / 32 + 27) / 28 + 1 + cell->stat_width; 2485 int thick = (sh * Th / 32 + 27) / 28 + 1 + cell->stat_width;
2267 2486
2268 glColor3ub (0, 0, 0); 2487 glColor3ub (0, 0, 0);
2269 glRectf (px + 1, py - thick - 2, 2488 glRectf (px + 1, py - thick - 2,
2270 px + width - 1, py); 2489 px + width - 1, py);
2271 2490
2277 } 2496 }
2278 } 2497 }
2279} 2498}
2280 2499
2281void 2500void
2282draw_magicmap (DC::Map self, int dx, int dy, int w, int h, unsigned char *data) 2501draw_magicmap (DC::Map self, int w, int h, unsigned char *data)
2283 CODE: 2502 CODE:
2284{ 2503{
2285 static float color[16][3] = { 2504 static float color[16][3] = {
2286 { 0.00F, 0.00F, 0.00F }, 2505 { 0.00f, 0.00f, 0.00f },
2287 { 1.00F, 1.00F, 1.00F }, 2506 { 1.00f, 1.00f, 1.00f },
2288 { 0.00F, 0.00F, 0.55F }, 2507 { 0.00f, 0.00f, 0.55f },
2289 { 1.00F, 0.00F, 0.00F }, 2508 { 1.00f, 0.00f, 0.00f },
2290 2509
2291 { 1.00F, 0.54F, 0.00F }, 2510 { 1.00f, 0.54f, 0.00f },
2292 { 0.11F, 0.56F, 1.00F }, 2511 { 0.11f, 0.56f, 1.00f },
2293 { 0.93F, 0.46F, 0.00F }, 2512 { 0.93f, 0.46f, 0.00f },
2294 { 0.18F, 0.54F, 0.34F }, 2513 { 0.18f, 0.54f, 0.34f },
2295 2514
2296 { 0.56F, 0.73F, 0.56F }, 2515 { 0.56f, 0.73f, 0.56f },
2297 { 0.80F, 0.80F, 0.80F }, 2516 { 0.80f, 0.80f, 0.80f },
2298 { 0.55F, 0.41F, 0.13F }, 2517 { 0.55f, 0.41f, 0.13f },
2299 { 0.99F, 0.77F, 0.26F }, 2518 { 0.99f, 0.77f, 0.26f },
2300 2519
2301 { 0.74F, 0.65F, 0.41F }, 2520 { 0.74f, 0.65f, 0.41f },
2302 2521
2303 { 0.00F, 1.00F, 1.00F }, 2522 { 0.00f, 1.00f, 1.00f },
2304 { 1.00F, 0.00F, 1.00F }, 2523 { 1.00f, 0.00f, 1.00f },
2305 { 1.00F, 1.00F, 0.00F }, 2524 { 1.00f, 1.00f, 0.00f },
2306 }; 2525 };
2307 2526
2308 int x, y; 2527 int x, y;
2309 2528
2310 glEnable (GL_TEXTURE_2D); 2529 glEnable (GL_TEXTURE_2D);
2530 /* GL_REPLACE would be correct, as we don't need to modulate alpha,
2531 * but the nvidia driver (185.18.14) mishandles alpha textures
2532 * and takes the colour from god knows where instead of using
2533 * Cp. MODULATE results in the same colour, but slightly different
2534 * alpha, but atcually gives us the correct colour with nvidia.
2535 */
2311 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 2536 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2312 glEnable (GL_BLEND); 2537 glEnable (GL_BLEND);
2313 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2538 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2314 glBegin (GL_QUADS); 2539 glBegin (GL_QUADS);
2315 2540
2316 for (y = 0; y < h; y++) 2541 for (y = 0; y < h; y++)
2320 2545
2321 if (m) 2546 if (m)
2322 { 2547 {
2323 float *c = color [m & 15]; 2548 float *c = color [m & 15];
2324 2549
2325 float tx1 = m & 0x40 ? 0.5 : 0.; 2550 float tx1 = m & 0x40 ? 0.5f : 0.f;
2326 float tx2 = tx1 + 0.5; 2551 float tx2 = tx1 + 0.5f;
2327 2552
2328 glColor4f (c[0], c[1], c[2], 0.75); 2553 glColor4f (c[0], c[1], c[2], 1);
2329 glTexCoord2f (tx1, 0.); glVertex2i (x , y ); 2554 glTexCoord2f (tx1, 0.); glVertex2i (x , y );
2330 glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1); 2555 glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
2331 glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1); 2556 glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
2332 glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y ); 2557 glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
2333 } 2558 }
2341void 2566void
2342fow_texture (DC::Map self, int mx, int my, int sw, int sh) 2567fow_texture (DC::Map self, int mx, int my, int sw, int sh)
2343 PPCODE: 2568 PPCODE:
2344{ 2569{
2345 int x, y; 2570 int x, y;
2346 int sw1 = sw + 2; 2571 int sw1 = sw + 2;
2347 int sh1 = sh + 2; 2572 int sh1 = sh + 2;
2348 int sh3 = sh * 3; 2573 int sh3 = sh * 3;
2349 int sw34 = (sw * 3 + 3) & ~3; 2574 int sw3 = sw * 3;
2575 SV *darkness3_sv = sv_2mortal (newSV (sw3 * sh3));
2576 uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv);
2350 uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1); 2577 uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1);
2351 SV *darkness3_sv = sv_2mortal (newSV (sw34 * sh3)); 2578 memset (darkness1, 0, sw1*sh1);
2352 uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv);
2353 2579
2354 SvPOK_only (darkness3_sv); 2580 SvPOK_only (darkness3_sv);
2355 SvCUR_set (darkness3_sv, sw34 * sh3); 2581 SvCUR_set (darkness3_sv, sw3 * sh3);
2356 2582
2357 mx += self->x - 1; 2583 mx += self->x - 1;
2358 my += self->y - 1; 2584 my += self->y - 1;
2359
2360 memset (darkness1, 255 - FOW_DARKNESS, sw1 * sh1);
2361 2585
2362 for (y = 0; y < sh1; y++) 2586 for (y = 0; y < sh1; y++)
2363 if (0 <= y + my && y + my < self->rows) 2587 if (0 <= y + my && y + my < self->rows)
2364 { 2588 {
2365 maprow *row = self->row + (y + my); 2589 maprow *row = self->row + (y + my);
2368 if (row->c0 <= x + mx && x + mx < row->c1) 2592 if (row->c0 <= x + mx && x + mx < row->c1)
2369 { 2593 {
2370 mapcell *cell = row->col + (x + mx - row->c0); 2594 mapcell *cell = row->col + (x + mx - row->c0);
2371 2595
2372 darkness1 [y * sw1 + x] = cell->darkness 2596 darkness1 [y * sw1 + x] = cell->darkness
2373 ? 255 - (cell->darkness - 1) 2597 ? DARKNESS_ADJUST (255 - (cell->darkness - 1))
2374 : 255 - FOW_DARKNESS; 2598 : DARKNESS_ADJUST (255 - FOW_DARKNESS);
2375 } 2599 }
2376 } 2600 }
2377 2601
2378 for (y = 0; y < sh; ++y) 2602 for (y = 0; y < sh; ++y)
2379 for (x = 0; x < sw; ++x) 2603 for (x = 0; x < sw; ++x)
2398 2622
2399 uint8_t r13 = (d13 + d23 + d12) / 3; 2623 uint8_t r13 = (d13 + d23 + d12) / 3;
2400 uint8_t r23 = d23; 2624 uint8_t r23 = d23;
2401 uint8_t r33 = (d23 + d33 + d32) / 3; 2625 uint8_t r33 = (d23 + d33 + d32) / 3;
2402 2626
2403 darkness3 [(y * 3 ) * sw34 + (x * 3 )] = MAX (d22, r11); 2627 darkness3 [(y * 3 ) * sw3 + (x * 3 )] = MAX (d22, r11);
2404 darkness3 [(y * 3 ) * sw34 + (x * 3 + 1)] = MAX (d22, r21); 2628 darkness3 [(y * 3 ) * sw3 + (x * 3 + 1)] = MAX (d22, r21);
2405 darkness3 [(y * 3 ) * sw34 + (x * 3 + 2)] = MAX (d22, r31); 2629 darkness3 [(y * 3 ) * sw3 + (x * 3 + 2)] = MAX (d22, r31);
2406 darkness3 [(y * 3 + 1) * sw34 + (x * 3 )] = MAX (d22, r12); 2630 darkness3 [(y * 3 + 1) * sw3 + (x * 3 )] = MAX (d22, r12);
2407 darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 1)] = MAX (d22, r22); 2631 darkness3 [(y * 3 + 1) * sw3 + (x * 3 + 1)] = MAX (d22, r22); /* this MUST be == d22 */
2408 darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 2)] = MAX (d22, r32); 2632 darkness3 [(y * 3 + 1) * sw3 + (x * 3 + 2)] = MAX (d22, r32);
2409 darkness3 [(y * 3 + 2) * sw34 + (x * 3 )] = MAX (d22, r13); 2633 darkness3 [(y * 3 + 2) * sw3 + (x * 3 )] = MAX (d22, r13);
2410 darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 1)] = MAX (d22, r23); 2634 darkness3 [(y * 3 + 2) * sw3 + (x * 3 + 1)] = MAX (d22, r23);
2411 darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 2)] = MAX (d22, r33); 2635 darkness3 [(y * 3 + 2) * sw3 + (x * 3 + 2)] = MAX (d22, r33);
2412 } 2636 }
2413 2637
2414 free (darkness1); 2638 free (darkness1);
2415 2639
2416 EXTEND (SP, 3); 2640 EXTEND (SP, 3);
2417 PUSHs (sv_2mortal (newSViv (sw34))); 2641 PUSHs (sv_2mortal (newSViv (sw3)));
2418 PUSHs (sv_2mortal (newSViv (sh3))); 2642 PUSHs (sv_2mortal (newSViv (sh3)));
2419 PUSHs (darkness3_sv); 2643 PUSHs (darkness3_sv);
2420} 2644}
2421 2645
2422SV * 2646SV *
2485 else 2709 else
2486 *data++ = 0; 2710 *data++ = 0;
2487 } 2711 }
2488 } 2712 }
2489 2713
2490 /* if size is w*h + 5 then no data has been found */ 2714 /* if size is w*h + 5 then no data has been found */
2491 if (data - (uint8_t *)SvPVX (data_sv) != w * h + 5) 2715 if (data - (uint8_t *)SvPVX (data_sv) != w * h + 5)
2492 { 2716 {
2493 SvPOK_only (data_sv); 2717 SvPOK_only (data_sv);
2494 SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv)); 2718 SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
2495 } 2719 }
2496 2720
2497 RETVAL = data_sv; 2721 RETVAL = data_sv;
2498} 2722}
2499 OUTPUT: 2723 OUTPUT:
2500 RETVAL 2724 RETVAL
2501 2725
2502void 2726void
2509 STRLEN len; 2733 STRLEN len;
2510 uint8_t *data, *end; 2734 uint8_t *data, *end;
2511 2735
2512 len = SvLEN (data_sv); 2736 len = SvLEN (data_sv);
2513 SvGROW (data_sv, len + 8); // reserve at least 7+ bytes more 2737 SvGROW (data_sv, len + 8); // reserve at least 7+ bytes more
2514 data = SvPVbyte_nolen (data_sv); 2738 data = (uint8_t *)SvPVbyte_nolen (data_sv);
2515 end = data + len + 8; 2739 end = data + len + 8;
2516 2740
2517 if (len < 5) 2741 if (len < 5)
2518 XSRETURN_EMPTY; 2742 XSRETURN_EMPTY;
2519 2743
2563 2787
2564 for (z = 0; z <= 2; z++) 2788 for (z = 0; z <= 2; z++)
2565 { 2789 {
2566 tileid t = tile [z]; 2790 tileid t = tile [z];
2567 2791
2568 if (t >= self->texs || (t && !self->tex [t].name)) 2792 if (t >= self->tex.size () || (t && !self->tex[t].name))
2569 { 2793 {
2570 PUSHs (sv_2mortal (newSViv (t))); 2794 PUSHs (sv_2mortal (newSViv (t)));
2571 need_texid (self, t); 2795 if (self->tex.size () <= t) self->tex.resize (t + 1);
2572 } 2796 }
2573 2797
2574 cell->tile [z] = t; 2798 cell->tile[z] = t;
2575 } 2799 }
2576 } 2800 }
2577 } 2801 }
2578 } 2802 }
2579 } 2803 }
2580} 2804}
2581 2805
2582MODULE = Deliantra::Client PACKAGE = DC::RW 2806MODULE = Deliantra::Client PACKAGE = DC::RW
2583 2807
2584DC::RW 2808DC::RW
2585new (SV *class, SV *data_sv) 2809new (SV *klass, SV *data_sv)
2586 CODE: 2810 CODE:
2587{ 2811{
2588 STRLEN datalen; 2812 STRLEN datalen;
2589 char *data = SvPVbyte (data_sv, datalen); 2813 char *data = SvPVbyte (data_sv, datalen);
2590 2814
2592} 2816}
2593 OUTPUT: 2817 OUTPUT:
2594 RETVAL 2818 RETVAL
2595 2819
2596DC::RW 2820DC::RW
2597new_from_file (SV *class, const char *path, const char *mode = "rb") 2821new_from_file (SV *klass, const char *path, const char *mode = "rb")
2598 CODE: 2822 CODE:
2599 RETVAL = SDL_RWFromFile (path, mode); 2823 RETVAL = SDL_RWFromFile (path, mode);
2600 OUTPUT: 2824 OUTPUT:
2601 RETVAL 2825 RETVAL
2602 2826
2620 if (RETVAL < 0) 2844 if (RETVAL < 0)
2621 { 2845 {
2622 RETVAL = Mix_GroupOldest (-1); 2846 RETVAL = Mix_GroupOldest (-1);
2623 2847
2624 if (RETVAL < 0) 2848 if (RETVAL < 0)
2849 {
2850 // happens sometimes, maybe it just stopped playing(?)
2851 RETVAL = Mix_GroupAvailable (-1);
2852
2853 if (RETVAL < 0)
2625 XSRETURN_UNDEF; 2854 XSRETURN_UNDEF;
2626 2855 }
2856 else
2627 Mix_HaltChannel (RETVAL); 2857 Mix_HaltChannel (RETVAL);
2628 } 2858 }
2629 2859
2630 Mix_UnregisterAllEffects (RETVAL); 2860 Mix_UnregisterAllEffects (RETVAL);
2631 Mix_Volume (RETVAL, 128); 2861 Mix_Volume (RETVAL, 128);
2632} 2862}
2679void 2909void
2680set_position_r (DC::Channel self, int dx, int dy, int maxdistance) 2910set_position_r (DC::Channel self, int dx, int dy, int maxdistance)
2681 CODE: 2911 CODE:
2682{ 2912{
2683 int distance = sqrtf (dx * dx + dy * dy) * (255.f / sqrtf (maxdistance * maxdistance)); 2913 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); 2914 int angle = atan2f (dx, -dy) * 180.f / (float)M_PI + 360.f;
2685 Mix_SetPosition (self, angle, CLAMP (distance, 0, 255)); 2915 Mix_SetPosition (self, angle, CLAMP (distance, 0, 255));
2686} 2916}
2687 2917
2688void 2918void
2689set_reverse_stereo (DC::Channel self, int flip) 2919set_reverse_stereo (DC::Channel self, int flip)
2692 2922
2693MODULE = Deliantra::Client PACKAGE = DC::MixChunk 2923MODULE = Deliantra::Client PACKAGE = DC::MixChunk
2694 2924
2695PROTOTYPES: DISABLE 2925PROTOTYPES: DISABLE
2696 2926
2927void
2928decoders ()
2929 PPCODE:
2930#if SDL_MIXER_MAJOR_VERSION > 1 || SDL_MIXER_MINOR_VERSION > 2 || SDL_MIXER_PATCHLEVEL >= 10
2931 int i, num = Mix_GetNumChunkDecoders ();
2932 EXTEND (SP, num);
2933 for (i = 0; i < num; ++i)
2934 PUSHs (sv_2mortal (newSVpv (Mix_GetChunkDecoder (i), 0)));
2935#else
2936 XPUSHs (sv_2mortal (newSVpv ("(sdl mixer too old)", 0)));
2937#endif
2938
2697DC::MixChunk 2939DC::MixChunk
2698new (SV *class, DC::RW rwops) 2940new (SV *klass, DC::RW rwops)
2699 CODE: 2941 CODE:
2700 RETVAL = Mix_LoadWAV_RW (rwops, 1); 2942 RETVAL = Mix_LoadWAV_RW (rwops, 1);
2701 OUTPUT: 2943 OUTPUT:
2702 RETVAL 2944 RETVAL
2703 2945
2733 OUTPUT: 2975 OUTPUT:
2734 RETVAL 2976 RETVAL
2735 2977
2736MODULE = Deliantra::Client PACKAGE = DC::MixMusic 2978MODULE = Deliantra::Client PACKAGE = DC::MixMusic
2737 2979
2980void
2981decoders ()
2982 PPCODE:
2983#if SDL_MIXER_MAJOR_VERSION > 1 || SDL_MIXER_MINOR_VERSION > 2 || SDL_MIXER_PATCHLEVEL >= 10
2984 int i, num = Mix_GetNumMusicDecoders ();
2985 EXTEND (SP, num);
2986 for (i = 0; i < num; ++i)
2987 PUSHs (sv_2mortal (newSVpv (Mix_GetMusicDecoder (i), 0)));
2988#else
2989 XPUSHs (sv_2mortal (newSVpv ("(sdl mixer too old)", 0)));
2990#endif
2991
2738int 2992int
2739volume (int volume = -1) 2993volume (int volume = -1)
2740 PROTOTYPE: ;$ 2994 PROTOTYPE: ;$
2741 CODE: 2995 CODE:
2742 if (items > 0) 2996 if (items > 0)
2753void 3007void
2754halt () 3008halt ()
2755 CODE: 3009 CODE:
2756 Mix_HaltMusic (); 3010 Mix_HaltMusic ();
2757 3011
3012int
3013playing ()
3014 CODE:
3015 RETVAL = Mix_PlayingMusic ();
3016 OUTPUT:
3017 RETVAL
3018
2758DC::MixMusic 3019DC::MixMusic
2759new (SV *class, DC::RW rwops) 3020new (SV *klass, DC::RW rwops)
2760 CODE: 3021 CODE:
2761 RETVAL = Mix_LoadMUS_RW (rwops); 3022 RETVAL = Mix_LoadMUS_RW (rwops);
2762 OUTPUT: 3023 OUTPUT:
2763 RETVAL 3024 RETVAL
2764 3025
2792 } *civ, const_iv[] = { 3053 } *civ, const_iv[] = {
2793# define const_iv(name) { # name, (IV)name } 3054# define const_iv(name) { # name, (IV)name }
2794 const_iv (GL_VENDOR), 3055 const_iv (GL_VENDOR),
2795 const_iv (GL_VERSION), 3056 const_iv (GL_VERSION),
2796 const_iv (GL_EXTENSIONS), 3057 const_iv (GL_EXTENSIONS),
3058 const_iv (GL_MAX_TEXTURE_UNITS),
2797 const_iv (GL_COLOR_MATERIAL), 3059 const_iv (GL_COLOR_MATERIAL),
2798 const_iv (GL_SMOOTH), 3060 const_iv (GL_SMOOTH),
2799 const_iv (GL_FLAT), 3061 const_iv (GL_FLAT),
2800 const_iv (GL_DITHER), 3062 const_iv (GL_DITHER),
2801 const_iv (GL_BLEND), 3063 const_iv (GL_BLEND),
2813 const_iv (GL_ZERO), 3075 const_iv (GL_ZERO),
2814 const_iv (GL_SRC_ALPHA), 3076 const_iv (GL_SRC_ALPHA),
2815 const_iv (GL_DST_ALPHA), 3077 const_iv (GL_DST_ALPHA),
2816 const_iv (GL_ONE_MINUS_SRC_ALPHA), 3078 const_iv (GL_ONE_MINUS_SRC_ALPHA),
2817 const_iv (GL_ONE_MINUS_DST_ALPHA), 3079 const_iv (GL_ONE_MINUS_DST_ALPHA),
3080 const_iv (GL_SRC_COLOR),
3081 const_iv (GL_DST_COLOR),
3082 const_iv (GL_ONE_MINUS_SRC_COLOR),
3083 const_iv (GL_ONE_MINUS_DST_COLOR),
2818 const_iv (GL_SRC_ALPHA_SATURATE), 3084 const_iv (GL_SRC_ALPHA_SATURATE),
2819 const_iv (GL_RGB), 3085 const_iv (GL_RGB),
2820 const_iv (GL_RGBA), 3086 const_iv (GL_RGBA),
2821 const_iv (GL_RGBA4), 3087 const_iv (GL_RGBA4),
2822 const_iv (GL_RGBA8), 3088 const_iv (GL_RGBA8),
2890 const_iv (GL_NICEST), 3156 const_iv (GL_NICEST),
2891 const_iv (GL_V2F), 3157 const_iv (GL_V2F),
2892 const_iv (GL_V3F), 3158 const_iv (GL_V3F),
2893 const_iv (GL_T2F_V3F), 3159 const_iv (GL_T2F_V3F),
2894 const_iv (GL_T2F_N3F_V3F), 3160 const_iv (GL_T2F_N3F_V3F),
3161 const_iv (GL_FUNC_ADD),
3162 const_iv (GL_FUNC_SUBTRACT),
3163 const_iv (GL_FUNC_REVERSE_SUBTRACT),
2895# undef const_iv 3164# undef const_iv
2896 }; 3165 };
2897 3166
2898 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) 3167 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--)
2899 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 3168 newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv));
2900 3169
2901 texture_av = newAV (); 3170 texture_av = newAV ();
2902 AvREAL_off (texture_av); 3171 AvREAL_off (texture_av);
2903} 3172}
2904 3173
2906disable_GL_EXT_blend_func_separate () 3175disable_GL_EXT_blend_func_separate ()
2907 CODE: 3176 CODE:
2908 gl.BlendFuncSeparate = 0; 3177 gl.BlendFuncSeparate = 0;
2909 gl.BlendFuncSeparateEXT = 0; 3178 gl.BlendFuncSeparateEXT = 0;
2910 3179
2911char * 3180void
3181apple_nvidia_bug (int enable)
3182
3183const char *
2912gl_vendor () 3184gl_vendor ()
2913 CODE: 3185 CODE:
2914 RETVAL = (char *)glGetString (GL_VENDOR); 3186 RETVAL = (const char *)glGetString (GL_VENDOR);
2915 OUTPUT: 3187 OUTPUT:
2916 RETVAL 3188 RETVAL
2917 3189
2918char * 3190const char *
2919gl_version () 3191gl_version ()
2920 CODE: 3192 CODE:
2921 RETVAL = (char *)glGetString (GL_VERSION); 3193 RETVAL = (const char *)glGetString (GL_VERSION);
2922 OUTPUT: 3194 OUTPUT:
2923 RETVAL 3195 RETVAL
2924 3196
2925char * 3197const char *
2926gl_extensions () 3198gl_extensions ()
2927 CODE: 3199 CODE:
2928 RETVAL = (char *)glGetString (GL_EXTENSIONS); 3200 RETVAL = (const char *)glGetString (GL_EXTENSIONS);
2929 OUTPUT: 3201 OUTPUT:
2930 RETVAL 3202 RETVAL
2931 3203
2932const char *glGetString (GLenum pname) 3204const char *glGetString (GLenum pname)
3205 CODE:
3206 RETVAL = (const char *)glGetString (pname);
3207 OUTPUT:
3208 RETVAL
2933 3209
2934GLint glGetInteger (GLenum pname) 3210GLint glGetInteger (GLenum pname)
2935 CODE: 3211 CODE:
2936 glGetIntegerv (pname, &RETVAL); 3212 glGetIntegerv (pname, &RETVAL);
2937 OUTPUT: 3213 OUTPUT:
2945 3221
2946int glGetError () 3222int glGetError ()
2947 3223
2948void glFinish () 3224void glFinish ()
2949 3225
3226void glFlush ()
3227
2950void glClear (int mask) 3228void glClear (int mask)
2951 3229
2952void glClearColor (float r, float g, float b, float a = 1.0) 3230void glClearColor (float r, float g, float b, float a = 1.0)
2953 PROTOTYPE: @ 3231 PROTOTYPE: @
2954 3232
2963void glBlendFunc (int sfactor, int dfactor) 3241void glBlendFunc (int sfactor, int dfactor)
2964 3242
2965void glBlendFuncSeparate (int sa, int da, int saa, int daa) 3243void glBlendFuncSeparate (int sa, int da, int saa, int daa)
2966 CODE: 3244 CODE:
2967 gl_BlendFuncSeparate (sa, da, saa, daa); 3245 gl_BlendFuncSeparate (sa, da, saa, daa);
3246
3247# void glBlendEquation (int se)
2968 3248
2969void glDepthMask (int flag) 3249void glDepthMask (int flag)
2970 3250
2971void glLogicOp (int opcode) 3251void glLogicOp (int opcode)
2972 3252
3123 3403
3124void glEndList () 3404void glEndList ()
3125 3405
3126void glCallList (int list) 3406void glCallList (int list)
3127 3407
3408void c_init ()
3409 CODE:
3410 glPixelStorei (GL_PACK_ALIGNMENT , 1);
3411 glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
3412
3128MODULE = Deliantra::Client PACKAGE = DC::UI::Base 3413MODULE = Deliantra::Client PACKAGE = DC::UI::Base
3129 3414
3130PROTOTYPES: DISABLE 3415PROTOTYPES: DISABLE
3131 3416
3132void 3417void
3133find_widget (SV *self, NV x, NV y) 3418find_widget (SV *self, NV x, NV y)
3134 PPCODE: 3419 PPCODE:
3135{ 3420{
3136 if (within_widget (self, x, y)) 3421 if (within_widget (self, x, y))
3137 XPUSHs (self); 3422 XPUSHs (self);
3138} 3423}
3139 3424
3140BOOT: 3425BOOT:
3141{ 3426{
3149 3434
3150void 3435void
3151draw (SV *self) 3436draw (SV *self)
3152 CODE: 3437 CODE:
3153{ 3438{
3154 HV *hv; 3439 HV *hv;
3155 SV **svp; 3440 SV **svp;
3156 NV x, y, w, h; 3441 NV x, y, w, h;
3157 SV *draw_x_sv = GvSV (draw_x_gv); 3442 SV *draw_x_sv = GvSV (draw_x_gv);
3158 SV *draw_y_sv = GvSV (draw_y_gv); 3443 SV *draw_y_sv = GvSV (draw_y_gv);
3159 SV *draw_w_sv = GvSV (draw_w_gv); 3444 SV *draw_w_sv = GvSV (draw_w_gv);
3160 SV *draw_h_sv = GvSV (draw_h_gv); 3445 SV *draw_h_sv = GvSV (draw_h_gv);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines