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.253 by root, Fri Dec 28 20:59:14 2007 UTC vs.
Revision 1.332 by root, Mon Nov 19 00:56:08 2018 UTC

15 15
16#include "EXTERN.h" 16#include "EXTERN.h"
17#include "perl.h" 17#include "perl.h"
18#include "XSUB.h" 18#include "XSUB.h"
19 19
20#include "flat_hash_map.hpp"
21
20#ifdef _WIN32 22#ifdef _WIN32
21# undef pipe 23# undef pipe
22// microsoft vs. C 24// microsoft vs. C
23# define sqrtf(x) sqrt(x) 25# define sqrtf(x) sqrt(x)
24# define 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>
39#include <SDL_endian.h> 43#include <SDL_endian.h>
40#include <SDL_image.h> 44#include <SDL_image.h>
41#include <SDL_mixer.h> 45#include <SDL_mixer.h>
42#include <SDL_opengl.h> 46#include <SDL_opengl.h>
43 47
48/* work around os x broken headers */
49#ifdef __MACOSX__
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);
53#endif
54
44#define PANGO_ENABLE_BACKEND 55#define PANGO_ENABLE_BACKEND
45#define G_DISABLE_CAST_CHECKS 56#define G_DISABLE_CAST_CHECKS
46 57
47#include <glib/gmacros.h> 58#include <glib.h>
48 59
49#include <pango/pango.h> 60#include <pango/pango.h>
50 61
51#if !(defined (PANGO_VERSION_CHECK) && PANGO_VERSION_CHECK (1, 15, 2)) 62#ifndef PANGO_VERSION_CHECK
63# define PANGO_VERSION_CHECK(a,b,c) 0
64#endif
65
66#if !PANGO_VERSION_CHECK (1, 15, 2)
52# define pango_layout_get_line_readonly pango_layout_get_line_readonly 67# define pango_layout_get_line_readonly pango_layout_get_line
53# define pango_layout_get_lines_readonly pango_layout_get_lines_readonly 68# define pango_layout_get_lines_readonly pango_layout_get_lines
54# define pango_layout_iter_get_line_readonly pango_layout_iter_get_line_readonly 69# define pango_layout_iter_get_line_readonly pango_layout_iter_get_line
55# define pango_layout_iter_get_run_readonly pango_layout_iter_get_run_readonly 70# define pango_layout_iter_get_run_readonly pango_layout_iter_get_run
56#endif 71#endif
57 72
58#ifndef _WIN32 73#ifndef _WIN32
59# include <sys/types.h> 74# include <sys/types.h>
60# include <sys/socket.h> 75# include <sys/socket.h>
61# include <netinet/in.h> 76# include <netinet/in.h>
62# include <netinet/tcp.h> 77# include <netinet/tcp.h>
63# include <inttypes.h> 78# include <inttypes.h>
64#endif 79#endif
65 80
81#include "ecb.h"
82
66#define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, object replacement character */ 83#define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, object replacement character */
67 84
85/* this is used as fow flag as well, so has to have a different value */
86/* then anything that is computed by incoming darkness */
68#define FOW_DARKNESS 32 87#define FOW_DARKNESS 50
88#define DARKNESS_ADJUST(n) (n)
69 89
70#define MAP_EXTEND_X 32 90#define MAP_EXTEND_X 32
71#define MAP_EXTEND_Y 512 91#define MAP_EXTEND_Y 512
72 92
73#define MIN_FONT_HEIGHT 10 93#define MIN_FONT_HEIGHT 10
74 94
75/* mask out modifiers we are not interested in */ 95/* mask out modifiers we are not interested in */
76#define MOD_MASK (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_META) 96#define MOD_MASK (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_META)
77 97
78#if 0 98#define KMOD_LRAM 0x10000 // our extension
79# define PARACHUTE SDL_INIT_NOPARACHUTE 99
80#else 100#define TEXID_SPEECH 1
81# define PARACHUTE 0 101#define TEXID_NOFACE 2
82#endif 102
103static char *
104fast_sv_grow (SV *sv, STRLEN need)
105{
106 STRLEN len = SvLEN (sv);
107 STRLEN want = SvCUR (sv) + need;
108
109 if (ecb_expect_false (len < want))
110 {
111 do
112 len *= 2;
113 while (len < want);
114
115 sv_grow (sv, len);
116 }
117
118 SvCUR_set (sv, want);
119 return SvEND (sv) - need;
120}
83 121
84static AV *texture_av; 122static AV *texture_av;
85 123
86static struct 124static struct
87{ 125{
144{ 182{
145 GSList *attrs = run->item->analysis.extra_attrs; 183 GSList *attrs = run->item->analysis.extra_attrs;
146 184
147 while (attrs) 185 while (attrs)
148 { 186 {
149 PangoAttribute *attr = attrs->data; 187 PangoAttribute *attr = (PangoAttribute *)attrs->data;
150 188
151 if (attr->klass->type == PANGO_ATTR_SHAPE) 189 if (attr->klass->type == PANGO_ATTR_SHAPE)
152 return 1; 190 return 1;
153 191
154 attrs = attrs->next; 192 attrs = attrs->next;
155 } 193 }
156 194
157 return 0; 195 return 0;
158} 196}
159 197
160typedef struct cf_layout { 198struct cf_layout {
161 PangoLayout *pl; 199 PangoLayout *pl;
162 float r, g, b, a; // default color for rgba mode 200 float r, g, b, a; // default color for rgba mode
163 int base_height; 201 int base_height;
164 DC__Font font; 202 DC__Font font;
165 rc_t *rc; 203 rc_t rc;
166} *DC__Layout; 204};
205
206typedef cf_layout *DC__Layout;
167 207
168static DC__Font default_font; 208static DC__Font default_font;
169static PangoContext *opengl_context; 209static PangoContext *opengl_context;
170static PangoFontMap *opengl_fontmap; 210static PangoFontMap *opengl_fontmap;
171 211
172static void 212static void
173substitute_func (FcPattern *pattern, gpointer data) 213substitute_func (FcPattern *pattern, gpointer data)
174{ 214{
175 FcPatternAddBool (pattern, FC_HINTING, 1); 215 FcPatternAddBool (pattern, FC_HINTING, 1);
176#ifdef FC_HINT_STYLE 216#ifdef FC_HINT_STYLE
177 FcPatternAddBool (pattern, FC_HINT_STYLE, FC_HINT_FULL); 217 FcPatternAddInteger (pattern, FC_HINT_STYLE, FC_HINT_FULL);
178#endif 218#endif
179 FcPatternAddBool (pattern, FC_AUTOHINT, 0); 219 FcPatternAddBool (pattern, FC_AUTOHINT, 0);
180} 220}
181 221
182static void 222static void
183layout_update_font (DC__Layout self) 223layout_update_font (DC__Layout self)
184{ 224{
185 /* use a random scale factor to account for unknown descenders, 0.8 works 225 /* use a random scale factor to account for unknown descenders, 0.8 works
186 * reasonably well with bitstream vera 226 * reasonably well with dejavu/bistream fonts
187 */ 227 */
188 PangoFontDescription *font = self->font ? self->font : default_font; 228 PangoFontDescription *font = self->font ? self->font : default_font;
189 229
190 pango_font_description_set_absolute_size (font, 230 pango_font_description_set_absolute_size (font,
191 MAX (MIN_FONT_HEIGHT, self->base_height) * (PANGO_SCALE * 8 / 10)); 231 MAX (MIN_FONT_HEIGHT, self->base_height) * (PANGO_SCALE * 8 / 10));
209 249
210 *w = rect.width; 250 *w = rect.width;
211 *h = rect.height; 251 *h = rect.height;
212} 252}
213 253
254/////////////////////////////////////////////////////////////////////////////
255
214typedef uint16_t tileid; 256typedef uint16_t tileid;
215typedef uint16_t faceid; 257typedef uint16_t faceid;
216 258
217typedef struct { 259struct maptex
260{
218 GLuint name; 261 GLuint name;
219 int w, h; 262 int w, h;
220 float s, t; 263 float s, t;
221 uint8_t r, g, b, a; 264 uint8_t r, g, b, a;
222 tileid smoothtile; 265 tileid smoothtile;
223 uint8_t smoothlevel; 266 uint8_t smoothlevel;
224} maptex; 267 uint8_t unused; /* set to zero on use */
268};
225 269
226typedef struct { 270struct mapcell
271{
227 uint32_t player; 272 uint32_t player;
228 tileid tile[3]; 273 tileid tile[3];
229 uint16_t darkness; 274 uint16_t darkness;
230 uint8_t stat_width, stat_hp, flags, smoothmax; 275 uint8_t stat_width, stat_hp, flags, smoothmax;
231} mapcell; 276};
232 277
233typedef struct { 278struct maprow
279{
234 int32_t c0, c1; 280 int32_t c0, c1;
235 mapcell *col; 281 mapcell *col;
236} maprow; 282};
237 283
238typedef struct map { 284struct mapgrid {
239 int x, y, w, h; 285 int x, y, w, h;
240 int ox, oy; /* offset to virtual global coordinate system */ 286 int ox, oy; /* offset to virtual global coordinate system */
241 int faces; tileid *face2tile; // [faceid] 287 int faces; tileid *face2tile; // [faceid]
242 int texs; maptex *tex; // [tileid] 288 int texs; maptex *tex; // [tileid]
243 289
244 int32_t rows; 290 int32_t rows;
245 maprow *row; 291 maprow *row;
246} *DC__Map; 292};
247 293
248static char * 294typedef mapgrid *DC__Map;
295
296template<typename T>
297static void
249prepend (char *ptr, int sze, int inc) 298prepend (T *&ptr, int sze, int inc)
250{ 299{
251 char *p; 300 T *p;
252 301
253 New (0, p, sze + inc, char); 302 Newx (p, inc + sze, T);
254 Zero (p, inc, char); 303 Zero (p, inc, T);
255 Move (ptr, p + inc, sze, char); 304 Move (ptr, p + inc, sze, T);
256 Safefree (ptr); 305 Safefree (ptr);
257 306
258 return p; 307 ptr = p;
259} 308}
260 309
261static char * 310template<typename T>
262append (char *ptr, int sze, int inc)
263{
264 Renew (ptr, sze + inc, char);
265 Zero (ptr + sze, inc, char);
266
267 return ptr;
268}
269
270#define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
271#define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
272
273static void 311static void
312append (T *&ptr, int sze, int inc)
313{
314 Renew (ptr, sze + inc, T);
315 Zero (ptr + sze, inc, T);
316}
317
318static void
274need_facenum (struct map *self, faceid face) 319need_facenum (struct mapgrid *self, faceid face)
275{ 320{
276 while (self->faces <= face) 321 while (self->faces <= face)
277 { 322 {
278 Append (tileid, self->face2tile, self->faces, self->faces); 323 append (self->face2tile, self->faces, self->faces);
279 self->faces *= 2; 324 self->faces *= 2;
280 } 325 }
281} 326}
282 327
283static void 328static void
284need_texid (struct map *self, int texid) 329need_texid (struct mapgrid *self, int texid)
285{ 330{
286 while (self->texs <= texid) 331 while (self->texs <= texid)
287 { 332 {
288 Append (maptex, self->tex, self->texs, self->texs); 333 append (self->tex, self->texs, self->texs);
289 self->texs *= 2; 334 self->texs *= 2;
290 } 335 }
291} 336}
292 337
293static maprow * 338static maprow *
294map_get_row (DC__Map self, int y) 339map_get_row (mapgrid *self, int y)
295{ 340{
296 if (0 > y) 341 if (0 > y)
297 { 342 {
298 int extend = - y + MAP_EXTEND_Y; 343 int extend = - y + MAP_EXTEND_Y;
299 Prepend (maprow, self->row, self->rows, extend); 344 prepend (self->row, self->rows, extend);
300 345
301 self->rows += extend; 346 self->rows += extend;
302 self->y += extend; 347 self->y += extend;
303 y += extend; 348 y += extend;
304 } 349 }
305 else if (y >= self->rows) 350 else if (y >= self->rows)
306 { 351 {
307 int extend = y - self->rows + MAP_EXTEND_Y; 352 int extend = y - self->rows + MAP_EXTEND_Y;
308 Append (maprow, self->row, self->rows, extend); 353 append (self->row, self->rows, extend);
309 self->rows += extend; 354 self->rows += extend;
310 } 355 }
311 356
312 return self->row + y; 357 return self->row + y;
313} 358}
323 } 368 }
324 369
325 if (row->c0 > x) 370 if (row->c0 > x)
326 { 371 {
327 int extend = row->c0 - x + MAP_EXTEND_X; 372 int extend = row->c0 - x + MAP_EXTEND_X;
328 Prepend (mapcell, row->col, row->c1 - row->c0, extend); 373 prepend (row->col, row->c1 - row->c0, extend);
329 row->c0 -= extend; 374 row->c0 -= extend;
330 } 375 }
331 else if (x >= row->c1) 376 else if (x >= row->c1)
332 { 377 {
333 int extend = x - row->c1 + MAP_EXTEND_X; 378 int extend = x - row->c1 + MAP_EXTEND_X;
334 Append (mapcell, row->col, row->c1 - row->c0, extend); 379 append (row->col, row->c1 - row->c0, extend);
335 row->c1 += extend; 380 row->c1 += extend;
336 } 381 }
337 382
338 return row->col + (x - row->c0); 383 return row->col + (x - row->c0);
339} 384}
340 385
341static mapcell * 386static mapcell *
342map_get_cell (DC__Map self, int x, int y) 387map_get_cell (mapgrid *self, int x, int y)
343{ 388{
344 return row_get_cell (map_get_row (self, y), x); 389 return row_get_cell (map_get_row (self, y), x);
345} 390}
346 391
347static void 392static void
348map_clear (DC__Map self) 393map_clear (mapgrid *self)
349{ 394{
350 int r; 395 int r;
351 396
352 for (r = 0; r < self->rows; r++) 397 for (r = 0; r < self->rows; r++)
353 Safefree (self->row[r].col); 398 Safefree (self->row[r].col);
360 self->oy = 0; 405 self->oy = 0;
361 self->row = 0; 406 self->row = 0;
362 self->rows = 0; 407 self->rows = 0;
363} 408}
364 409
410#define CELL_CLEAR(cell) \
411 do { \
412 if ((cell)->player) \
413 (cell)->tile [2] = 0; \
414 (cell)->darkness = 0; \
415 (cell)->stat_hp = 0; \
416 (cell)->flags = 0; \
417 (cell)->player = 0; \
418 } while (0)
419
365static void 420static void
366map_blank (DC__Map self, int x0, int y0, int w, int h) 421map_blank (mapgrid *self, int x0, int y0, int w, int h)
367{ 422{
368 int x, y; 423 int x, y;
369 maprow *row; 424 maprow *row;
370 mapcell *cell; 425 mapcell *cell;
371 426
383 if (x >= row->c1) 438 if (x >= row->c1)
384 break; 439 break;
385 440
386 cell = row->col + x - row->c0; 441 cell = row->col + x - row->c0;
387 442
388 cell->darkness = 0; 443 CELL_CLEAR (cell);
389 cell->stat_hp = 0;
390 cell->flags = 0;
391 cell->player = 0;
392 } 444 }
393 } 445 }
394} 446}
395 447
396typedef struct { 448struct smooth_key
449{
397 tileid tile; 450 tileid tile;
398 uint8_t x, y, level; 451 uint8_t x, y, level;
399} smooth_key; 452
453 bool operator == (const smooth_key &o) const
454 {
455 return tile == o.tile && x == o.x && y == o.y && level == o.level;
456 }
457};
458
459typedef ska::flat_hash_map<smooth_key, IV> smooth_hash;
460
461namespace std {
462 template <>
463 struct hash<smooth_key>
464 {
465 size_t operator () (const smooth_key &v) const
466 {
467 return v.tile + (v.x << 8) + (v.y << 16) + (v.level << 24);
468 }
469 };
470}
400 471
401static void 472static void
402smooth_or_bits (HV *hv, smooth_key *key, IV bits) 473smooth_or_bits (smooth_hash &h, smooth_key &key, IV bits)
403{ 474{
404 SV **sv = hv_fetch (hv, (char *)key, sizeof (*key), 1); 475 auto &&it = h.find (key);
405 476
406 if (SvIOK (*sv)) 477 if (it == h.end ())
407 SvIV_set (*sv, SvIVX (*sv) | bits); 478 h.insert (std::make_pair (key, bits));
408 else 479 else
409 sv_setiv (*sv, bits); 480 it->second |= bits;
410} 481}
411 482
412static void 483static void
413music_finished (void) 484music_finished (void)
414{ 485{
431 ev.code = 1; 502 ev.code = 1;
432 ev.data1 = (void *)(long)channel; 503 ev.data1 = (void *)(long)channel;
433 ev.data2 = 0; 504 ev.data2 = 0;
434 505
435 SDL_PushEvent ((SDL_Event *)&ev); 506 SDL_PushEvent ((SDL_Event *)&ev);
507}
508
509// approximately divide by 255
510static unsigned int
511div255 (unsigned int n)
512{
513 return (n + (n >> 8)) >> 8;
436} 514}
437 515
438static unsigned int 516static unsigned int
439minpot (unsigned int n) 517minpot (unsigned int n)
440{ 518{
450 n |= n >> 16; 528 n |= n >> 16;
451 529
452 return n + 1; 530 return n + 1;
453} 531}
454 532
455static unsigned int
456popcount (unsigned int n)
457{
458 n -= (n >> 1) & 0x55555555U;
459 n = ((n >> 2) & 0x33333333U) + (n & 0x33333333U);
460 n = ((n >> 4) + n) & 0x0f0f0f0fU;
461 n *= 0x01010101U;
462
463 return n >> 24;
464}
465
466/* SDL should provide this, really. */ 533/* SDL should provide this, really. */
467#define SDLK_MODIFIER_MIN 300 534#define SDLK_MODIFIER_MIN 300
468#define SDLK_MODIFIER_MAX 314 535#define SDLK_MODIFIER_MAX 314
469 536
470/******************************************************************************/ 537/******************************************************************************/
507 if (!svp || !SvTRUE (*svp)) 574 if (!svp || !SvTRUE (*svp))
508 return 0; 575 return 0;
509 576
510 return 1; 577 return 1;
511} 578}
579
580/******************************************************************************/
581
582/* process keyboard modifiers */
583static int
584mod_munge (int mod)
585{
586 mod &= MOD_MASK;
587
588 if (mod & (KMOD_META | KMOD_ALT))
589 mod |= KMOD_LRAM;
590
591 return mod;
592}
593
594static void
595deliantra_main (SV *real_main)
596{
597 dSP;
598
599 PUSHMARK (SP);
600 call_sv (real_main, G_DISCARD | G_VOID);
601}
602
603#ifdef __MACOSX__
604 static SV *real_main;
605
606 /* to due surprising braindamage on the side of SDL design, we
607 * do some mind-boggling hack here: SDL requires a custom main()
608 * on OS X, so... we provide one and call the original main(), which,
609 * due to shared library magic, calls -lSDLmain's main, not perl's main,
610 * and which calls our main (== SDL_main) back.
611 */
612 extern C_LINKAGE int
613 main (int argc, char *argv[])
614 {
615 deliantra_main (real_main);
616 }
617
618 #undef main
619
620 extern C_LINKAGE int main (int argc, char *argv[]);
621
622 static void
623 SDL_main_hack (SV *real_main_)
624 {
625 real_main = real_main_;
626
627 char *argv[] = { "deliantra client", 0 };
628 (main) (1, argv);
629 }
630#else
631 static void
632 SDL_main_hack (SV *real_main)
633 {
634 deliantra_main (real_main);
635 }
636#endif
512 637
513MODULE = Deliantra::Client PACKAGE = DC 638MODULE = Deliantra::Client PACKAGE = DC
514 639
515PROTOTYPES: ENABLE 640PROTOTYPES: ENABLE
516 641
545 const_iv (SDL_USEREVENT), 670 const_iv (SDL_USEREVENT),
546 671
547 const_iv (SDL_APPINPUTFOCUS), 672 const_iv (SDL_APPINPUTFOCUS),
548 const_iv (SDL_APPMOUSEFOCUS), 673 const_iv (SDL_APPMOUSEFOCUS),
549 const_iv (SDL_APPACTIVE), 674 const_iv (SDL_APPACTIVE),
675
676
677 const_iv (SDLK_UNKNOWN),
678 const_iv (SDLK_FIRST),
679 const_iv (SDLK_BACKSPACE),
680 const_iv (SDLK_TAB),
681 const_iv (SDLK_CLEAR),
682 const_iv (SDLK_RETURN),
683 const_iv (SDLK_PAUSE),
684 const_iv (SDLK_ESCAPE),
685 const_iv (SDLK_SPACE),
686 const_iv (SDLK_EXCLAIM),
687 const_iv (SDLK_QUOTEDBL),
688 const_iv (SDLK_HASH),
689 const_iv (SDLK_DOLLAR),
690 const_iv (SDLK_AMPERSAND),
691 const_iv (SDLK_QUOTE),
692 const_iv (SDLK_LEFTPAREN),
693 const_iv (SDLK_RIGHTPAREN),
694 const_iv (SDLK_ASTERISK),
695 const_iv (SDLK_PLUS),
696 const_iv (SDLK_COMMA),
697 const_iv (SDLK_MINUS),
698 const_iv (SDLK_PERIOD),
699 const_iv (SDLK_SLASH),
700 const_iv (SDLK_0),
701 const_iv (SDLK_1),
702 const_iv (SDLK_2),
703 const_iv (SDLK_3),
704 const_iv (SDLK_4),
705 const_iv (SDLK_5),
706 const_iv (SDLK_6),
707 const_iv (SDLK_7),
708 const_iv (SDLK_8),
709 const_iv (SDLK_9),
710 const_iv (SDLK_COLON),
711 const_iv (SDLK_SEMICOLON),
712 const_iv (SDLK_LESS),
713 const_iv (SDLK_EQUALS),
714 const_iv (SDLK_GREATER),
715 const_iv (SDLK_QUESTION),
716 const_iv (SDLK_AT),
717
718 const_iv (SDLK_LEFTBRACKET),
719 const_iv (SDLK_BACKSLASH),
720 const_iv (SDLK_RIGHTBRACKET),
721 const_iv (SDLK_CARET),
722 const_iv (SDLK_UNDERSCORE),
723 const_iv (SDLK_BACKQUOTE),
724 const_iv (SDLK_DELETE),
550 725
551 const_iv (SDLK_FIRST), 726 const_iv (SDLK_FIRST),
552 const_iv (SDLK_LAST), 727 const_iv (SDLK_LAST),
553 const_iv (SDLK_KP0), 728 const_iv (SDLK_KP0),
554 const_iv (SDLK_KP1), 729 const_iv (SDLK_KP1),
630 const_iv (KMOD_RMETA), 805 const_iv (KMOD_RMETA),
631 const_iv (KMOD_NUM), 806 const_iv (KMOD_NUM),
632 const_iv (KMOD_CAPS), 807 const_iv (KMOD_CAPS),
633 const_iv (KMOD_MODE), 808 const_iv (KMOD_MODE),
634 809
810 const_iv (KMOD_LRAM),
811
635 const_iv (MIX_DEFAULT_FORMAT), 812 const_iv (MIX_DEFAULT_FORMAT),
813
814 const_iv (SDL_INIT_TIMER),
815 const_iv (SDL_INIT_AUDIO),
816 const_iv (SDL_INIT_VIDEO),
817 const_iv (SDL_INIT_CDROM),
818 const_iv (SDL_INIT_JOYSTICK),
819 const_iv (SDL_INIT_EVERYTHING),
820 const_iv (SDL_INIT_NOPARACHUTE),
821 const_iv (SDL_INIT_EVENTTHREAD),
822
823 const_iv (SDL_GL_RED_SIZE),
824 const_iv (SDL_GL_GREEN_SIZE),
825 const_iv (SDL_GL_BLUE_SIZE),
826 const_iv (SDL_GL_ALPHA_SIZE),
827 const_iv (SDL_GL_DOUBLEBUFFER),
828 const_iv (SDL_GL_BUFFER_SIZE),
829 const_iv (SDL_GL_DEPTH_SIZE),
830 const_iv (SDL_GL_STENCIL_SIZE),
831 const_iv (SDL_GL_ACCUM_RED_SIZE),
832 const_iv (SDL_GL_ACCUM_GREEN_SIZE),
833 const_iv (SDL_GL_ACCUM_BLUE_SIZE),
834 const_iv (SDL_GL_ACCUM_ALPHA_SIZE),
835 const_iv (SDL_GL_STEREO),
836 const_iv (SDL_GL_MULTISAMPLEBUFFERS),
837 const_iv (SDL_GL_MULTISAMPLESAMPLES),
838 const_iv (SDL_GL_ACCELERATED_VISUAL),
839 const_iv (SDL_GL_SWAP_CONTROL),
840
841 const_iv (FOW_DARKNESS)
636# undef const_iv 842# undef const_iv
637 }; 843 };
638 844
639 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) 845 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--)
640 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 846 newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv));
641 847
642 assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK); 848 assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK);
643 assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE); 849 assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE);
644} 850}
645 851
660 866
661NV ceil (NV x) 867NV ceil (NV x)
662 868
663IV minpot (UV n) 869IV minpot (UV n)
664 870
871UV ld32 (UV n)
872 CODE:
873 RETVAL = ecb_ld32 (n);
874 OUTPUT:
875 RETVAL
876
665IV popcount (UV n) 877IV popcount (UV n)
878 CODE:
879 RETVAL = ecb_popcount32 (n);
880 OUTPUT:
881 RETVAL
882
883NV distance (NV dx, NV dy)
884 CODE:
885 RETVAL = pow (dx * dx + dy * dy, 0.5);
886 OUTPUT:
887 RETVAL
666 888
667void 889void
668pango_init () 890pango_init ()
669 CODE: 891 CODE:
670{ 892{
671 opengl_fontmap = pango_opengl_font_map_new (); 893 opengl_fontmap = pango_opengl_font_map_new ();
672 pango_opengl_font_map_set_default_substitute ((PangoOpenGLFontMap *)opengl_fontmap, substitute_func, 0, 0); 894 pango_opengl_font_map_set_default_substitute ((PangoOpenGLFontMap *)opengl_fontmap, substitute_func, 0, 0);
673 opengl_context = pango_opengl_font_map_create_context ((PangoOpenGLFontMap *)opengl_fontmap); 895 opengl_context = pango_opengl_font_map_create_context ((PangoOpenGLFontMap *)opengl_fontmap);
674#if defined (PANGO_VERSION_CHECK) && PANGO_VERSION_CHECK (1, 15, 2) 896 /*pango_context_set_font_description (opengl_context, default_font);*/
897#if PANGO_VERSION_CHECK (1, 15, 2)
675 pango_context_set_language (opengl_context, pango_language_from_string ("en")); 898 pango_context_set_language (opengl_context, pango_language_from_string ("en"));
676 /*pango_context_set_base_dir (opengl_context, PANGO_DIRECTION_WEAK_LTR);*/ 899 /*pango_context_set_base_dir (opengl_context, PANGO_DIRECTION_WEAK_LTR);*/
677#endif 900#endif
678} 901}
679 902
680char *
681SDL_GetError () 903char *SDL_GetError ()
682 904
683int 905void SDL_main_hack (SV *real_main)
684SDL_Init (U32 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | PARACHUTE) 906 PROTOTYPE: &
685 907
686void 908int SDL_Init (U32 flags)
909
910int SDL_InitSubSystem (U32 flags)
911
912void SDL_QuitSubSystem (U32 flags)
913
687SDL_Quit () 914void SDL_Quit ()
915
916int SDL_GL_SetAttribute (int attr, int value)
917 C_ARGS: (SDL_GLattr)attr, value
918
919int SDL_GL_GetAttribute (int attr)
920 CODE:
921 if (SDL_GL_GetAttribute ((SDL_GLattr)attr, &RETVAL))
922 XSRETURN_UNDEF;
923 OUTPUT:
924 RETVAL
688 925
689void 926void
690SDL_ListModes (int rgb, int alpha) 927SDL_ListModes (int rgb, int alpha)
691 PPCODE: 928 PPCODE:
692{ 929{
704 SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0); 941 SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0);
705 SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE , 0); 942 SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE , 0);
706 SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0); 943 SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0);
707 944
708 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1); 945 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
709#if SDL_VERSION_ATLEAST(1,2,10)
710 SDL_GL_SetAttribute (SDL_GL_ACCELERATED_VISUAL, 1);
711 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1); 946 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
712#endif
713 947
714 m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL); 948 m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL);
715 949
716 if (m && m != (SDL_Rect **)-1) 950 if (m && m != (SDL_Rect **)-1)
717 while (*m) 951 while (*m)
718 { 952 {
719 if ((*m)->w >= 800 && (*m)->h >= 480) 953 if ((*m)->w >= 400 && (*m)->h >= 300)
720 { 954 {
721 AV *av = newAV (); 955 AV *av = newAV ();
722 av_push (av, newSViv ((*m)->w)); 956 av_push (av, newSViv ((*m)->w));
723 av_push (av, newSViv ((*m)->h)); 957 av_push (av, newSViv ((*m)->h));
724 av_push (av, newSViv (rgb)); 958 av_push (av, newSViv (rgb));
747 ); 981 );
748 982
749 if (RETVAL) 983 if (RETVAL)
750 { 984 {
751 av_clear (texture_av); 985 av_clear (texture_av);
752
753 SDL_WM_SetCaption ("Deliantra MORPG Client " VERSION, "Deliantra");
754#define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name); 986#define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name);
755#include "glfunc.h" 987#include "glfunc.h"
756#undef GL_FUNC 988#undef GL_FUNC
989 if (!gl.ActiveTexture ) gl.ActiveTexture = gl.ActiveTextureARB;
990 if (!gl.MultiTexCoord2f) gl.MultiTexCoord2f = gl.MultiTexCoord2fARB;
757 } 991 }
758} 992}
759 OUTPUT: 993 OUTPUT:
760 RETVAL 994 RETVAL
995
996void
997SDL_WM_SetCaption (const char *title, const char *icon)
761 998
762void 999void
763SDL_GL_SwapBuffers () 1000SDL_GL_SwapBuffers ()
764 1001
765char * 1002char *
766SDL_GetKeyName (int sym) 1003SDL_GetKeyName (int sym)
1004 C_ARGS: (SDLKey)sym
767 1005
768int 1006int
769SDL_GetAppState () 1007SDL_GetAppState ()
770 1008
1009int
1010SDL_GetModState ()
1011
1012int
1013SDL_WaitEvent ()
1014 C_ARGS: 0
1015
771void 1016void
1017SDL_PumpEvents ()
1018
1019void
772poll_events () 1020peep_events ()
773 PPCODE: 1021 PPCODE:
774{ 1022{
775 SDL_Event ev; 1023 SDL_Event ev;
776 1024
777 SDL_PumpEvents (); 1025 SDL_PumpEvents ();
784 { 1032 {
785 case SDL_KEYDOWN: 1033 case SDL_KEYDOWN:
786 case SDL_KEYUP: 1034 case SDL_KEYUP:
787 hv_store (hv, "state", 5, newSViv (ev.key.state), 0); 1035 hv_store (hv, "state", 5, newSViv (ev.key.state), 0);
788 hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0); 1036 hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0);
789 hv_store (hv, "mod", 3, newSViv (ev.key.keysym.mod & MOD_MASK), 0); 1037 hv_store (hv, "mod", 3, newSViv (mod_munge (ev.key.keysym.mod)), 0);
790 hv_store (hv, "cmod", 4, newSViv (SDL_GetModState () & MOD_MASK), 0); /* current mode */ 1038 hv_store (hv, "cmod", 4, newSViv (mod_munge (SDL_GetModState ())), 0); /* current mode */
791 hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0); 1039 hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0);
792 break; 1040 break;
793 1041
794 case SDL_ACTIVEEVENT: 1042 case SDL_ACTIVEEVENT:
795 hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0); 1043 hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0);
813 x = ev.motion.x; 1061 x = ev.motion.x;
814 y = ev.motion.y; 1062 y = ev.motion.y;
815 SDL_PeepEvents (&ev, 1, SDL_GETEVENT, SDL_EVENTMASK (SDL_MOUSEMOTION)); 1063 SDL_PeepEvents (&ev, 1, SDL_GETEVENT, SDL_EVENTMASK (SDL_MOUSEMOTION));
816 } 1064 }
817 1065
818 hv_store (hv, "mod", 3, newSViv (SDL_GetModState () & MOD_MASK), 0); 1066 hv_store (hv, "mod", 3, newSViv (mod_munge (SDL_GetModState ())), 0);
819 hv_store (hv, "state", 5, newSViv (state), 0); 1067 hv_store (hv, "state", 5, newSViv (state), 0);
820 hv_store (hv, "x", 1, newSViv (x), 0); 1068 hv_store (hv, "x", 1, newSViv (x), 0);
821 hv_store (hv, "y", 1, newSViv (y), 0); 1069 hv_store (hv, "y", 1, newSViv (y), 0);
822 hv_store (hv, "xrel", 4, newSViv (xrel), 0); 1070 hv_store (hv, "xrel", 4, newSViv (xrel), 0);
823 hv_store (hv, "yrel", 4, newSViv (yrel), 0); 1071 hv_store (hv, "yrel", 4, newSViv (yrel), 0);
843 1091
844 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("DC::UI::Event", 1)))); 1092 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("DC::UI::Event", 1))));
845 } 1093 }
846} 1094}
847 1095
1096char *
1097SDL_AudioDriverName ()
1098 CODE:
1099{
1100 char buf [256];
1101 if (!SDL_AudioDriverName (buf, sizeof (buf)))
1102 XSRETURN_UNDEF;
1103
1104 RETVAL = buf;
1105}
1106 OUTPUT:
1107 RETVAL
1108
848int 1109int
849Mix_OpenAudio (int frequency = 44100, int format = MIX_DEFAULT_FORMAT, int channels = 2, int chunksize = 4096) 1110Mix_OpenAudio (int frequency = 44100, int format = MIX_DEFAULT_FORMAT, int channels = 2, int chunksize = 4096)
850 POSTCALL: 1111 POSTCALL:
851 Mix_HookMusicFinished (music_finished); 1112 Mix_HookMusicFinished (music_finished);
852 Mix_ChannelFinished (channel_finished); 1113 Mix_ChannelFinished (channel_finished);
853 1114
854void 1115void
855Mix_QuerySpec () 1116Mix_QuerySpec ()
908 } 1169 }
909 } 1170 }
910#endif 1171#endif
911} 1172}
912 1173
913void 1174int
914add_font (char *file) 1175add_font (char *file)
915 CODE: 1176 CODE:
916 FcConfigAppFontAddFile (0, (const FcChar8 *)file); 1177 RETVAL = FcConfigAppFontAddFile (0, (const FcChar8 *)file);
1178 OUTPUT:
1179 RETVAL
1180
1181void
1182IMG_Init (int flags = IMG_INIT_JPG | IMG_INIT_PNG)
1183
1184# MIX_INIT_MP3 gives smpeg + libstdc++ + libgcc_s
1185void
1186Mix_Init (int flags = MIX_INIT_MOD | MIX_INIT_OGG)
917 1187
918void 1188void
919load_image_inline (SV *image_) 1189load_image_inline (SV *image_)
920 ALIAS: 1190 ALIAS:
921 load_image_file = 1 1191 load_image_file = 1
967 1237
968 SDL_LockSurface (surface2); 1238 SDL_LockSurface (surface2);
969 EXTEND (SP, 6); 1239 EXTEND (SP, 6);
970 PUSHs (sv_2mortal (newSViv (surface2->w))); 1240 PUSHs (sv_2mortal (newSViv (surface2->w)));
971 PUSHs (sv_2mortal (newSViv (surface2->h))); 1241 PUSHs (sv_2mortal (newSViv (surface2->h)));
972 PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch))); 1242 PUSHs (sv_2mortal (newSVpvn ((const char *)surface2->pixels, surface2->h * surface2->pitch)));
973 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB))); 1243 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
974 PUSHs (sv_2mortal (newSViv (GL_RGBA))); 1244 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
975 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE))); 1245 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
976 SDL_UnlockSurface (surface2); 1246 SDL_UnlockSurface (surface2);
977 1247
1037#if DEBUG 1307#if DEBUG
1038 VALGRIND_DO_LEAK_CHECK; 1308 VALGRIND_DO_LEAK_CHECK;
1039#endif 1309#endif
1040} 1310}
1041 1311
1312int
1313SvREFCNT (SV *sv)
1314 CODE:
1315 RETVAL = SvREFCNT (sv);
1316 OUTPUT:
1317 RETVAL
1318
1042MODULE = Deliantra::Client PACKAGE = DC::Font 1319MODULE = Deliantra::Client PACKAGE = DC::Font
1043 1320
1044PROTOTYPES: DISABLE 1321PROTOTYPES: DISABLE
1045 1322
1046DC::Font 1323DC::Font
1047new_from_file (SV *class, char *path, int id = 0) 1324new_from_file (SV *klass, char *path, int id = 0)
1048 CODE: 1325 CODE:
1049{ 1326{
1050 int count; 1327 int count;
1051 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count); 1328 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count);
1052 RETVAL = pango_fc_font_description_from_pattern (pattern, 0); 1329 RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
1081 PROTOTYPE: 1358 PROTOTYPE:
1082 CODE: 1359 CODE:
1083 tc_restore (); 1360 tc_restore ();
1084 1361
1085DC::Layout 1362DC::Layout
1086new (SV *class) 1363new (SV *klass)
1087 CODE: 1364 CODE:
1088 New (0, RETVAL, 1, struct cf_layout); 1365 RETVAL = new cf_layout;
1089 1366
1090 RETVAL->pl = pango_layout_new (opengl_context); 1367 RETVAL->pl = pango_layout_new (opengl_context);
1091 RETVAL->r = 1.; 1368 RETVAL->r = 1.;
1092 RETVAL->g = 1.; 1369 RETVAL->g = 1.;
1093 RETVAL->b = 1.; 1370 RETVAL->b = 1.;
1094 RETVAL->a = 1.; 1371 RETVAL->a = 1.;
1095 RETVAL->base_height = MIN_FONT_HEIGHT; 1372 RETVAL->base_height = MIN_FONT_HEIGHT;
1096 RETVAL->font = 0; 1373 RETVAL->font = 0;
1097 RETVAL->rc = rc_alloc ();
1098 1374
1099 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR); 1375 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
1100 layout_update_font (RETVAL); 1376 layout_update_font (RETVAL);
1101 OUTPUT: 1377 OUTPUT:
1102 RETVAL 1378 RETVAL
1103 1379
1104void 1380void
1105DESTROY (DC::Layout self) 1381DESTROY (DC::Layout self)
1106 CODE: 1382 CODE:
1107 g_object_unref (self->pl); 1383 g_object_unref (self->pl);
1108 rc_free (self->rc);
1109 Safefree (self); 1384 delete self;
1110 1385
1111void 1386void
1112set_text (DC::Layout self, SV *text_) 1387set_text (DC::Layout self, SV *text_)
1113 CODE: 1388 CODE:
1114{ 1389{
1240 1515
1241void 1516void
1242set_height (DC::Layout self, int base_height) 1517set_height (DC::Layout self, int base_height)
1243 CODE: 1518 CODE:
1244 if (self->base_height != base_height) 1519 if (self->base_height != base_height)
1245 { 1520 {
1246 self->base_height = base_height; 1521 self->base_height = base_height;
1247 layout_update_font (self); 1522 layout_update_font (self);
1248 } 1523 }
1249 1524
1250void 1525void
1331 PPCODE: 1606 PPCODE:
1332{ 1607{
1333 int line, x; 1608 int line, x;
1334 1609
1335 pango_layout_index_to_line_x (self->pl, index, trailing, &line, &x); 1610 pango_layout_index_to_line_x (self->pl, index, trailing, &line, &x);
1336#if !(defined (PANGO_VERSION_CHECK) && PANGO_VERSION_CHECK (1, 17, 3)) 1611#if !PANGO_VERSION_CHECK (1, 17, 3)
1337 /* pango bug: line is between 1..numlines, not 0..numlines-1 */ 1612 /* pango bug: line is between 1..numlines, not 0..numlines-1 */
1338 --line; 1613 --line;
1339#endif 1614#endif
1340 EXTEND (SP, 2); 1615 EXTEND (SP, 2);
1341 PUSHs (sv_2mortal (newSViv (line))); 1616 PUSHs (sv_2mortal (newSViv (line)));
1368} 1643}
1369 1644
1370void 1645void
1371render (DC::Layout self, float x, float y, int flags = 0) 1646render (DC::Layout self, float x, float y, int flags = 0)
1372 CODE: 1647 CODE:
1373 rc_clear (self->rc); 1648 self->rc.clear ();
1374 pango_opengl_render_layout_subpixel ( 1649 pango_opengl_render_layout_subpixel (
1375 self->pl, 1650 self->pl,
1376 self->rc, 1651 &self->rc,
1377 x * PANGO_SCALE, y * PANGO_SCALE, 1652 x * PANGO_SCALE, y * PANGO_SCALE,
1378 self->r, self->g, self->b, self->a, 1653 self->r, self->g, self->b, self->a,
1379 flags 1654 flags
1380 ); 1655 );
1381 // we assume that context_change actually clears/frees stuff 1656 // we assume that context_change actually clears/frees stuff
1392 gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 1667 gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1393 GL_ONE , GL_ONE_MINUS_SRC_ALPHA); 1668 GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1394 glEnable (GL_ALPHA_TEST); 1669 glEnable (GL_ALPHA_TEST);
1395 glAlphaFunc (GL_GREATER, 7.f / 255.f); 1670 glAlphaFunc (GL_GREATER, 7.f / 255.f);
1396 1671
1397 rc_draw (self->rc); 1672 self->rc.draw ();
1398 1673
1399 glDisable (GL_ALPHA_TEST); 1674 glDisable (GL_ALPHA_TEST);
1400 glDisable (GL_BLEND); 1675 glDisable (GL_BLEND);
1401 glDisable (GL_TEXTURE_2D); 1676 glDisable (GL_TEXTURE_2D);
1402} 1677}
1477 glDisable (GL_ALPHA_TEST); 1752 glDisable (GL_ALPHA_TEST);
1478 glDisable (GL_BLEND); 1753 glDisable (GL_BLEND);
1479 } 1754 }
1480} 1755}
1481 1756
1757void
1758draw_fow_texture (float intensity, int hidden_tex, int name1, uint8_t *data1, float s, float t, int w, int h, float blend = 0.f, int dx = 0, int dy = 0, int name2 = 0, uint8_t *data2 = data1)
1759 PROTOTYPE: @
1760 CODE:
1761{
1762 glEnable (GL_BLEND);
1763 glBlendFunc (intensity ? GL_SRC_ALPHA : GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1764 glEnable (GL_TEXTURE_2D);
1765 glBindTexture (GL_TEXTURE_2D, name1);
1766
1767 glColor3f (intensity, intensity, intensity);
1768 glPushMatrix ();
1769 glScalef (1./3, 1./3, 1.);
1770
1771 if (blend > 0.f)
1772 {
1773 float dx3 = dx * -3.f / w;
1774 float dy3 = dy * -3.f / h;
1775 GLfloat env_color[4] = { 0., 0., 0., blend };
1776
1777 /* interpolate the two shadow textures */
1778 /* stage 0 == rgb(glcolor) + alpha(t0) */
1779 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1780
1781 /* stage 1 == rgb(glcolor) + alpha(interpolate t0, t1, texenv) */
1782 gl.ActiveTexture (GL_TEXTURE1);
1783 glEnable (GL_TEXTURE_2D);
1784 glBindTexture (GL_TEXTURE_2D, name2);
1785 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
1786
1787 /* rgb == rgb(glcolor) */
1788 glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
1789 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
1790 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
1791
1792 /* alpha = interpolate t0, t1 by env_alpha */
1793 glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, env_color);
1794
1795 glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_INTERPOLATE);
1796 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
1797 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
1798
1799 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS);
1800 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
1801
1802 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_CONSTANT);
1803 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA);
1804
1805 glBegin (GL_QUADS);
1806 gl.MultiTexCoord2f (GL_TEXTURE0, 0, 0); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 , dy3 ); glVertex2i (0, 0);
1807 gl.MultiTexCoord2f (GL_TEXTURE0, 0, t); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 , dy3 + t); glVertex2i (0, h);
1808 gl.MultiTexCoord2f (GL_TEXTURE0, s, t); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 + s, dy3 + t); glVertex2i (w, h);
1809 gl.MultiTexCoord2f (GL_TEXTURE0, s, 0); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 + s, dy3 ); glVertex2i (w, 0);
1810 glEnd ();
1811
1812 glDisable (GL_TEXTURE_2D);
1813 gl.ActiveTexture (GL_TEXTURE0);
1814 }
1815 else
1816 {
1817 /* simple blending of one texture, also opengl <1.3 path */
1818 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1819
1820 glBegin (GL_QUADS);
1821 glTexCoord2f (0, 0); glVertex2f (0, 0);
1822 glTexCoord2f (0, t); glVertex2f (0, h);
1823 glTexCoord2f (s, t); glVertex2f (w, h);
1824 glTexCoord2f (s, 0); glVertex2f (w, 0);
1825 glEnd ();
1826 }
1827
1828 /* draw ?-marks or equivalent, this is very clumsy code :/ */
1829 {
1830 int x, y;
1831 int dx3 = dx * 3;
1832 int dy3 = dy * 3;
1833
1834 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1835 glBindTexture (GL_TEXTURE_2D, hidden_tex);
1836 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1837 glTranslatef (-1., -1., 0);
1838 glBegin (GL_QUADS);
1839
1840 for (y = 1; y < h; y += 3)
1841 {
1842 int y1 = y - dy3;
1843 int y1valid = y1 >= 0 && y1 < h;
1844
1845 for (x = 1; x < w; x += 3)
1846 {
1847 int x1 = x - dx3;
1848 uint8_t h1 = data1 [x + y * w] == DARKNESS_ADJUST (255 - FOW_DARKNESS);
1849 uint8_t h2;
1850
1851 if (y1valid && x1 >= 0 && x1 < w)
1852 h2 = data2 [x1 + y1 * w] == DARKNESS_ADJUST (255 - FOW_DARKNESS);
1853 else
1854 h2 = 1; /* out of range == invisible */
1855
1856 if (h1 || h2)
1857 {
1858 float alpha = h1 == h2 ? 1.f : h1 ? 1.f - blend : blend;
1859 glColor4f (1., 1., 1., alpha);
1860
1861 glTexCoord2f (0, 0.); glVertex2i (x , y );
1862 glTexCoord2f (0, 1.); glVertex2i (x , y + 3);
1863 glTexCoord2f (1, 1.); glVertex2i (x + 3, y + 3);
1864 glTexCoord2f (1, 0.); glVertex2i (x + 3, y );
1865 }
1866 }
1867 }
1868 }
1869
1870 glEnd ();
1871
1872 glPopMatrix ();
1873
1874 glDisable (GL_TEXTURE_2D);
1875 glDisable (GL_BLEND);
1876}
1877
1482IV texture_valid_2d (GLint internalformat, GLsizei w, GLsizei h, GLenum format, GLenum type) 1878IV texture_valid_2d (GLint internalformat, GLsizei w, GLsizei h, GLenum format, GLenum type)
1483 CODE: 1879 CODE:
1484{ 1880{
1485 GLint width; 1881 GLint width;
1486 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, internalformat, w, h, 0, format, type, 0); 1882 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, internalformat, w, h, 0, format, type, 0);
1493MODULE = Deliantra::Client PACKAGE = DC::Map 1889MODULE = Deliantra::Client PACKAGE = DC::Map
1494 1890
1495PROTOTYPES: DISABLE 1891PROTOTYPES: DISABLE
1496 1892
1497DC::Map 1893DC::Map
1498new (SV *class) 1894new (SV *klass)
1499 CODE: 1895 CODE:
1500 New (0, RETVAL, 1, struct map); 1896 New (0, RETVAL, 1, mapgrid);
1501 RETVAL->x = 0; 1897 RETVAL->x = 0;
1502 RETVAL->y = 0; 1898 RETVAL->y = 0;
1503 RETVAL->w = 0; 1899 RETVAL->w = 0;
1504 RETVAL->h = 0; 1900 RETVAL->h = 0;
1505 RETVAL->ox = 0; 1901 RETVAL->ox = 0;
1542 1938
1543void 1939void
1544set_smooth (DC::Map self, int face, int smooth, int level) 1940set_smooth (DC::Map self, int face, int smooth, int level)
1545 CODE: 1941 CODE:
1546{ 1942{
1547 tileid texid; 1943 tileid texid;
1548 maptex *tex; 1944 maptex *tex;
1549 1945
1550 if (face < 0 || face >= self->faces) 1946 if (face < 0 || face >= self->faces)
1551 return; 1947 return;
1552 1948
1553 if (smooth < 0 || smooth >= self->faces) 1949 if (smooth < 0 || smooth >= self->faces)
1554 return; 1950 return;
1555 1951
1556 texid = self->face2tile [face]; 1952 texid = self->face2tile [face];
1557 1953
1558 if (!texid) 1954 if (!texid)
1559 return; 1955 return;
1560 1956
1561 tex = self->tex + texid; 1957 tex = self->tex + texid;
1590 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 1986 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1591 // use uglier nearest interpolation because linear suffers 1987 // use uglier nearest interpolation because linear suffers
1592 // from transparent color bleeding and ugly wrapping effects. 1988 // from transparent color bleeding and ugly wrapping effects.
1593 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1989 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1594} 1990}
1991
1992void
1993expire_textures (DC::Map self, int texid, int count)
1994 PPCODE:
1995 for (; texid < self->texs && count; ++texid, --count)
1996 {
1997 maptex *tex = self->tex + texid;
1998
1999 if (tex->name)
2000 {
2001 if (tex->unused)
2002 {
2003 tex->name = 0;
2004 tex->unused = 0;
2005 XPUSHs (sv_2mortal (newSViv (texid)));
2006 }
2007 else
2008 tex->unused = 1;
2009 }
2010 }
1595 2011
1596int 2012int
1597ox (DC::Map self) 2013ox (DC::Map self)
1598 ALIAS: 2014 ALIAS:
1599 oy = 1 2015 oy = 1
1631 self->ox += dx; self->x += dx; 2047 self->ox += dx; self->x += dx;
1632 self->oy += dy; self->y += dy; 2048 self->oy += dy; self->y += dy;
1633 2049
1634 while (self->y < 0) 2050 while (self->y < 0)
1635 { 2051 {
1636 Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y); 2052 prepend (self->row, self->rows, MAP_EXTEND_Y);
1637 2053
1638 self->rows += MAP_EXTEND_Y; 2054 self->rows += MAP_EXTEND_Y;
1639 self->y += MAP_EXTEND_Y; 2055 self->y += MAP_EXTEND_Y;
1640 } 2056 }
1641} 2057}
1642 2058
1643SV * 2059SV *
1644map1a_update (DC::Map self, SV *data_, int extmap) 2060map1a_update (DC::Map self, SV *data_)
1645 CODE: 2061 CODE:
1646{ 2062{
1647 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_); 2063 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1648 uint8_t *data_end = (uint8_t *)SvEND (data_); 2064 uint8_t *data_end = (uint8_t *)SvEND (data_);
1649 mapcell *cell; 2065 mapcell *cell;
1670 2086
1671 //TODO: don't trust server data to be in-range(!) 2087 //TODO: don't trust server data to be in-range(!)
1672 2088
1673 if (flags & 8) 2089 if (flags & 8)
1674 { 2090 {
2091 uint8_t ext, cmd;
2092
1675 if (extmap) 2093 do
1676 { 2094 {
1677 uint8_t ext, cmd; 2095 ext = *data++;
2096 cmd = ext & 0x7f;
1678 2097
1679 do 2098 if (cmd < 4)
2099 cell->darkness = 255 - ext * 64 + 1; /* make sure this doesn't collide with FOW_DARKNESS */
2100 else if (cmd == 5) // health
1680 { 2101 {
1681 ext = *data++;
1682 cmd = ext & 0x3f;
1683
1684 if (cmd < 4)
1685 cell->darkness = 255 - ext * 64 + 1;
1686 else if (cmd == 5) // health
1687 {
1688 cell->stat_width = 1; 2102 cell->stat_width = 1;
1689 cell->stat_hp = *data++; 2103 cell->stat_hp = *data++;
1690 }
1691 else if (cmd == 6) // monster width
1692 cell->stat_width = *data++ + 1;
1693 else if (cmd == 0x47)
1694 {
1695 if (*data == 4)
1696 ; // decode player count
1697
1698 data += *data + 1;
1699 }
1700 else if (cmd == 8) // cell flags
1701 cell->flags = *data++;
1702 else if (ext & 0x40) // unknown, multibyte => skip
1703 data += *data + 1;
1704 else
1705 data++;
1706 } 2104 }
1707 while (ext & 0x80); 2105 else if (cmd == 6) // monster width
2106 cell->stat_width = *data++ + 1;
2107 else if (cmd == 0x47)
2108 {
2109 if (*data == 1) cell->player = data [1];
2110 else if (*data == 2) cell->player = data [2] + (data [1] << 8);
2111 else if (*data == 3) cell->player = data [3] + (data [2] << 8) + (data [1] << 16);
2112 else if (*data == 4) cell->player = data [4] + (data [3] << 8) + (data [2] << 16) + (data [1] << 24);
2113
2114 data += *data + 1;
2115 }
2116 else if (cmd == 8) // cell flags
2117 cell->flags = *data++;
2118 else if (ext & 0x40) // unknown, multibyte => skip
2119 data += *data + 1;
2120 else
2121 data++;
1708 } 2122 }
1709 else 2123 while (ext & 0x80);
1710 cell->darkness = *data++ + 1;
1711 } 2124 }
1712 2125
1713 for (z = 0; z <= 2; ++z) 2126 for (z = 0; z <= 2; ++z)
1714 if (flags & (4 >> z)) 2127 if (flags & (4 >> z))
1715 { 2128 {
1718 cell->tile [z] = self->face2tile [face]; 2131 cell->tile [z] = self->face2tile [face];
1719 2132
1720 if (cell->tile [z]) 2133 if (cell->tile [z])
1721 { 2134 {
1722 maptex *tex = self->tex + cell->tile [z]; 2135 maptex *tex = self->tex + cell->tile [z];
2136 tex->unused = 0;
1723 if (!tex->name) 2137 if (!tex->name)
1724 av_push (missing, newSViv (cell->tile [z])); 2138 av_push (missing, newSViv (cell->tile [z]));
1725 2139
1726 if (tex->smoothtile) 2140 if (tex->smoothtile)
1727 { 2141 {
1728 maptex *smooth = self->tex + tex->smoothtile; 2142 maptex *smooth = self->tex + tex->smoothtile;
2143 smooth->unused = 0;
1729 if (!smooth->name) 2144 if (!smooth->name)
1730 av_push (missing, newSViv (tex->smoothtile)); 2145 av_push (missing, newSViv (tex->smoothtile));
1731 } 2146 }
1732 } 2147 }
1733 } 2148 }
1734 } 2149 }
1735 else 2150 else
1736 cell->darkness = 0; 2151 CELL_CLEAR (cell);
1737 } 2152 }
1738} 2153}
1739 OUTPUT: 2154 OUTPUT:
1740 RETVAL 2155 RETVAL
1741 2156
1761 ? self->row + y 2176 ? self->row + y
1762 : 0; 2177 : 0;
1763 2178
1764 for (x = x0; x < x1; x++) 2179 for (x = x0; x < x1; x++)
1765 { 2180 {
1766 int r = 32, g = 32, b = 32, a = 192; 2181 unsigned int r = 32, g = 32, b = 32, a = 192;
1767 2182
1768 if (row && row->c0 <= x && x < row->c1) 2183 if (row && row->c0 <= x && x < row->c1)
1769 { 2184 {
1770 mapcell *cell = row->col + (x - row->c0); 2185 mapcell *cell = row->col + (x - row->c0);
1771 2186
1773 { 2188 {
1774 maptex tex = self->tex [cell->tile [z]]; 2189 maptex tex = self->tex [cell->tile [z]];
1775 int a0 = 255 - tex.a; 2190 int a0 = 255 - tex.a;
1776 int a1 = tex.a; 2191 int a1 = tex.a;
1777 2192
1778 r = (r * a0 + tex.r * a1) / 255; 2193 r = div255 (r * a0 + tex.r * a1);
1779 g = (g * a0 + tex.g * a1) / 255; 2194 g = div255 (g * a0 + tex.g * a1);
1780 b = (b * a0 + tex.b * a1) / 255; 2195 b = div255 (b * a0 + tex.b * a1);
1781 a = (a * a0 + tex.a * a1) / 255; 2196 a = div255 (a * a0 + tex.a * a1);
1782 } 2197 }
1783 } 2198 }
1784 2199
1785 *map++ = (r ) 2200 *map++ = (r )
1786 | (g << 8) 2201 | (g << 8)
1787 | (b << 16) 2202 | (b << 16)
1788 | (a << 24); 2203 | (a << 24);
1789 } 2204 }
1790 } 2205 }
1791 2206
1792 RETVAL = map_sv; 2207 RETVAL = map_sv;
1793} 2208}
1794 OUTPUT: 2209 OUTPUT:
1795 RETVAL 2210 RETVAL
1796 2211
1797void 2212void
1798draw (DC::Map self, int mx, int my, int sw, int sh, int T) 2213draw (DC::Map self, int mx, int my, int sw, int sh, int Tw, int Th, U32 player = 0xffffffff, int sdx = 0, int sdy = 0)
1799 CODE: 2214 CODE:
1800{ 2215{
1801 int x, y, z; 2216 int x, y, z;
1802 2217
1803 HV *smooth = (HV *)sv_2mortal ((SV *)newHV ());
1804 uint32_t smooth_level[256 / 32]; // one bit for every possible smooth level
1805 static uint8_t smooth_max[256][256]; // egad, fast and wasteful on memory (64k) 2218 static uint8_t smooth_max[256][256]; // egad, fast and wasteful on memory (64k), also, static!
1806 smooth_key skey; 2219 int pl_x, pl_y;
1807 2220 maptex pl_tex;
1808 rc_t *rc = rc_alloc (); 2221 rc_t rc;
2222 rc_t rc_ov;
1809 rc_key_t key; 2223 rc_key_t key;
1810 rc_array_t *arr; 2224 rc_t::array_t *arr;
1811 2225
2226 pl_tex.name = 0;
2227
1812 // thats current max. sorry. 2228 // that's current max. sorry.
1813 if (sw > 255) sw = 255; 2229 if (sw > 255) sw = 255;
1814 if (sh > 255) sh = 255; 2230 if (sh > 255) sh = 255;
1815
1816 // clear key, in case of extra padding
1817 memset (&skey, 0, sizeof (skey));
1818 2231
1819 memset (&key, 0, sizeof (key)); 2232 memset (&key, 0, sizeof (key));
1820 key.r = 255; 2233 key.r = 255;
1821 key.g = 255; 2234 key.g = 255;
1822 key.b = 255; 2235 key.b = 255;
1823 key.a = 255; 2236 key.a = 255;
1824 key.mode = GL_QUADS; 2237 key.mode = GL_QUADS;
1825 key.format = GL_T2F_V3F; 2238 key.format = GL_T2F_V3F;
1826 key.texname = -1;
1827 2239
1828 mx += self->x; 2240 mx += self->x;
1829 my += self->y; 2241 my += self->y;
1830 2242
1831 // first pass: determine smooth_max 2243 // first pass: determine smooth_max
1832 // rather ugly, if you ask me 2244 // rather ugly, if you ask me
1833 // could also be stored inside mapcell and updated on change 2245 // could also be stored inside mapcell and updated on change
1834 memset (smooth_max, 0, sizeof (smooth_max)); 2246 memset (smooth_max, 0, sizeof (smooth_max[0]) * (sh + 1));
1835 2247
1836 for (y = 0; y < sh; y++) 2248 for (y = 0; y < sh; y++)
1837 if (0 <= y + my && y + my < self->rows) 2249 if (0 <= y + my && y + my < self->rows)
1838 { 2250 {
1839 maprow *row = self->row + (y + my); 2251 maprow *row = self->row + (y + my);
1854 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2266 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1855 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 2267 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1856 2268
1857 for (z = 0; z <= 2; z++) 2269 for (z = 0; z <= 2; z++)
1858 { 2270 {
1859 memset (smooth_level, 0, sizeof (smooth_level)); 2271 std::bitset<256> smooth_level; // one bit for every possible smooth level
2272 smooth_key skey;
2273 smooth_hash smooth;
2274 key.texname = -1;
1860 2275
1861 for (y = 0; y < sh; y++) 2276 for (y = 0; y < sh; y++)
1862 if (0 <= y + my && y + my < self->rows) 2277 if (0 <= y + my && y + my < self->rows)
1863 { 2278 {
1864 maprow *row = self->row + (y + my); 2279 maprow *row = self->row + (y + my);
1874 maptex tex = self->tex [tile]; 2289 maptex tex = self->tex [tile];
1875 int px, py; 2290 int px, py;
1876 2291
1877 if (key.texname != tex.name) 2292 if (key.texname != tex.name)
1878 { 2293 {
2294 self->tex [tile].unused = 0;
2295
1879 if (!tex.name) 2296 if (!tex.name)
1880 tex = self->tex [2]; /* missing, replace by noface */ 2297 tex = self->tex [TEXID_NOFACE]; /* missing, replace by noface */
1881 2298
1882 key.texname = tex.name; 2299 key.texname = tex.name;
1883 arr = rc_array (rc, &key); 2300 arr = &rc.array (key);
1884 } 2301 }
1885 2302
1886 px = (x + 1) * T - tex.w; 2303 px = (x + 1) * Th - tex.w;
1887 py = (y + 1) * T - tex.h; 2304 py = (y + 1) * Tw - tex.h;
1888 2305
1889 rc_t2f_v3f (arr, 0 , 0 , px , py , 0); 2306 if (ecb_expect_false (cell->player == player) && ecb_expect_false (z == 2))
1890 rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0);
1891 rc_t2f_v3f (arr, tex.s, tex.t, px + tex.w, py + tex.h, 0);
1892 rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0);
1893
1894 if (cell->flags && z == 2)
1895 { 2307 {
1896 // overlays such as the speech bubble, probably more to come 2308 pl_x = px;
1897 if (cell->flags & 1) 2309 pl_y = py;
2310 pl_tex = tex;
1898 { 2311 continue;
1899 maptex tex = self->tex [1];
1900 int px = x * T + T * 2 / 32;
1901 int py = y * T - T * 6 / 32;
1902
1903 if (tex.name)
1904 {
1905 if (key.texname != tex.name)
1906 {
1907 key.texname = tex.name;
1908 arr = rc_array (rc, &key);
1909 }
1910
1911 rc_t2f_v3f (arr, 0 , 0 , px , py , 0);
1912 rc_t2f_v3f (arr, 0 , tex.t, px , py + T, 0);
1913 rc_t2f_v3f (arr, tex.s, tex.t, px + T, py + T, 0);
1914 rc_t2f_v3f (arr, tex.s, 0 , px + T, py , 0);
1915 }
1916 }
1917 } 2312 }
2313
2314 arr->t2f_v3f (0 , 0 , px , py , 0);
2315 arr->t2f_v3f (0 , tex.t, px , py + tex.h, 0);
2316 arr->t2f_v3f (tex.s, tex.t, px + tex.w, py + tex.h, 0);
2317 arr->t2f_v3f (tex.s, 0 , px + tex.w, py , 0);
1918 2318
1919 // update smooth hash 2319 // update smooth hash
1920 if (tex.smoothtile) 2320 if (tex.smoothtile)
1921 { 2321 {
1922 skey.tile = tex.smoothtile; 2322 skey.tile = tex.smoothtile;
1923 skey.level = tex.smoothlevel; 2323 skey.level = tex.smoothlevel;
1924 2324
1925 smooth_level [tex.smoothlevel >> 5] |= ((uint32_t)1) << (tex.smoothlevel & 31); 2325 smooth_level[tex.smoothlevel] = 1;
1926 2326
1927 // add bits to current tile and all neighbours. skey.x|y is 2327 // add bits to current tile and all neighbours. skey.x|y is
1928 // shifted +1|+1 so we always stay positive. 2328 // shifted +1|+1 so we always stay positive.
1929 2329
1930 // bits is ___n cccc CCCC bbbb 2330 // bits is ___n cccc CCCC bbbb
1938 2338
1939 // corners: 1 ┛· 2 ·┗ 4 ·· 8 ·· 2339 // corners: 1 ┛· 2 ·┗ 4 ·· 8 ··
1940 // ·· ·· ·┏ ┓· 2340 // ·· ·· ·┏ ┓·
1941 2341
1942 // full tile 2342 // full tile
1943 skey.x = x + 1; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x1000); 2343 skey.x = x + 1; skey.y = y + 1; smooth_or_bits (smooth, skey, 0x1000);
1944 2344
1945 // borders 2345 // borders
1946 skey.x = x + 2; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0091); 2346 skey.x = x + 2; skey.y = y + 1; smooth_or_bits (smooth, skey, 0x0091);
1947 skey.x = x + 1; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0032); 2347 skey.x = x + 1; skey.y = y + 2; smooth_or_bits (smooth, skey, 0x0032);
1948 skey.x = x ; skey.y = y + 1; smooth_or_bits (smooth, &skey, 0x0064); 2348 skey.x = x ; skey.y = y + 1; smooth_or_bits (smooth, skey, 0x0064);
1949 skey.x = x + 1; skey.y = y ; smooth_or_bits (smooth, &skey, 0x00c8); 2349 skey.x = x + 1; skey.y = y ; smooth_or_bits (smooth, skey, 0x00c8);
1950 2350
1951 // corners 2351 // corners
1952 skey.x = x + 2; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0100); 2352 skey.x = x + 2; skey.y = y + 2; smooth_or_bits (smooth, skey, 0x0100);
1953 skey.x = x ; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0200); 2353 skey.x = x ; skey.y = y + 2; smooth_or_bits (smooth, skey, 0x0200);
1954 skey.x = x ; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0400); 2354 skey.x = x ; skey.y = y ; smooth_or_bits (smooth, skey, 0x0400);
1955 skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0800); 2355 skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, skey, 0x0800);
2356 }
2357 }
2358
2359 if (ecb_expect_false (z == 2) && ecb_expect_false (cell->flags))
2360 {
2361 // overlays such as the speech bubble, probably more to come
2362 if (cell->flags & 1)
2363 {
2364 rc_key_t key_ov = key;
2365 maptex tex = self->tex[TEXID_SPEECH];
2366 int px = x * Tw + Tw * 2 / 32;
2367 int py = y * Th - Th * 6 / 32;
2368
2369 key_ov.texname = tex.name;
2370 rc_t::array_t &arr = rc_ov.array (key_ov);
2371
2372 arr.t2f_v3f (0 , 0 , px , py , 0);
2373 arr.t2f_v3f (0 , tex.t, px , py + Th, 0);
2374 arr.t2f_v3f (tex.s, tex.t, px + Tw, py + Th, 0);
2375 arr.t2f_v3f (tex.s, 0 , px + Tw, py , 0);
1956 } 2376 }
1957 } 2377 }
1958 } 2378 }
1959 } 2379 }
1960 2380
1961 rc_draw (rc); 2381 rc.draw ();
1962 rc_clear (rc); 2382 rc.clear ();
1963 2383
1964 // go through all smoothlevels, lowest to highest, then draw. 2384 // go through all smoothlevels, lowest to highest, then draw.
1965 // this is basically counting sort 2385 // this is basically counting sort
1966 { 2386 {
1967 int w, b; 2387 int w, b;
1968 2388
1969 glEnable (GL_TEXTURE_2D); 2389 glEnable (GL_TEXTURE_2D);
1970 glBegin (GL_QUADS); 2390 glBegin (GL_QUADS);
1971 for (w = 0; w < 256 / 32; ++w) 2391 for (int level = 0; level < smooth_level.size (); ++level)
2392 if (smooth_level[level])
2393 for (auto &&it = smooth.begin (); it != smooth.end (); ++it)
1972 { 2394 {
1973 uint32_t smask = smooth_level [w]; 2395 smooth_key &skey = it->first;
1974 if (smask) 2396 IV bits = it->second;
1975 for (b = 0; b < 32; ++b) 2397
1976 if (smask & (((uint32_t)1) << b)) 2398 if (!(bits & 0x1000)
2399 && skey.level == level
2400 && level > smooth_max [skey.x][skey.y])
1977 { 2401 {
1978 int level = (w << 5) | b; 2402 maptex tex = self->tex [skey.tile];
2403 int px = (((int)skey.x) - 1) * Tw;
2404 int py = (((int)skey.y) - 1) * Th;
2405 int border = bits & 15;
2406 int corner = (bits >> 8) & ~(bits >> 4) & 15;
2407 float dx = tex.s * .0625f; // 16 images/row
2408 float dy = tex.t * .5f ; // 2 images/column
2409
1979 HE *he; 2410 if (tex.name)
1980
1981 hv_iterinit (smooth);
1982 while ((he = hv_iternext (smooth)))
1983 { 2411 {
1984 smooth_key *skey = (smooth_key *)HeKEY (he); 2412 // this time avoiding texture state changes
1985 IV bits = SvIVX (HeVAL (he)); 2413 // save gobs of state changes.
1986 2414 if (key.texname != tex.name)
1987 if (!(bits & 0x1000)
1988 && skey->level == level
1989 && level > smooth_max [skey->x][skey->y])
1990 { 2415 {
1991 maptex tex = self->tex [skey->tile]; 2416 self->tex [skey.tile].unused = 0;
1992 int px = (((int)skey->x) - 1) * T;
1993 int py = (((int)skey->y) - 1) * T;
1994 int border = bits & 15;
1995 int corner = (bits >> 8) & ~(bits >> 4) & 15;
1996 float dx = tex.s * .0625f; // 16 images/row
1997 float dy = tex.t * .5f ; // 2 images/column
1998 2417
1999 if (tex.name)
2000 {
2001 // this time avoiding texture state changes
2002 // save gobs of state changes.
2003 if (key.texname != tex.name)
2004 {
2005 glEnd (); 2418 glEnd ();
2006 glBindTexture (GL_TEXTURE_2D, key.texname = tex.name); 2419 glBindTexture (GL_TEXTURE_2D, key.texname = tex.name);
2007 glBegin (GL_QUADS); 2420 glBegin (GL_QUADS);
2008 } 2421 }
2009 2422
2010 if (border) 2423 if (border)
2011 { 2424 {
2012 float ox = border * dx; 2425 float ox = border * dx;
2013 2426
2014 glTexCoord2f (ox , 0.f ); glVertex2i (px , py ); 2427 glTexCoord2f (ox , 0.f ); glVertex2i (px , py );
2015 glTexCoord2f (ox , dy ); glVertex2i (px , py + T); 2428 glTexCoord2f (ox , dy ); glVertex2i (px , py + Th);
2016 glTexCoord2f (ox + dx, dy ); glVertex2i (px + T, py + T); 2429 glTexCoord2f (ox + dx, dy ); glVertex2i (px + Tw, py + Th);
2017 glTexCoord2f (ox + dx, 0.f ); glVertex2i (px + T, py ); 2430 glTexCoord2f (ox + dx, 0.f ); glVertex2i (px + Tw, py );
2018 } 2431 }
2019 2432
2020 if (corner) 2433 if (corner)
2021 { 2434 {
2022 float ox = corner * dx; 2435 float ox = corner * dx;
2023 2436
2024 glTexCoord2f (ox , dy ); glVertex2i (px , py ); 2437 glTexCoord2f (ox , dy ); glVertex2i (px , py );
2025 glTexCoord2f (ox , dy * 2.f); glVertex2i (px , py + T); 2438 glTexCoord2f (ox , dy * 2.f); glVertex2i (px , py + Th);
2026 glTexCoord2f (ox + dx, dy * 2.f); glVertex2i (px + T, py + T); 2439 glTexCoord2f (ox + dx, dy * 2.f); glVertex2i (px + Tw, py + Th);
2027 glTexCoord2f (ox + dx, dy ); glVertex2i (px + T, py ); 2440 glTexCoord2f (ox + dx, dy ); glVertex2i (px + Tw, py );
2028 }
2029 }
2030 } 2441 }
2031 } 2442 }
2032 } 2443 }
2033 } 2444 }
2034 2445
2035 glEnd (); 2446 glEnd ();
2036 glDisable (GL_TEXTURE_2D); 2447 glDisable (GL_TEXTURE_2D);
2037 key.texname = -1; 2448 key.texname = -1;
2038 } 2449 }
2039
2040 hv_clear (smooth);
2041 } 2450 }
2042 2451
2452 if (pl_tex.name)
2453 {
2454 maptex tex = pl_tex;
2455 int px = pl_x + sdx;
2456 int py = pl_y + sdy;
2457
2458 key.texname = tex.name;
2459 rc_t::array_t &arr = rc.array (key);
2460
2461 arr.t2f_v3f (0 , 0 , px , py , 0);
2462 arr.t2f_v3f (0 , tex.t, px , py + tex.h, 0);
2463 arr.t2f_v3f (tex.s, tex.t, px + tex.w, py + tex.h, 0);
2464 arr.t2f_v3f (tex.s, 0 , px + tex.w, py , 0);
2465
2466 rc.draw ();
2467 }
2468
2469 rc_ov.draw ();
2470 rc_ov.clear ();
2471
2043 glDisable (GL_BLEND); 2472 glDisable (GL_BLEND);
2044 rc_free (rc);
2045 2473
2046 // top layer: overlays such as the health bar 2474 // top layer: overlays such as the health bar
2047 for (y = 0; y < sh; y++) 2475 for (y = 0; y < sh; y++)
2048 if (0 <= y + my && y + my < self->rows) 2476 if (0 <= y + my && y + my < self->rows)
2049 { 2477 {
2052 for (x = 0; x < sw; x++) 2480 for (x = 0; x < sw; x++)
2053 if (row->c0 <= x + mx && x + mx < row->c1) 2481 if (row->c0 <= x + mx && x + mx < row->c1)
2054 { 2482 {
2055 mapcell *cell = row->col + (x + mx - row->c0); 2483 mapcell *cell = row->col + (x + mx - row->c0);
2056 2484
2057 int px = x * T; 2485 int px = x * Tw;
2058 int py = y * T; 2486 int py = y * Th;
2487
2488 if (ecb_expect_false (cell->player == player))
2489 {
2490 px += sdx;
2491 py += sdy;
2492 }
2059 2493
2060 if (cell->stat_hp) 2494 if (cell->stat_hp)
2061 { 2495 {
2062 int width = cell->stat_width * T; 2496 int width = cell->stat_width * Tw;
2063 int thick = (sh * T / 32 + 27) / 28 + 1 + cell->stat_width; 2497 int thick = (sh * Th / 32 + 27) / 28 + 1 + cell->stat_width;
2064 2498
2065 glColor3ub (0, 0, 0); 2499 glColor3ub (0, 0, 0);
2066 glRectf (px + 1, py - thick - 2, 2500 glRectf (px + 1, py - thick - 2,
2067 px + width - 1, py); 2501 px + width - 1, py);
2068 2502
2074 } 2508 }
2075 } 2509 }
2076} 2510}
2077 2511
2078void 2512void
2079draw_magicmap (DC::Map self, int dx, int dy, int w, int h, unsigned char *data) 2513draw_magicmap (DC::Map self, int w, int h, unsigned char *data)
2080 CODE: 2514 CODE:
2081{ 2515{
2082 static float color[16][3] = { 2516 static float color[16][3] = {
2083 { 0.00F, 0.00F, 0.00F }, 2517 { 0.00f, 0.00f, 0.00f },
2084 { 1.00F, 1.00F, 1.00F }, 2518 { 1.00f, 1.00f, 1.00f },
2085 { 0.00F, 0.00F, 0.55F }, 2519 { 0.00f, 0.00f, 0.55f },
2086 { 1.00F, 0.00F, 0.00F }, 2520 { 1.00f, 0.00f, 0.00f },
2087 2521
2088 { 1.00F, 0.54F, 0.00F }, 2522 { 1.00f, 0.54f, 0.00f },
2089 { 0.11F, 0.56F, 1.00F }, 2523 { 0.11f, 0.56f, 1.00f },
2090 { 0.93F, 0.46F, 0.00F }, 2524 { 0.93f, 0.46f, 0.00f },
2091 { 0.18F, 0.54F, 0.34F }, 2525 { 0.18f, 0.54f, 0.34f },
2092 2526
2093 { 0.56F, 0.73F, 0.56F }, 2527 { 0.56f, 0.73f, 0.56f },
2094 { 0.80F, 0.80F, 0.80F }, 2528 { 0.80f, 0.80f, 0.80f },
2095 { 0.55F, 0.41F, 0.13F }, 2529 { 0.55f, 0.41f, 0.13f },
2096 { 0.99F, 0.77F, 0.26F }, 2530 { 0.99f, 0.77f, 0.26f },
2097 2531
2098 { 0.74F, 0.65F, 0.41F }, 2532 { 0.74f, 0.65f, 0.41f },
2099 2533
2100 { 0.00F, 1.00F, 1.00F }, 2534 { 0.00f, 1.00f, 1.00f },
2101 { 1.00F, 0.00F, 1.00F }, 2535 { 1.00f, 0.00f, 1.00f },
2102 { 1.00F, 1.00F, 0.00F }, 2536 { 1.00f, 1.00f, 0.00f },
2103 }; 2537 };
2104 2538
2105 int x, y; 2539 int x, y;
2106 2540
2107 glEnable (GL_TEXTURE_2D); 2541 glEnable (GL_TEXTURE_2D);
2542 /* GL_REPLACE would be correct, as we don't need to modulate alpha,
2543 * but the nvidia driver (185.18.14) mishandles alpha textures
2544 * and takes the colour from god knows where instead of using
2545 * Cp. MODULATE results in the same colour, but slightly different
2546 * alpha, but atcually gives us the correct colour with nvidia.
2547 */
2108 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 2548 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2109 glEnable (GL_BLEND); 2549 glEnable (GL_BLEND);
2110 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2550 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2111 glBegin (GL_QUADS); 2551 glBegin (GL_QUADS);
2112 2552
2113 for (y = 0; y < h; y++) 2553 for (y = 0; y < h; y++)
2117 2557
2118 if (m) 2558 if (m)
2119 { 2559 {
2120 float *c = color [m & 15]; 2560 float *c = color [m & 15];
2121 2561
2122 float tx1 = m & 0x40 ? 0.5 : 0.; 2562 float tx1 = m & 0x40 ? 0.5f : 0.f;
2123 float tx2 = tx1 + 0.5; 2563 float tx2 = tx1 + 0.5f;
2124 2564
2125 glColor4f (c[0], c[1], c[2], 0.75); 2565 glColor4f (c[0], c[1], c[2], 1);
2126 glTexCoord2f (tx1, 0.); glVertex2i (x , y ); 2566 glTexCoord2f (tx1, 0.); glVertex2i (x , y );
2127 glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1); 2567 glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
2128 glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1); 2568 glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
2129 glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y ); 2569 glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
2130 } 2570 }
2138void 2578void
2139fow_texture (DC::Map self, int mx, int my, int sw, int sh) 2579fow_texture (DC::Map self, int mx, int my, int sw, int sh)
2140 PPCODE: 2580 PPCODE:
2141{ 2581{
2142 int x, y; 2582 int x, y;
2143 int sw1 = sw + 2; 2583 int sw1 = sw + 2;
2144 int sh1 = sh + 2; 2584 int sh1 = sh + 2;
2145 int sh3 = sh * 3; 2585 int sh3 = sh * 3;
2146 int sw34 = (sw * 3 + 3) & ~3; 2586 int sw3 = sw * 3;
2587 SV *darkness3_sv = sv_2mortal (newSV (sw3 * sh3));
2588 uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv);
2147 uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1); 2589 uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1);
2148 SV *darkness3_sv = sv_2mortal (newSV (sw34 * sh3)); 2590 memset (darkness1, 0, sw1*sh1);
2149 uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv);
2150 2591
2151 SvPOK_only (darkness3_sv); 2592 SvPOK_only (darkness3_sv);
2152 SvCUR_set (darkness3_sv, sw34 * sh3); 2593 SvCUR_set (darkness3_sv, sw3 * sh3);
2153 2594
2154 mx += self->x - 1; 2595 mx += self->x - 1;
2155 my += self->y - 1; 2596 my += self->y - 1;
2156
2157 memset (darkness1, 255, sw1 * sh1);
2158 2597
2159 for (y = 0; y < sh1; y++) 2598 for (y = 0; y < sh1; y++)
2160 if (0 <= y + my && y + my < self->rows) 2599 if (0 <= y + my && y + my < self->rows)
2161 { 2600 {
2162 maprow *row = self->row + (y + my); 2601 maprow *row = self->row + (y + my);
2165 if (row->c0 <= x + mx && x + mx < row->c1) 2604 if (row->c0 <= x + mx && x + mx < row->c1)
2166 { 2605 {
2167 mapcell *cell = row->col + (x + mx - row->c0); 2606 mapcell *cell = row->col + (x + mx - row->c0);
2168 2607
2169 darkness1 [y * sw1 + x] = cell->darkness 2608 darkness1 [y * sw1 + x] = cell->darkness
2170 ? 255 - (cell->darkness - 1) 2609 ? DARKNESS_ADJUST (255 - (cell->darkness - 1))
2171 : 255 - FOW_DARKNESS; 2610 : DARKNESS_ADJUST (255 - FOW_DARKNESS);
2172 } 2611 }
2173 } 2612 }
2174 2613
2175 for (y = 0; y < sh; ++y) 2614 for (y = 0; y < sh; ++y)
2176 for (x = 0; x < sw; ++x) 2615 for (x = 0; x < sw; ++x)
2195 2634
2196 uint8_t r13 = (d13 + d23 + d12) / 3; 2635 uint8_t r13 = (d13 + d23 + d12) / 3;
2197 uint8_t r23 = d23; 2636 uint8_t r23 = d23;
2198 uint8_t r33 = (d23 + d33 + d32) / 3; 2637 uint8_t r33 = (d23 + d33 + d32) / 3;
2199 2638
2200 darkness3 [(y * 3 ) * sw34 + (x * 3 )] = MAX (d22, r11); 2639 darkness3 [(y * 3 ) * sw3 + (x * 3 )] = MAX (d22, r11);
2201 darkness3 [(y * 3 ) * sw34 + (x * 3 + 1)] = MAX (d22, r21); 2640 darkness3 [(y * 3 ) * sw3 + (x * 3 + 1)] = MAX (d22, r21);
2202 darkness3 [(y * 3 ) * sw34 + (x * 3 + 2)] = MAX (d22, r31); 2641 darkness3 [(y * 3 ) * sw3 + (x * 3 + 2)] = MAX (d22, r31);
2203 darkness3 [(y * 3 + 1) * sw34 + (x * 3 )] = MAX (d22, r12); 2642 darkness3 [(y * 3 + 1) * sw3 + (x * 3 )] = MAX (d22, r12);
2204 darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 1)] = MAX (d22, r22); 2643 darkness3 [(y * 3 + 1) * sw3 + (x * 3 + 1)] = MAX (d22, r22); /* this MUST be == d22 */
2205 darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 2)] = MAX (d22, r32); 2644 darkness3 [(y * 3 + 1) * sw3 + (x * 3 + 2)] = MAX (d22, r32);
2206 darkness3 [(y * 3 + 2) * sw34 + (x * 3 )] = MAX (d22, r13); 2645 darkness3 [(y * 3 + 2) * sw3 + (x * 3 )] = MAX (d22, r13);
2207 darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 1)] = MAX (d22, r23); 2646 darkness3 [(y * 3 + 2) * sw3 + (x * 3 + 1)] = MAX (d22, r23);
2208 darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 2)] = MAX (d22, r33); 2647 darkness3 [(y * 3 + 2) * sw3 + (x * 3 + 2)] = MAX (d22, r33);
2209 } 2648 }
2210 2649
2211 free (darkness1); 2650 free (darkness1);
2212 2651
2213 EXTEND (SP, 3); 2652 EXTEND (SP, 3);
2214 PUSHs (sv_2mortal (newSViv (sw34))); 2653 PUSHs (sv_2mortal (newSViv (sw3)));
2215 PUSHs (sv_2mortal (newSViv (sh3))); 2654 PUSHs (sv_2mortal (newSViv (sh3)));
2216 PUSHs (darkness3_sv); 2655 PUSHs (darkness3_sv);
2217} 2656}
2218 2657
2219SV * 2658SV *
2282 else 2721 else
2283 *data++ = 0; 2722 *data++ = 0;
2284 } 2723 }
2285 } 2724 }
2286 2725
2726 /* if size is w*h + 5 then no data has been found */
2727 if (data - (uint8_t *)SvPVX (data_sv) != w * h + 5)
2728 {
2287 SvPOK_only (data_sv); 2729 SvPOK_only (data_sv);
2288 SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv)); 2730 SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
2731 }
2732
2289 RETVAL = data_sv; 2733 RETVAL = data_sv;
2290} 2734}
2291 OUTPUT: 2735 OUTPUT:
2292 RETVAL 2736 RETVAL
2293 2737
2294void 2738void
2295set_rect (DC::Map self, int x0, int y0, uint8_t *data) 2739set_rect (DC::Map self, int x0, int y0, SV *data_sv)
2296 PPCODE: 2740 PPCODE:
2297{ 2741{
2298 int x, y, z; 2742 int x, y, z;
2299 int w, h; 2743 int w, h;
2300 int x1, y1; 2744 int x1, y1;
2745 STRLEN len;
2746 uint8_t *data, *end;
2747
2748 len = SvLEN (data_sv);
2749 SvGROW (data_sv, len + 8); // reserve at least 7+ bytes more
2750 data = (uint8_t *)SvPVbyte_nolen (data_sv);
2751 end = data + len + 8;
2752
2753 if (len < 5)
2754 XSRETURN_EMPTY;
2301 2755
2302 if (*data++ != 0) 2756 if (*data++ != 0)
2303 XSRETURN_EMPTY; /* version mismatch */ 2757 XSRETURN_EMPTY; /* version mismatch */
2304 2758
2305 w = *data++ << 8; w |= *data++; 2759 w = *data++ << 8; w |= *data++;
2320 { 2774 {
2321 maprow *row = map_get_row (self, y); 2775 maprow *row = map_get_row (self, y);
2322 2776
2323 for (x = x0; x < x1; x++) 2777 for (x = x0; x < x1; x++)
2324 { 2778 {
2779 uint8_t flags;
2780
2781 if (data + 7 >= end)
2782 XSRETURN_EMPTY;
2783
2325 uint8_t flags = *data++; 2784 flags = *data++;
2326 2785
2327 if (flags) 2786 if (flags)
2328 { 2787 {
2329 mapcell *cell = row_get_cell (row, x); 2788 mapcell *cell = row_get_cell (row, x);
2330 tileid tile[3] = { 0, 0, 0 }; 2789 tileid tile[3] = { 0, 0, 0 };
2333 if (flags & 2) { tile[1] = *data++ << 8; tile[1] |= *data++; } 2792 if (flags & 2) { tile[1] = *data++ << 8; tile[1] |= *data++; }
2334 if (flags & 4) { tile[2] = *data++ << 8; tile[2] |= *data++; } 2793 if (flags & 4) { tile[2] = *data++ << 8; tile[2] |= *data++; }
2335 2794
2336 if (cell->darkness == 0) 2795 if (cell->darkness == 0)
2337 { 2796 {
2338 cell->darkness = 0; 2797 /*cell->darkness = 0;*/
2798 EXTEND (SP, 3);
2339 2799
2340 for (z = 0; z <= 2; z++) 2800 for (z = 0; z <= 2; z++)
2341 { 2801 {
2342 tileid t = tile [z]; 2802 tileid t = tile [z];
2343 2803
2344 if (t >= self->texs || (t && !self->tex [t].name)) 2804 if (t >= self->texs || (t && !self->tex [t].name))
2345 { 2805 {
2346 XPUSHs (sv_2mortal (newSViv (t))); 2806 PUSHs (sv_2mortal (newSViv (t)));
2347 need_texid (self, t); 2807 need_texid (self, t);
2348 } 2808 }
2349 2809
2350 cell->tile [z] = t; 2810 cell->tile [z] = t;
2351 } 2811 }
2356} 2816}
2357 2817
2358MODULE = Deliantra::Client PACKAGE = DC::RW 2818MODULE = Deliantra::Client PACKAGE = DC::RW
2359 2819
2360DC::RW 2820DC::RW
2361new (SV *class, SV *data_sv) 2821new (SV *klass, SV *data_sv)
2362 CODE: 2822 CODE:
2363{ 2823{
2364 STRLEN datalen; 2824 STRLEN datalen;
2365 char *data = SvPVbyte (data_sv, datalen); 2825 char *data = SvPVbyte (data_sv, datalen);
2366 2826
2368} 2828}
2369 OUTPUT: 2829 OUTPUT:
2370 RETVAL 2830 RETVAL
2371 2831
2372DC::RW 2832DC::RW
2373new_from_file (SV *class, const char *path, const char *mode = "rb") 2833new_from_file (SV *klass, const char *path, const char *mode = "rb")
2374 CODE: 2834 CODE:
2375 RETVAL = SDL_RWFromFile (path, mode); 2835 RETVAL = SDL_RWFromFile (path, mode);
2376 OUTPUT: 2836 OUTPUT:
2377 RETVAL 2837 RETVAL
2378 2838
2396 if (RETVAL < 0) 2856 if (RETVAL < 0)
2397 { 2857 {
2398 RETVAL = Mix_GroupOldest (-1); 2858 RETVAL = Mix_GroupOldest (-1);
2399 2859
2400 if (RETVAL < 0) 2860 if (RETVAL < 0)
2861 {
2862 // happens sometimes, maybe it just stopped playing(?)
2863 RETVAL = Mix_GroupAvailable (-1);
2864
2865 if (RETVAL < 0)
2401 XSRETURN_UNDEF; 2866 XSRETURN_UNDEF;
2402 2867 }
2868 else
2403 Mix_HaltChannel (RETVAL); 2869 Mix_HaltChannel (RETVAL);
2404 } 2870 }
2405 2871
2406 Mix_UnregisterAllEffects (RETVAL); 2872 Mix_UnregisterAllEffects (RETVAL);
2407 Mix_Volume (RETVAL, 128); 2873 Mix_Volume (RETVAL, 128);
2408} 2874}
2455void 2921void
2456set_position_r (DC::Channel self, int dx, int dy, int maxdistance) 2922set_position_r (DC::Channel self, int dx, int dy, int maxdistance)
2457 CODE: 2923 CODE:
2458{ 2924{
2459 int distance = sqrtf (dx * dx + dy * dy) * (255.f / sqrtf (maxdistance * maxdistance)); 2925 int distance = sqrtf (dx * dx + dy * dy) * (255.f / sqrtf (maxdistance * maxdistance));
2460 int angle = 360 + (int)roundf (atan2f (dx, -dy) * 180.f / (float)M_PI); 2926 int angle = atan2f (dx, -dy) * 180.f / (float)M_PI + 360.f;
2461 Mix_SetPosition (self, angle, CLAMP (distance, 0, 255)); 2927 Mix_SetPosition (self, angle, CLAMP (distance, 0, 255));
2462} 2928}
2463 2929
2464void 2930void
2465set_reverse_stereo (DC::Channel self, int flip) 2931set_reverse_stereo (DC::Channel self, int flip)
2468 2934
2469MODULE = Deliantra::Client PACKAGE = DC::MixChunk 2935MODULE = Deliantra::Client PACKAGE = DC::MixChunk
2470 2936
2471PROTOTYPES: DISABLE 2937PROTOTYPES: DISABLE
2472 2938
2939void
2940decoders ()
2941 PPCODE:
2942#if SDL_MIXER_MAJOR_VERSION > 1 || SDL_MIXER_MINOR_VERSION > 2 || SDL_MIXER_PATCHLEVEL >= 10
2943 int i, num = Mix_GetNumChunkDecoders ();
2944 EXTEND (SP, num);
2945 for (i = 0; i < num; ++i)
2946 PUSHs (sv_2mortal (newSVpv (Mix_GetChunkDecoder (i), 0)));
2947#else
2948 XPUSHs (sv_2mortal (newSVpv ("(sdl mixer too old)", 0)));
2949#endif
2950
2473DC::MixChunk 2951DC::MixChunk
2474new (SV *class, DC::RW rwops) 2952new (SV *klass, DC::RW rwops)
2475 CODE: 2953 CODE:
2476 RETVAL = Mix_LoadWAV_RW (rwops, 1); 2954 RETVAL = Mix_LoadWAV_RW (rwops, 1);
2477 OUTPUT: 2955 OUTPUT:
2478 RETVAL 2956 RETVAL
2479 2957
2509 OUTPUT: 2987 OUTPUT:
2510 RETVAL 2988 RETVAL
2511 2989
2512MODULE = Deliantra::Client PACKAGE = DC::MixMusic 2990MODULE = Deliantra::Client PACKAGE = DC::MixMusic
2513 2991
2992void
2993decoders ()
2994 PPCODE:
2995#if SDL_MIXER_MAJOR_VERSION > 1 || SDL_MIXER_MINOR_VERSION > 2 || SDL_MIXER_PATCHLEVEL >= 10
2996 int i, num = Mix_GetNumMusicDecoders ();
2997 EXTEND (SP, num);
2998 for (i = 0; i < num; ++i)
2999 PUSHs (sv_2mortal (newSVpv (Mix_GetMusicDecoder (i), 0)));
3000#else
3001 XPUSHs (sv_2mortal (newSVpv ("(sdl mixer too old)", 0)));
3002#endif
3003
2514int 3004int
2515volume (int volume = -1) 3005volume (int volume = -1)
2516 PROTOTYPE: ;$ 3006 PROTOTYPE: ;$
2517 CODE: 3007 CODE:
2518 if (items > 0) 3008 if (items > 0)
2529void 3019void
2530halt () 3020halt ()
2531 CODE: 3021 CODE:
2532 Mix_HaltMusic (); 3022 Mix_HaltMusic ();
2533 3023
3024int
3025playing ()
3026 CODE:
3027 RETVAL = Mix_PlayingMusic ();
3028 OUTPUT:
3029 RETVAL
3030
2534DC::MixMusic 3031DC::MixMusic
2535new (SV *class, DC::RW rwops) 3032new (SV *klass, DC::RW rwops)
2536 CODE: 3033 CODE:
2537 RETVAL = Mix_LoadMUS_RW (rwops); 3034 RETVAL = Mix_LoadMUS_RW (rwops);
2538 OUTPUT: 3035 OUTPUT:
2539 RETVAL 3036 RETVAL
2540 3037
2568 } *civ, const_iv[] = { 3065 } *civ, const_iv[] = {
2569# define const_iv(name) { # name, (IV)name } 3066# define const_iv(name) { # name, (IV)name }
2570 const_iv (GL_VENDOR), 3067 const_iv (GL_VENDOR),
2571 const_iv (GL_VERSION), 3068 const_iv (GL_VERSION),
2572 const_iv (GL_EXTENSIONS), 3069 const_iv (GL_EXTENSIONS),
3070 const_iv (GL_MAX_TEXTURE_UNITS),
2573 const_iv (GL_COLOR_MATERIAL), 3071 const_iv (GL_COLOR_MATERIAL),
2574 const_iv (GL_SMOOTH), 3072 const_iv (GL_SMOOTH),
2575 const_iv (GL_FLAT), 3073 const_iv (GL_FLAT),
2576 const_iv (GL_DITHER), 3074 const_iv (GL_DITHER),
2577 const_iv (GL_BLEND), 3075 const_iv (GL_BLEND),
2589 const_iv (GL_ZERO), 3087 const_iv (GL_ZERO),
2590 const_iv (GL_SRC_ALPHA), 3088 const_iv (GL_SRC_ALPHA),
2591 const_iv (GL_DST_ALPHA), 3089 const_iv (GL_DST_ALPHA),
2592 const_iv (GL_ONE_MINUS_SRC_ALPHA), 3090 const_iv (GL_ONE_MINUS_SRC_ALPHA),
2593 const_iv (GL_ONE_MINUS_DST_ALPHA), 3091 const_iv (GL_ONE_MINUS_DST_ALPHA),
3092 const_iv (GL_SRC_COLOR),
3093 const_iv (GL_DST_COLOR),
3094 const_iv (GL_ONE_MINUS_SRC_COLOR),
3095 const_iv (GL_ONE_MINUS_DST_COLOR),
2594 const_iv (GL_SRC_ALPHA_SATURATE), 3096 const_iv (GL_SRC_ALPHA_SATURATE),
2595 const_iv (GL_RGB), 3097 const_iv (GL_RGB),
2596 const_iv (GL_RGBA), 3098 const_iv (GL_RGBA),
2597 const_iv (GL_RGBA4), 3099 const_iv (GL_RGBA4),
2598 const_iv (GL_RGBA8), 3100 const_iv (GL_RGBA8),
2666 const_iv (GL_NICEST), 3168 const_iv (GL_NICEST),
2667 const_iv (GL_V2F), 3169 const_iv (GL_V2F),
2668 const_iv (GL_V3F), 3170 const_iv (GL_V3F),
2669 const_iv (GL_T2F_V3F), 3171 const_iv (GL_T2F_V3F),
2670 const_iv (GL_T2F_N3F_V3F), 3172 const_iv (GL_T2F_N3F_V3F),
3173 const_iv (GL_FUNC_ADD),
3174 const_iv (GL_FUNC_SUBTRACT),
3175 const_iv (GL_FUNC_REVERSE_SUBTRACT),
2671# undef const_iv 3176# undef const_iv
2672 }; 3177 };
2673 3178
2674 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) 3179 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--)
2675 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 3180 newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv));
2676 3181
2677 texture_av = newAV (); 3182 texture_av = newAV ();
2678 AvREAL_off (texture_av); 3183 AvREAL_off (texture_av);
2679} 3184}
2680 3185
2682disable_GL_EXT_blend_func_separate () 3187disable_GL_EXT_blend_func_separate ()
2683 CODE: 3188 CODE:
2684 gl.BlendFuncSeparate = 0; 3189 gl.BlendFuncSeparate = 0;
2685 gl.BlendFuncSeparateEXT = 0; 3190 gl.BlendFuncSeparateEXT = 0;
2686 3191
2687char * 3192void
3193apple_nvidia_bug (int enable)
3194
3195const char *
2688gl_vendor () 3196gl_vendor ()
2689 CODE: 3197 CODE:
2690 RETVAL = (char *)glGetString (GL_VENDOR); 3198 RETVAL = (const char *)glGetString (GL_VENDOR);
2691 OUTPUT: 3199 OUTPUT:
2692 RETVAL 3200 RETVAL
2693 3201
2694char * 3202const char *
2695gl_version () 3203gl_version ()
2696 CODE: 3204 CODE:
2697 RETVAL = (char *)glGetString (GL_VERSION); 3205 RETVAL = (const char *)glGetString (GL_VERSION);
2698 OUTPUT: 3206 OUTPUT:
2699 RETVAL 3207 RETVAL
2700 3208
2701char * 3209const char *
2702gl_extensions () 3210gl_extensions ()
2703 CODE: 3211 CODE:
2704 RETVAL = (char *)glGetString (GL_EXTENSIONS); 3212 RETVAL = (const char *)glGetString (GL_EXTENSIONS);
2705 OUTPUT: 3213 OUTPUT:
2706 RETVAL 3214 RETVAL
2707 3215
2708const char *glGetString (GLenum pname) 3216const char *glGetString (GLenum pname)
3217 CODE:
3218 RETVAL = (const char *)glGetString (pname);
3219 OUTPUT:
3220 RETVAL
2709 3221
2710GLint glGetInteger (GLenum pname) 3222GLint glGetInteger (GLenum pname)
2711 CODE: 3223 CODE:
2712 glGetIntegerv (pname, &RETVAL); 3224 glGetIntegerv (pname, &RETVAL);
2713 OUTPUT: 3225 OUTPUT:
2721 3233
2722int glGetError () 3234int glGetError ()
2723 3235
2724void glFinish () 3236void glFinish ()
2725 3237
3238void glFlush ()
3239
2726void glClear (int mask) 3240void glClear (int mask)
2727 3241
2728void glClearColor (float r, float g, float b, float a = 1.0) 3242void glClearColor (float r, float g, float b, float a = 1.0)
2729 PROTOTYPE: @ 3243 PROTOTYPE: @
2730 3244
2739void glBlendFunc (int sfactor, int dfactor) 3253void glBlendFunc (int sfactor, int dfactor)
2740 3254
2741void glBlendFuncSeparate (int sa, int da, int saa, int daa) 3255void glBlendFuncSeparate (int sa, int da, int saa, int daa)
2742 CODE: 3256 CODE:
2743 gl_BlendFuncSeparate (sa, da, saa, daa); 3257 gl_BlendFuncSeparate (sa, da, saa, daa);
3258
3259# void glBlendEquation (int se)
2744 3260
2745void glDepthMask (int flag) 3261void glDepthMask (int flag)
2746 3262
2747void glLogicOp (int opcode) 3263void glLogicOp (int opcode)
2748 3264
2783void glRotate (float angle, float x, float y, float z) 3299void glRotate (float angle, float x, float y, float z)
2784 CODE: 3300 CODE:
2785 glRotatef (angle, x, y, z); 3301 glRotatef (angle, x, y, z);
2786 3302
2787void glColor (float r, float g, float b, float a = 1.0) 3303void glColor (float r, float g, float b, float a = 1.0)
3304 PROTOTYPE: @
2788 ALIAS: 3305 ALIAS:
2789 glColor_premultiply = 1 3306 glColor_premultiply = 1
2790 CODE: 3307 CODE:
2791 if (ix) 3308 if (ix)
2792 { 3309 {
2898 3415
2899void glEndList () 3416void glEndList ()
2900 3417
2901void glCallList (int list) 3418void glCallList (int list)
2902 3419
3420void c_init ()
3421 CODE:
3422 glPixelStorei (GL_PACK_ALIGNMENT , 1);
3423 glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
3424
2903MODULE = Deliantra::Client PACKAGE = DC::UI::Base 3425MODULE = Deliantra::Client PACKAGE = DC::UI::Base
2904 3426
2905PROTOTYPES: DISABLE 3427PROTOTYPES: DISABLE
2906 3428
2907void 3429void
2908find_widget (SV *self, NV x, NV y) 3430find_widget (SV *self, NV x, NV y)
2909 PPCODE: 3431 PPCODE:
2910{ 3432{
2911 if (within_widget (self, x, y)) 3433 if (within_widget (self, x, y))
2912 XPUSHs (self); 3434 XPUSHs (self);
2913} 3435}
2914 3436
2915BOOT: 3437BOOT:
2916{ 3438{
2924 3446
2925void 3447void
2926draw (SV *self) 3448draw (SV *self)
2927 CODE: 3449 CODE:
2928{ 3450{
2929 HV *hv; 3451 HV *hv;
2930 SV **svp; 3452 SV **svp;
2931 NV x, y, w, h; 3453 NV x, y, w, h;
2932 SV *draw_x_sv = GvSV (draw_x_gv); 3454 SV *draw_x_sv = GvSV (draw_x_gv);
2933 SV *draw_y_sv = GvSV (draw_y_gv); 3455 SV *draw_y_sv = GvSV (draw_y_gv);
2934 SV *draw_w_sv = GvSV (draw_w_gv); 3456 SV *draw_w_sv = GvSV (draw_w_gv);
2935 SV *draw_h_sv = GvSV (draw_h_gv); 3457 SV *draw_h_sv = GvSV (draw_h_gv);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines