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.249 by root, Fri Dec 28 15:40:07 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#if 0 95/* mask out modifiers we are not interested in */
76# define PARACHUTE SDL_INIT_NOPARACHUTE 96#define MOD_MASK (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_META)
77#else 97
78# define PARACHUTE 0 98#define KMOD_LRAM 0x10000 // our extension
79#endif 99
100#define TEXID_SPEECH 1
101#define TEXID_NOFACE 2
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}
80 121
81static AV *texture_av; 122static AV *texture_av;
82 123
83static struct 124static struct
84{ 125{
141{ 182{
142 GSList *attrs = run->item->analysis.extra_attrs; 183 GSList *attrs = run->item->analysis.extra_attrs;
143 184
144 while (attrs) 185 while (attrs)
145 { 186 {
146 PangoAttribute *attr = attrs->data; 187 PangoAttribute *attr = (PangoAttribute *)attrs->data;
147 188
148 if (attr->klass->type == PANGO_ATTR_SHAPE) 189 if (attr->klass->type == PANGO_ATTR_SHAPE)
149 return 1; 190 return 1;
150 191
151 attrs = attrs->next; 192 attrs = attrs->next;
152 } 193 }
153 194
154 return 0; 195 return 0;
155} 196}
156 197
157typedef struct cf_layout { 198struct cf_layout {
158 PangoLayout *pl; 199 PangoLayout *pl;
159 float r, g, b, a; // default color for rgba mode 200 float r, g, b, a; // default color for rgba mode
160 int base_height; 201 int base_height;
161 DC__Font font; 202 DC__Font font;
162 rc_t *rc; 203 rc_t rc;
163} *DC__Layout; 204};
205
206typedef cf_layout *DC__Layout;
164 207
165static DC__Font default_font; 208static DC__Font default_font;
166static PangoContext *opengl_context; 209static PangoContext *opengl_context;
167static PangoFontMap *opengl_fontmap; 210static PangoFontMap *opengl_fontmap;
168 211
169static void 212static void
170substitute_func (FcPattern *pattern, gpointer data) 213substitute_func (FcPattern *pattern, gpointer data)
171{ 214{
172 FcPatternAddBool (pattern, FC_HINTING, 1); 215 FcPatternAddBool (pattern, FC_HINTING, 1);
173#ifdef FC_HINT_STYLE 216#ifdef FC_HINT_STYLE
174 FcPatternAddBool (pattern, FC_HINT_STYLE, FC_HINT_FULL); 217 FcPatternAddInteger (pattern, FC_HINT_STYLE, FC_HINT_FULL);
175#endif 218#endif
176 FcPatternAddBool (pattern, FC_AUTOHINT, 0); 219 FcPatternAddBool (pattern, FC_AUTOHINT, 0);
177} 220}
178 221
179static void 222static void
180layout_update_font (DC__Layout self) 223layout_update_font (DC__Layout self)
181{ 224{
182 /* 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
183 * reasonably well with bitstream vera 226 * reasonably well with dejavu/bistream fonts
184 */ 227 */
185 PangoFontDescription *font = self->font ? self->font : default_font; 228 PangoFontDescription *font = self->font ? self->font : default_font;
186 229
187 pango_font_description_set_absolute_size (font, 230 pango_font_description_set_absolute_size (font,
188 MAX (MIN_FONT_HEIGHT, self->base_height) * (PANGO_SCALE * 8 / 10)); 231 MAX (MIN_FONT_HEIGHT, self->base_height) * (PANGO_SCALE * 8 / 10));
206 249
207 *w = rect.width; 250 *w = rect.width;
208 *h = rect.height; 251 *h = rect.height;
209} 252}
210 253
254/////////////////////////////////////////////////////////////////////////////
255
211typedef uint16_t tileid; 256typedef uint16_t tileid;
212typedef uint16_t faceid; 257typedef uint16_t faceid;
213 258
214typedef struct { 259struct maptex
260{
215 GLuint name; 261 GLuint name;
216 int w, h; 262 int w, h;
217 float s, t; 263 float s, t;
218 uint8_t r, g, b, a; 264 uint8_t r, g, b, a;
219 tileid smoothtile; 265 tileid smoothtile;
220 uint8_t smoothlevel; 266 uint8_t smoothlevel;
221} maptex; 267 uint8_t unused; /* set to zero on use */
268};
222 269
223typedef struct { 270struct mapcell
271{
224 uint32_t player; 272 uint32_t player;
225 tileid tile[3]; 273 tileid tile[3];
226 uint16_t darkness; 274 uint16_t darkness;
227 uint8_t stat_width, stat_hp, flags, smoothmax; 275 uint8_t stat_width, stat_hp, flags, smoothmax;
228} mapcell; 276};
229 277
230typedef struct { 278struct maprow
279{
231 int32_t c0, c1; 280 int32_t c0, c1;
232 mapcell *col; 281 mapcell *col;
233} maprow; 282};
234 283
235typedef struct map { 284struct mapgrid {
236 int x, y, w, h; 285 int x, y, w, h;
237 int ox, oy; /* offset to virtual global coordinate system */ 286 int ox, oy; /* offset to virtual global coordinate system */
238 int faces; tileid *face2tile; // [faceid] 287 int faces; tileid *face2tile; // [faceid]
239 int texs; maptex *tex; // [tileid] 288 int texs; maptex *tex; // [tileid]
240 289
241 int32_t rows; 290 int32_t rows;
242 maprow *row; 291 maprow *row;
243} *DC__Map; 292};
244 293
245static char * 294typedef mapgrid *DC__Map;
295
296template<typename T>
297static void
246prepend (char *ptr, int sze, int inc) 298prepend (T *&ptr, int sze, int inc)
247{ 299{
248 char *p; 300 T *p;
249 301
250 New (0, p, sze + inc, char); 302 Newx (p, inc + sze, T);
251 Zero (p, inc, char); 303 Zero (p, inc, T);
252 Move (ptr, p + inc, sze, char); 304 Move (ptr, p + inc, sze, T);
253 Safefree (ptr); 305 Safefree (ptr);
254 306
255 return p; 307 ptr = p;
256} 308}
257 309
258static char * 310template<typename T>
259append (char *ptr, int sze, int inc)
260{
261 Renew (ptr, sze + inc, char);
262 Zero (ptr + sze, inc, char);
263
264 return ptr;
265}
266
267#define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
268#define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
269
270static 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
271need_facenum (struct map *self, faceid face) 319need_facenum (struct mapgrid *self, faceid face)
272{ 320{
273 while (self->faces <= face) 321 while (self->faces <= face)
274 { 322 {
275 Append (tileid, self->face2tile, self->faces, self->faces); 323 append (self->face2tile, self->faces, self->faces);
276 self->faces *= 2; 324 self->faces *= 2;
277 } 325 }
278} 326}
279 327
280static void 328static void
281need_texid (struct map *self, int texid) 329need_texid (struct mapgrid *self, int texid)
282{ 330{
283 while (self->texs <= texid) 331 while (self->texs <= texid)
284 { 332 {
285 Append (maptex, self->tex, self->texs, self->texs); 333 append (self->tex, self->texs, self->texs);
286 self->texs *= 2; 334 self->texs *= 2;
287 } 335 }
288} 336}
289 337
290static maprow * 338static maprow *
291map_get_row (DC__Map self, int y) 339map_get_row (mapgrid *self, int y)
292{ 340{
293 if (0 > y) 341 if (0 > y)
294 { 342 {
295 int extend = - y + MAP_EXTEND_Y; 343 int extend = - y + MAP_EXTEND_Y;
296 Prepend (maprow, self->row, self->rows, extend); 344 prepend (self->row, self->rows, extend);
297 345
298 self->rows += extend; 346 self->rows += extend;
299 self->y += extend; 347 self->y += extend;
300 y += extend; 348 y += extend;
301 } 349 }
302 else if (y >= self->rows) 350 else if (y >= self->rows)
303 { 351 {
304 int extend = y - self->rows + MAP_EXTEND_Y; 352 int extend = y - self->rows + MAP_EXTEND_Y;
305 Append (maprow, self->row, self->rows, extend); 353 append (self->row, self->rows, extend);
306 self->rows += extend; 354 self->rows += extend;
307 } 355 }
308 356
309 return self->row + y; 357 return self->row + y;
310} 358}
320 } 368 }
321 369
322 if (row->c0 > x) 370 if (row->c0 > x)
323 { 371 {
324 int extend = row->c0 - x + MAP_EXTEND_X; 372 int extend = row->c0 - x + MAP_EXTEND_X;
325 Prepend (mapcell, row->col, row->c1 - row->c0, extend); 373 prepend (row->col, row->c1 - row->c0, extend);
326 row->c0 -= extend; 374 row->c0 -= extend;
327 } 375 }
328 else if (x >= row->c1) 376 else if (x >= row->c1)
329 { 377 {
330 int extend = x - row->c1 + MAP_EXTEND_X; 378 int extend = x - row->c1 + MAP_EXTEND_X;
331 Append (mapcell, row->col, row->c1 - row->c0, extend); 379 append (row->col, row->c1 - row->c0, extend);
332 row->c1 += extend; 380 row->c1 += extend;
333 } 381 }
334 382
335 return row->col + (x - row->c0); 383 return row->col + (x - row->c0);
336} 384}
337 385
338static mapcell * 386static mapcell *
339map_get_cell (DC__Map self, int x, int y) 387map_get_cell (mapgrid *self, int x, int y)
340{ 388{
341 return row_get_cell (map_get_row (self, y), x); 389 return row_get_cell (map_get_row (self, y), x);
342} 390}
343 391
344static void 392static void
345map_clear (DC__Map self) 393map_clear (mapgrid *self)
346{ 394{
347 int r; 395 int r;
348 396
349 for (r = 0; r < self->rows; r++) 397 for (r = 0; r < self->rows; r++)
350 Safefree (self->row[r].col); 398 Safefree (self->row[r].col);
357 self->oy = 0; 405 self->oy = 0;
358 self->row = 0; 406 self->row = 0;
359 self->rows = 0; 407 self->rows = 0;
360} 408}
361 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
362static void 420static void
363map_blank (DC__Map self, int x0, int y0, int w, int h) 421map_blank (mapgrid *self, int x0, int y0, int w, int h)
364{ 422{
365 int x, y; 423 int x, y;
366 maprow *row; 424 maprow *row;
367 mapcell *cell; 425 mapcell *cell;
368 426
380 if (x >= row->c1) 438 if (x >= row->c1)
381 break; 439 break;
382 440
383 cell = row->col + x - row->c0; 441 cell = row->col + x - row->c0;
384 442
385 cell->darkness = 0; 443 CELL_CLEAR (cell);
386 cell->stat_hp = 0;
387 cell->flags = 0;
388 cell->player = 0;
389 } 444 }
390 } 445 }
391} 446}
392 447
393typedef struct { 448struct smooth_key
449{
394 tileid tile; 450 tileid tile;
395 uint8_t x, y, level; 451 uint8_t x, y, level;
396} 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}
397 471
398static void 472static void
399smooth_or_bits (HV *hv, smooth_key *key, IV bits) 473smooth_or_bits (smooth_hash &h, smooth_key &key, IV bits)
400{ 474{
401 SV **sv = hv_fetch (hv, (char *)key, sizeof (*key), 1); 475 auto &&it = h.find (key);
402 476
403 if (SvIOK (*sv)) 477 if (it == h.end ())
404 SvIV_set (*sv, SvIVX (*sv) | bits); 478 h.insert (std::make_pair (key, bits));
405 else 479 else
406 sv_setiv (*sv, bits); 480 it->second |= bits;
407} 481}
408 482
409static void 483static void
410music_finished (void) 484music_finished (void)
411{ 485{
428 ev.code = 1; 502 ev.code = 1;
429 ev.data1 = (void *)(long)channel; 503 ev.data1 = (void *)(long)channel;
430 ev.data2 = 0; 504 ev.data2 = 0;
431 505
432 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;
433} 514}
434 515
435static unsigned int 516static unsigned int
436minpot (unsigned int n) 517minpot (unsigned int n)
437{ 518{
447 n |= n >> 16; 528 n |= n >> 16;
448 529
449 return n + 1; 530 return n + 1;
450} 531}
451 532
452static unsigned int
453popcount (unsigned int n)
454{
455 n -= (n >> 1) & 0x55555555U;
456 n = ((n >> 2) & 0x33333333U) + (n & 0x33333333U);
457 n = ((n >> 4) + n) & 0x0f0f0f0fU;
458 n *= 0x01010101U;
459
460 return n >> 24;
461}
462
463/* SDL should provide this, really. */ 533/* SDL should provide this, really. */
464#define SDLK_MODIFIER_MIN 300 534#define SDLK_MODIFIER_MIN 300
465#define SDLK_MODIFIER_MAX 314 535#define SDLK_MODIFIER_MAX 314
466 536
467/******************************************************************************/ 537/******************************************************************************/
504 if (!svp || !SvTRUE (*svp)) 574 if (!svp || !SvTRUE (*svp))
505 return 0; 575 return 0;
506 576
507 return 1; 577 return 1;
508} 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
509 637
510MODULE = Deliantra::Client PACKAGE = DC 638MODULE = Deliantra::Client PACKAGE = DC
511 639
512PROTOTYPES: ENABLE 640PROTOTYPES: ENABLE
513 641
542 const_iv (SDL_USEREVENT), 670 const_iv (SDL_USEREVENT),
543 671
544 const_iv (SDL_APPINPUTFOCUS), 672 const_iv (SDL_APPINPUTFOCUS),
545 const_iv (SDL_APPMOUSEFOCUS), 673 const_iv (SDL_APPMOUSEFOCUS),
546 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),
547 725
548 const_iv (SDLK_FIRST), 726 const_iv (SDLK_FIRST),
549 const_iv (SDLK_LAST), 727 const_iv (SDLK_LAST),
550 const_iv (SDLK_KP0), 728 const_iv (SDLK_KP0),
551 const_iv (SDLK_KP1), 729 const_iv (SDLK_KP1),
627 const_iv (KMOD_RMETA), 805 const_iv (KMOD_RMETA),
628 const_iv (KMOD_NUM), 806 const_iv (KMOD_NUM),
629 const_iv (KMOD_CAPS), 807 const_iv (KMOD_CAPS),
630 const_iv (KMOD_MODE), 808 const_iv (KMOD_MODE),
631 809
810 const_iv (KMOD_LRAM),
811
632 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)
633# undef const_iv 842# undef const_iv
634 }; 843 };
635 844
636 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--)
637 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 846 newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv));
638 847
639 assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK); 848 assert (SDLK_MODIFIER_MIN == SDLK_NUMLOCK);
640 assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE); 849 assert (SDLK_MODIFIER_MAX == SDLK_COMPOSE);
641} 850}
642 851
657 866
658NV ceil (NV x) 867NV ceil (NV x)
659 868
660IV minpot (UV n) 869IV minpot (UV n)
661 870
871UV ld32 (UV n)
872 CODE:
873 RETVAL = ecb_ld32 (n);
874 OUTPUT:
875 RETVAL
876
662IV 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
663 888
664void 889void
665pango_init () 890pango_init ()
666 CODE: 891 CODE:
667{ 892{
668 opengl_fontmap = pango_opengl_font_map_new (); 893 opengl_fontmap = pango_opengl_font_map_new ();
669 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);
670 opengl_context = pango_opengl_font_map_create_context ((PangoOpenGLFontMap *)opengl_fontmap); 895 opengl_context = pango_opengl_font_map_create_context ((PangoOpenGLFontMap *)opengl_fontmap);
671#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)
672 pango_context_set_language (opengl_context, pango_language_from_string ("en")); 898 pango_context_set_language (opengl_context, pango_language_from_string ("en"));
673 pango_context_set_base_dir (opengl_context, PANGO_DIRECTION_WEAK_LTR); 899 /*pango_context_set_base_dir (opengl_context, PANGO_DIRECTION_WEAK_LTR);*/
674#endif 900#endif
675} 901}
676 902
677char *
678SDL_GetError () 903char *SDL_GetError ()
679 904
680int 905void SDL_main_hack (SV *real_main)
681SDL_Init (U32 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | PARACHUTE) 906 PROTOTYPE: &
682 907
683void 908int SDL_Init (U32 flags)
909
910int SDL_InitSubSystem (U32 flags)
911
912void SDL_QuitSubSystem (U32 flags)
913
684SDL_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
685 925
686void 926void
687SDL_ListModes (int rgb, int alpha) 927SDL_ListModes (int rgb, int alpha)
688 PPCODE: 928 PPCODE:
689{ 929{
701 SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0); 941 SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0);
702 SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE , 0); 942 SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE , 0);
703 SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0); 943 SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0);
704 944
705 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1); 945 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
706#if SDL_VERSION_ATLEAST(1,2,10)
707 SDL_GL_SetAttribute (SDL_GL_ACCELERATED_VISUAL, 1);
708 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1); 946 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
709#endif
710 947
711 m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL); 948 m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL);
712 949
713 if (m && m != (SDL_Rect **)-1) 950 if (m && m != (SDL_Rect **)-1)
714 while (*m) 951 while (*m)
715 { 952 {
716 if ((*m)->w >= 800 && (*m)->h >= 480) 953 if ((*m)->w >= 400 && (*m)->h >= 300)
717 { 954 {
718 AV *av = newAV (); 955 AV *av = newAV ();
719 av_push (av, newSViv ((*m)->w)); 956 av_push (av, newSViv ((*m)->w));
720 av_push (av, newSViv ((*m)->h)); 957 av_push (av, newSViv ((*m)->h));
721 av_push (av, newSViv (rgb)); 958 av_push (av, newSViv (rgb));
744 ); 981 );
745 982
746 if (RETVAL) 983 if (RETVAL)
747 { 984 {
748 av_clear (texture_av); 985 av_clear (texture_av);
749
750 SDL_WM_SetCaption ("Deliantra MORPG Client " VERSION, "Deliantra");
751#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);
752#include "glfunc.h" 987#include "glfunc.h"
753#undef GL_FUNC 988#undef GL_FUNC
989 if (!gl.ActiveTexture ) gl.ActiveTexture = gl.ActiveTextureARB;
990 if (!gl.MultiTexCoord2f) gl.MultiTexCoord2f = gl.MultiTexCoord2fARB;
754 } 991 }
755} 992}
756 OUTPUT: 993 OUTPUT:
757 RETVAL 994 RETVAL
995
996void
997SDL_WM_SetCaption (const char *title, const char *icon)
758 998
759void 999void
760SDL_GL_SwapBuffers () 1000SDL_GL_SwapBuffers ()
761 1001
762char * 1002char *
763SDL_GetKeyName (int sym) 1003SDL_GetKeyName (int sym)
1004 C_ARGS: (SDLKey)sym
764 1005
765int 1006int
766SDL_GetAppState () 1007SDL_GetAppState ()
767 1008
1009int
1010SDL_GetModState ()
1011
1012int
1013SDL_WaitEvent ()
1014 C_ARGS: 0
1015
768void 1016void
1017SDL_PumpEvents ()
1018
1019void
769poll_events () 1020peep_events ()
770 PPCODE: 1021 PPCODE:
771{ 1022{
772 SDL_Event ev; 1023 SDL_Event ev;
773 1024
774 SDL_PumpEvents (); 1025 SDL_PumpEvents ();
781 { 1032 {
782 case SDL_KEYDOWN: 1033 case SDL_KEYDOWN:
783 case SDL_KEYUP: 1034 case SDL_KEYUP:
784 hv_store (hv, "state", 5, newSViv (ev.key.state), 0); 1035 hv_store (hv, "state", 5, newSViv (ev.key.state), 0);
785 hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0); 1036 hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0);
786 hv_store (hv, "mod", 3, newSViv (ev.key.keysym.mod), 0); 1037 hv_store (hv, "mod", 3, newSViv (mod_munge (ev.key.keysym.mod)), 0);
787 hv_store (hv, "cmod", 4, newSViv (SDL_GetModState ()), 0); /* current mode */ 1038 hv_store (hv, "cmod", 4, newSViv (mod_munge (SDL_GetModState ())), 0); /* current mode */
788 hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0); 1039 hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0);
789 break; 1040 break;
790 1041
791 case SDL_ACTIVEEVENT: 1042 case SDL_ACTIVEEVENT:
792 hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0); 1043 hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0);
810 x = ev.motion.x; 1061 x = ev.motion.x;
811 y = ev.motion.y; 1062 y = ev.motion.y;
812 SDL_PeepEvents (&ev, 1, SDL_GETEVENT, SDL_EVENTMASK (SDL_MOUSEMOTION)); 1063 SDL_PeepEvents (&ev, 1, SDL_GETEVENT, SDL_EVENTMASK (SDL_MOUSEMOTION));
813 } 1064 }
814 1065
815 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0); 1066 hv_store (hv, "mod", 3, newSViv (mod_munge (SDL_GetModState ())), 0);
816 hv_store (hv, "state", 5, newSViv (state), 0); 1067 hv_store (hv, "state", 5, newSViv (state), 0);
817 hv_store (hv, "x", 1, newSViv (x), 0); 1068 hv_store (hv, "x", 1, newSViv (x), 0);
818 hv_store (hv, "y", 1, newSViv (y), 0); 1069 hv_store (hv, "y", 1, newSViv (y), 0);
819 hv_store (hv, "xrel", 4, newSViv (xrel), 0); 1070 hv_store (hv, "xrel", 4, newSViv (xrel), 0);
820 hv_store (hv, "yrel", 4, newSViv (yrel), 0); 1071 hv_store (hv, "yrel", 4, newSViv (yrel), 0);
821 } 1072 }
822 break; 1073 break;
823 1074
824 case SDL_MOUSEBUTTONDOWN: 1075 case SDL_MOUSEBUTTONDOWN:
825 case SDL_MOUSEBUTTONUP: 1076 case SDL_MOUSEBUTTONUP:
826 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0); 1077 hv_store (hv, "mod", 3, newSViv (SDL_GetModState () & MOD_MASK), 0);
827 1078
828 hv_store (hv, "button", 6, newSViv (ev.button.button), 0); 1079 hv_store (hv, "button", 6, newSViv (ev.button.button), 0);
829 hv_store (hv, "state", 5, newSViv (ev.button.state), 0); 1080 hv_store (hv, "state", 5, newSViv (ev.button.state), 0);
830 hv_store (hv, "x", 1, newSViv (ev.button.x), 0); 1081 hv_store (hv, "x", 1, newSViv (ev.button.x), 0);
831 hv_store (hv, "y", 1, newSViv (ev.button.y), 0); 1082 hv_store (hv, "y", 1, newSViv (ev.button.y), 0);
840 1091
841 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))));
842 } 1093 }
843} 1094}
844 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
845int 1109int
846Mix_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)
847 POSTCALL: 1111 POSTCALL:
848 Mix_HookMusicFinished (music_finished); 1112 Mix_HookMusicFinished (music_finished);
849 Mix_ChannelFinished (channel_finished); 1113 Mix_ChannelFinished (channel_finished);
850 1114
851void 1115void
852Mix_QuerySpec () 1116Mix_QuerySpec ()
905 } 1169 }
906 } 1170 }
907#endif 1171#endif
908} 1172}
909 1173
910void 1174int
911add_font (char *file) 1175add_font (char *file)
912 CODE: 1176 CODE:
913 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)
914 1187
915void 1188void
916load_image_inline (SV *image_) 1189load_image_inline (SV *image_)
917 ALIAS: 1190 ALIAS:
918 load_image_file = 1 1191 load_image_file = 1
964 1237
965 SDL_LockSurface (surface2); 1238 SDL_LockSurface (surface2);
966 EXTEND (SP, 6); 1239 EXTEND (SP, 6);
967 PUSHs (sv_2mortal (newSViv (surface2->w))); 1240 PUSHs (sv_2mortal (newSViv (surface2->w)));
968 PUSHs (sv_2mortal (newSViv (surface2->h))); 1241 PUSHs (sv_2mortal (newSViv (surface2->h)));
969 PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch))); 1242 PUSHs (sv_2mortal (newSVpvn ((const char *)surface2->pixels, surface2->h * surface2->pitch)));
970 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)));
971 PUSHs (sv_2mortal (newSViv (GL_RGBA))); 1244 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
972 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE))); 1245 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
973 SDL_UnlockSurface (surface2); 1246 SDL_UnlockSurface (surface2);
974 1247
1034#if DEBUG 1307#if DEBUG
1035 VALGRIND_DO_LEAK_CHECK; 1308 VALGRIND_DO_LEAK_CHECK;
1036#endif 1309#endif
1037} 1310}
1038 1311
1312int
1313SvREFCNT (SV *sv)
1314 CODE:
1315 RETVAL = SvREFCNT (sv);
1316 OUTPUT:
1317 RETVAL
1318
1039MODULE = Deliantra::Client PACKAGE = DC::Font 1319MODULE = Deliantra::Client PACKAGE = DC::Font
1040 1320
1041PROTOTYPES: DISABLE 1321PROTOTYPES: DISABLE
1042 1322
1043DC::Font 1323DC::Font
1044new_from_file (SV *class, char *path, int id = 0) 1324new_from_file (SV *klass, char *path, int id = 0)
1045 CODE: 1325 CODE:
1046{ 1326{
1047 int count; 1327 int count;
1048 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count); 1328 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count);
1049 RETVAL = pango_fc_font_description_from_pattern (pattern, 0); 1329 RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
1078 PROTOTYPE: 1358 PROTOTYPE:
1079 CODE: 1359 CODE:
1080 tc_restore (); 1360 tc_restore ();
1081 1361
1082DC::Layout 1362DC::Layout
1083new (SV *class) 1363new (SV *klass)
1084 CODE: 1364 CODE:
1085 New (0, RETVAL, 1, struct cf_layout); 1365 RETVAL = new cf_layout;
1086 1366
1087 RETVAL->pl = pango_layout_new (opengl_context); 1367 RETVAL->pl = pango_layout_new (opengl_context);
1088 RETVAL->r = 1.; 1368 RETVAL->r = 1.;
1089 RETVAL->g = 1.; 1369 RETVAL->g = 1.;
1090 RETVAL->b = 1.; 1370 RETVAL->b = 1.;
1091 RETVAL->a = 1.; 1371 RETVAL->a = 1.;
1092 RETVAL->base_height = MIN_FONT_HEIGHT; 1372 RETVAL->base_height = MIN_FONT_HEIGHT;
1093 RETVAL->font = 0; 1373 RETVAL->font = 0;
1094 RETVAL->rc = rc_alloc ();
1095 1374
1096 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR); 1375 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
1097 layout_update_font (RETVAL); 1376 layout_update_font (RETVAL);
1098 OUTPUT: 1377 OUTPUT:
1099 RETVAL 1378 RETVAL
1100 1379
1101void 1380void
1102DESTROY (DC::Layout self) 1381DESTROY (DC::Layout self)
1103 CODE: 1382 CODE:
1104 g_object_unref (self->pl); 1383 g_object_unref (self->pl);
1105 rc_free (self->rc);
1106 Safefree (self); 1384 delete self;
1107 1385
1108void 1386void
1109set_text (DC::Layout self, SV *text_) 1387set_text (DC::Layout self, SV *text_)
1110 CODE: 1388 CODE:
1111{ 1389{
1237 1515
1238void 1516void
1239set_height (DC::Layout self, int base_height) 1517set_height (DC::Layout self, int base_height)
1240 CODE: 1518 CODE:
1241 if (self->base_height != base_height) 1519 if (self->base_height != base_height)
1242 { 1520 {
1243 self->base_height = base_height; 1521 self->base_height = base_height;
1244 layout_update_font (self); 1522 layout_update_font (self);
1245 } 1523 }
1246 1524
1247void 1525void
1312 1590
1313void 1591void
1314cursor_pos (DC::Layout self, int index) 1592cursor_pos (DC::Layout self, int index)
1315 PPCODE: 1593 PPCODE:
1316{ 1594{
1317 PangoRectangle strong_pos; 1595 PangoRectangle pos;
1318 pango_layout_get_cursor_pos (self->pl, index, &strong_pos, 0); 1596 pango_layout_get_cursor_pos (self->pl, index, &pos, 0);
1319 1597
1320 EXTEND (SP, 3); 1598 EXTEND (SP, 3);
1321 PUSHs (sv_2mortal (newSViv (strong_pos.x / PANGO_SCALE))); 1599 PUSHs (sv_2mortal (newSViv (pos.x / PANGO_SCALE)));
1322 PUSHs (sv_2mortal (newSViv (strong_pos.y / PANGO_SCALE))); 1600 PUSHs (sv_2mortal (newSViv (pos.y / PANGO_SCALE)));
1323 PUSHs (sv_2mortal (newSViv (strong_pos.height / PANGO_SCALE))); 1601 PUSHs (sv_2mortal (newSViv (pos.height / PANGO_SCALE)));
1324} 1602}
1325 1603
1326void 1604void
1327index_to_line_x (DC::Layout self, int index, int trailing = 0) 1605index_to_line_x (DC::Layout self, int index, int trailing = 0)
1328 PPCODE: 1606 PPCODE:
1329{ 1607{
1330 int line, x; 1608 int line, x;
1331 1609
1332 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);
1333#if !(defined (PANGO_VERSION_CHECK) && PANGO_VERSION_CHECK (1, 17, 3)) 1611#if !PANGO_VERSION_CHECK (1, 17, 3)
1334 /* pango bug: line is between 1..numlines, not 0..numlines-1 */ 1612 /* pango bug: line is between 1..numlines, not 0..numlines-1 */
1335 --line; 1613 --line;
1336#endif 1614#endif
1337 EXTEND (SP, 2); 1615 EXTEND (SP, 2);
1338 PUSHs (sv_2mortal (newSViv (line))); 1616 PUSHs (sv_2mortal (newSViv (line)));
1365} 1643}
1366 1644
1367void 1645void
1368render (DC::Layout self, float x, float y, int flags = 0) 1646render (DC::Layout self, float x, float y, int flags = 0)
1369 CODE: 1647 CODE:
1370 rc_clear (self->rc); 1648 self->rc.clear ();
1371 pango_opengl_render_layout_subpixel ( 1649 pango_opengl_render_layout_subpixel (
1372 self->pl, 1650 self->pl,
1373 self->rc, 1651 &self->rc,
1374 x * PANGO_SCALE, y * PANGO_SCALE, 1652 x * PANGO_SCALE, y * PANGO_SCALE,
1375 self->r, self->g, self->b, self->a, 1653 self->r, self->g, self->b, self->a,
1376 flags 1654 flags
1377 ); 1655 );
1378 // we assume that context_change actually clears/frees stuff 1656 // we assume that context_change actually clears/frees stuff
1389 gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 1667 gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1390 GL_ONE , GL_ONE_MINUS_SRC_ALPHA); 1668 GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1391 glEnable (GL_ALPHA_TEST); 1669 glEnable (GL_ALPHA_TEST);
1392 glAlphaFunc (GL_GREATER, 7.f / 255.f); 1670 glAlphaFunc (GL_GREATER, 7.f / 255.f);
1393 1671
1394 rc_draw (self->rc); 1672 self->rc.draw ();
1395 1673
1396 glDisable (GL_ALPHA_TEST); 1674 glDisable (GL_ALPHA_TEST);
1397 glDisable (GL_BLEND); 1675 glDisable (GL_BLEND);
1398 glDisable (GL_TEXTURE_2D); 1676 glDisable (GL_TEXTURE_2D);
1399} 1677}
1474 glDisable (GL_ALPHA_TEST); 1752 glDisable (GL_ALPHA_TEST);
1475 glDisable (GL_BLEND); 1753 glDisable (GL_BLEND);
1476 } 1754 }
1477} 1755}
1478 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
1479IV 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)
1480 CODE: 1879 CODE:
1481{ 1880{
1482 GLint width; 1881 GLint width;
1483 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);
1490MODULE = Deliantra::Client PACKAGE = DC::Map 1889MODULE = Deliantra::Client PACKAGE = DC::Map
1491 1890
1492PROTOTYPES: DISABLE 1891PROTOTYPES: DISABLE
1493 1892
1494DC::Map 1893DC::Map
1495new (SV *class) 1894new (SV *klass)
1496 CODE: 1895 CODE:
1497 New (0, RETVAL, 1, struct map); 1896 New (0, RETVAL, 1, mapgrid);
1498 RETVAL->x = 0; 1897 RETVAL->x = 0;
1499 RETVAL->y = 0; 1898 RETVAL->y = 0;
1500 RETVAL->w = 0; 1899 RETVAL->w = 0;
1501 RETVAL->h = 0; 1900 RETVAL->h = 0;
1502 RETVAL->ox = 0; 1901 RETVAL->ox = 0;
1539 1938
1540void 1939void
1541set_smooth (DC::Map self, int face, int smooth, int level) 1940set_smooth (DC::Map self, int face, int smooth, int level)
1542 CODE: 1941 CODE:
1543{ 1942{
1544 tileid texid; 1943 tileid texid;
1545 maptex *tex; 1944 maptex *tex;
1546 1945
1547 if (face < 0 || face >= self->faces) 1946 if (face < 0 || face >= self->faces)
1548 return; 1947 return;
1549 1948
1550 if (smooth < 0 || smooth >= self->faces) 1949 if (smooth < 0 || smooth >= self->faces)
1551 return; 1950 return;
1552 1951
1553 texid = self->face2tile [face]; 1952 texid = self->face2tile [face];
1554 1953
1555 if (!texid) 1954 if (!texid)
1556 return; 1955 return;
1557 1956
1558 tex = self->tex + texid; 1957 tex = self->tex + texid;
1587 //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);
1588 // use uglier nearest interpolation because linear suffers 1987 // use uglier nearest interpolation because linear suffers
1589 // from transparent color bleeding and ugly wrapping effects. 1988 // from transparent color bleeding and ugly wrapping effects.
1590 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1989 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1591} 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 }
1592 2011
1593int 2012int
1594ox (DC::Map self) 2013ox (DC::Map self)
1595 ALIAS: 2014 ALIAS:
1596 oy = 1 2015 oy = 1
1628 self->ox += dx; self->x += dx; 2047 self->ox += dx; self->x += dx;
1629 self->oy += dy; self->y += dy; 2048 self->oy += dy; self->y += dy;
1630 2049
1631 while (self->y < 0) 2050 while (self->y < 0)
1632 { 2051 {
1633 Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y); 2052 prepend (self->row, self->rows, MAP_EXTEND_Y);
1634 2053
1635 self->rows += MAP_EXTEND_Y; 2054 self->rows += MAP_EXTEND_Y;
1636 self->y += MAP_EXTEND_Y; 2055 self->y += MAP_EXTEND_Y;
1637 } 2056 }
1638} 2057}
1639 2058
1640SV * 2059SV *
1641map1a_update (DC::Map self, SV *data_, int extmap) 2060map1a_update (DC::Map self, SV *data_)
1642 CODE: 2061 CODE:
1643{ 2062{
1644 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_); 2063 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1645 uint8_t *data_end = (uint8_t *)SvEND (data_); 2064 uint8_t *data_end = (uint8_t *)SvEND (data_);
1646 mapcell *cell; 2065 mapcell *cell;
1667 2086
1668 //TODO: don't trust server data to be in-range(!) 2087 //TODO: don't trust server data to be in-range(!)
1669 2088
1670 if (flags & 8) 2089 if (flags & 8)
1671 { 2090 {
2091 uint8_t ext, cmd;
2092
1672 if (extmap) 2093 do
1673 { 2094 {
1674 uint8_t ext, cmd; 2095 ext = *data++;
2096 cmd = ext & 0x7f;
1675 2097
1676 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
1677 { 2101 {
1678 ext = *data++;
1679 cmd = ext & 0x3f;
1680
1681 if (cmd < 4)
1682 cell->darkness = 255 - ext * 64 + 1;
1683 else if (cmd == 5) // health
1684 {
1685 cell->stat_width = 1; 2102 cell->stat_width = 1;
1686 cell->stat_hp = *data++; 2103 cell->stat_hp = *data++;
1687 }
1688 else if (cmd == 6) // monster width
1689 cell->stat_width = *data++ + 1;
1690 else if (cmd == 0x47)
1691 {
1692 if (*data == 4)
1693 ; // decode player count
1694
1695 data += *data + 1;
1696 }
1697 else if (cmd == 8) // cell flags
1698 cell->flags = *data++;
1699 else if (ext & 0x40) // unknown, multibyte => skip
1700 data += *data + 1;
1701 else
1702 data++;
1703 } 2104 }
1704 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++;
1705 } 2122 }
1706 else 2123 while (ext & 0x80);
1707 cell->darkness = *data++ + 1;
1708 } 2124 }
1709 2125
1710 for (z = 0; z <= 2; ++z) 2126 for (z = 0; z <= 2; ++z)
1711 if (flags & (4 >> z)) 2127 if (flags & (4 >> z))
1712 { 2128 {
1715 cell->tile [z] = self->face2tile [face]; 2131 cell->tile [z] = self->face2tile [face];
1716 2132
1717 if (cell->tile [z]) 2133 if (cell->tile [z])
1718 { 2134 {
1719 maptex *tex = self->tex + cell->tile [z]; 2135 maptex *tex = self->tex + cell->tile [z];
2136 tex->unused = 0;
1720 if (!tex->name) 2137 if (!tex->name)
1721 av_push (missing, newSViv (cell->tile [z])); 2138 av_push (missing, newSViv (cell->tile [z]));
1722 2139
1723 if (tex->smoothtile) 2140 if (tex->smoothtile)
1724 { 2141 {
1725 maptex *smooth = self->tex + tex->smoothtile; 2142 maptex *smooth = self->tex + tex->smoothtile;
2143 smooth->unused = 0;
1726 if (!smooth->name) 2144 if (!smooth->name)
1727 av_push (missing, newSViv (tex->smoothtile)); 2145 av_push (missing, newSViv (tex->smoothtile));
1728 } 2146 }
1729 } 2147 }
1730 } 2148 }
1731 } 2149 }
1732 else 2150 else
1733 cell->darkness = 0; 2151 CELL_CLEAR (cell);
1734 } 2152 }
1735} 2153}
1736 OUTPUT: 2154 OUTPUT:
1737 RETVAL 2155 RETVAL
1738 2156
1758 ? self->row + y 2176 ? self->row + y
1759 : 0; 2177 : 0;
1760 2178
1761 for (x = x0; x < x1; x++) 2179 for (x = x0; x < x1; x++)
1762 { 2180 {
1763 int r = 32, g = 32, b = 32, a = 192; 2181 unsigned int r = 32, g = 32, b = 32, a = 192;
1764 2182
1765 if (row && row->c0 <= x && x < row->c1) 2183 if (row && row->c0 <= x && x < row->c1)
1766 { 2184 {
1767 mapcell *cell = row->col + (x - row->c0); 2185 mapcell *cell = row->col + (x - row->c0);
1768 2186
1770 { 2188 {
1771 maptex tex = self->tex [cell->tile [z]]; 2189 maptex tex = self->tex [cell->tile [z]];
1772 int a0 = 255 - tex.a; 2190 int a0 = 255 - tex.a;
1773 int a1 = tex.a; 2191 int a1 = tex.a;
1774 2192
1775 r = (r * a0 + tex.r * a1) / 255; 2193 r = div255 (r * a0 + tex.r * a1);
1776 g = (g * a0 + tex.g * a1) / 255; 2194 g = div255 (g * a0 + tex.g * a1);
1777 b = (b * a0 + tex.b * a1) / 255; 2195 b = div255 (b * a0 + tex.b * a1);
1778 a = (a * a0 + tex.a * a1) / 255; 2196 a = div255 (a * a0 + tex.a * a1);
1779 } 2197 }
1780 } 2198 }
1781 2199
1782 *map++ = (r ) 2200 *map++ = (r )
1783 | (g << 8) 2201 | (g << 8)
1784 | (b << 16) 2202 | (b << 16)
1785 | (a << 24); 2203 | (a << 24);
1786 } 2204 }
1787 } 2205 }
1788 2206
1789 RETVAL = map_sv; 2207 RETVAL = map_sv;
1790} 2208}
1791 OUTPUT: 2209 OUTPUT:
1792 RETVAL 2210 RETVAL
1793 2211
1794void 2212void
1795draw (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)
1796 CODE: 2214 CODE:
1797{ 2215{
1798 int x, y, z; 2216 int x, y, z;
1799 2217
1800 HV *smooth = (HV *)sv_2mortal ((SV *)newHV ());
1801 uint32_t smooth_level[256 / 32]; // one bit for every possible smooth level
1802 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!
1803 smooth_key skey; 2219 int pl_x, pl_y;
1804 2220 maptex pl_tex;
1805 rc_t *rc = rc_alloc (); 2221 rc_t rc;
2222 rc_t rc_ov;
1806 rc_key_t key; 2223 rc_key_t key;
1807 rc_array_t *arr; 2224 rc_t::array_t *arr;
1808 2225
2226 pl_tex.name = 0;
2227
1809 // thats current max. sorry. 2228 // that's current max. sorry.
1810 if (sw > 255) sw = 255; 2229 if (sw > 255) sw = 255;
1811 if (sh > 255) sh = 255; 2230 if (sh > 255) sh = 255;
1812
1813 // clear key, in case of extra padding
1814 memset (&skey, 0, sizeof (skey));
1815 2231
1816 memset (&key, 0, sizeof (key)); 2232 memset (&key, 0, sizeof (key));
1817 key.r = 255; 2233 key.r = 255;
1818 key.g = 255; 2234 key.g = 255;
1819 key.b = 255; 2235 key.b = 255;
1820 key.a = 255; 2236 key.a = 255;
1821 key.mode = GL_QUADS; 2237 key.mode = GL_QUADS;
1822 key.format = GL_T2F_V3F; 2238 key.format = GL_T2F_V3F;
1823 key.texname = -1;
1824 2239
1825 mx += self->x; 2240 mx += self->x;
1826 my += self->y; 2241 my += self->y;
1827 2242
1828 // first pass: determine smooth_max 2243 // first pass: determine smooth_max
1829 // rather ugly, if you ask me 2244 // rather ugly, if you ask me
1830 // could also be stored inside mapcell and updated on change 2245 // could also be stored inside mapcell and updated on change
1831 memset (smooth_max, 0, sizeof (smooth_max)); 2246 memset (smooth_max, 0, sizeof (smooth_max[0]) * (sh + 1));
1832 2247
1833 for (y = 0; y < sh; y++) 2248 for (y = 0; y < sh; y++)
1834 if (0 <= y + my && y + my < self->rows) 2249 if (0 <= y + my && y + my < self->rows)
1835 { 2250 {
1836 maprow *row = self->row + (y + my); 2251 maprow *row = self->row + (y + my);
1851 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2266 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1852 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 2267 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1853 2268
1854 for (z = 0; z <= 2; z++) 2269 for (z = 0; z <= 2; z++)
1855 { 2270 {
1856 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;
1857 2275
1858 for (y = 0; y < sh; y++) 2276 for (y = 0; y < sh; y++)
1859 if (0 <= y + my && y + my < self->rows) 2277 if (0 <= y + my && y + my < self->rows)
1860 { 2278 {
1861 maprow *row = self->row + (y + my); 2279 maprow *row = self->row + (y + my);
1871 maptex tex = self->tex [tile]; 2289 maptex tex = self->tex [tile];
1872 int px, py; 2290 int px, py;
1873 2291
1874 if (key.texname != tex.name) 2292 if (key.texname != tex.name)
1875 { 2293 {
2294 self->tex [tile].unused = 0;
2295
1876 if (!tex.name) 2296 if (!tex.name)
1877 tex = self->tex [2]; /* missing, replace by noface */ 2297 tex = self->tex [TEXID_NOFACE]; /* missing, replace by noface */
1878 2298
1879 key.texname = tex.name; 2299 key.texname = tex.name;
1880 arr = rc_array (rc, &key); 2300 arr = &rc.array (key);
1881 } 2301 }
1882 2302
1883 px = (x + 1) * T - tex.w; 2303 px = (x + 1) * Th - tex.w;
1884 py = (y + 1) * T - tex.h; 2304 py = (y + 1) * Tw - tex.h;
1885 2305
1886 rc_t2f_v3f (arr, 0 , 0 , px , py , 0); 2306 if (ecb_expect_false (cell->player == player) && ecb_expect_false (z == 2))
1887 rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0);
1888 rc_t2f_v3f (arr, tex.s, tex.t, px + tex.w, py + tex.h, 0);
1889 rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0);
1890
1891 if (cell->flags && z == 2)
1892 { 2307 {
1893 // overlays such as the speech bubble, probably more to come 2308 pl_x = px;
1894 if (cell->flags & 1) 2309 pl_y = py;
2310 pl_tex = tex;
1895 { 2311 continue;
1896 maptex tex = self->tex [1];
1897 int px = x * T + T * 2 / 32;
1898 int py = y * T - T * 6 / 32;
1899
1900 if (tex.name)
1901 {
1902 if (key.texname != tex.name)
1903 {
1904 key.texname = tex.name;
1905 arr = rc_array (rc, &key);
1906 }
1907
1908 rc_t2f_v3f (arr, 0 , 0 , px , py , 0);
1909 rc_t2f_v3f (arr, 0 , tex.t, px , py + T, 0);
1910 rc_t2f_v3f (arr, tex.s, tex.t, px + T, py + T, 0);
1911 rc_t2f_v3f (arr, tex.s, 0 , px + T, py , 0);
1912 }
1913 }
1914 } 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);
1915 2318
1916 // update smooth hash 2319 // update smooth hash
1917 if (tex.smoothtile) 2320 if (tex.smoothtile)
1918 { 2321 {
1919 skey.tile = tex.smoothtile; 2322 skey.tile = tex.smoothtile;
1920 skey.level = tex.smoothlevel; 2323 skey.level = tex.smoothlevel;
1921 2324
1922 smooth_level [tex.smoothlevel >> 5] |= ((uint32_t)1) << (tex.smoothlevel & 31); 2325 smooth_level[tex.smoothlevel] = 1;
1923 2326
1924 // 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
1925 // shifted +1|+1 so we always stay positive. 2328 // shifted +1|+1 so we always stay positive.
1926 2329
1927 // bits is ___n cccc CCCC bbbb 2330 // bits is ___n cccc CCCC bbbb
1935 2338
1936 // corners: 1 ┛· 2 ·┗ 4 ·· 8 ·· 2339 // corners: 1 ┛· 2 ·┗ 4 ·· 8 ··
1937 // ·· ·· ·┏ ┓· 2340 // ·· ·· ·┏ ┓·
1938 2341
1939 // full tile 2342 // full tile
1940 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);
1941 2344
1942 // borders 2345 // borders
1943 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);
1944 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);
1945 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);
1946 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);
1947 2350
1948 // corners 2351 // corners
1949 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);
1950 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);
1951 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);
1952 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);
1953 } 2376 }
1954 } 2377 }
1955 } 2378 }
1956 } 2379 }
1957 2380
1958 rc_draw (rc); 2381 rc.draw ();
1959 rc_clear (rc); 2382 rc.clear ();
1960 2383
1961 // go through all smoothlevels, lowest to highest, then draw. 2384 // go through all smoothlevels, lowest to highest, then draw.
1962 // this is basically counting sort 2385 // this is basically counting sort
1963 { 2386 {
1964 int w, b; 2387 int w, b;
1965 2388
1966 glEnable (GL_TEXTURE_2D); 2389 glEnable (GL_TEXTURE_2D);
1967 glBegin (GL_QUADS); 2390 glBegin (GL_QUADS);
1968 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)
1969 { 2394 {
1970 uint32_t smask = smooth_level [w]; 2395 smooth_key &skey = it->first;
1971 if (smask) 2396 IV bits = it->second;
1972 for (b = 0; b < 32; ++b) 2397
1973 if (smask & (((uint32_t)1) << b)) 2398 if (!(bits & 0x1000)
2399 && skey.level == level
2400 && level > smooth_max [skey.x][skey.y])
1974 { 2401 {
1975 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
1976 HE *he; 2410 if (tex.name)
1977
1978 hv_iterinit (smooth);
1979 while ((he = hv_iternext (smooth)))
1980 { 2411 {
1981 smooth_key *skey = (smooth_key *)HeKEY (he); 2412 // this time avoiding texture state changes
1982 IV bits = SvIVX (HeVAL (he)); 2413 // save gobs of state changes.
1983 2414 if (key.texname != tex.name)
1984 if (!(bits & 0x1000)
1985 && skey->level == level
1986 && level > smooth_max [skey->x][skey->y])
1987 { 2415 {
1988 maptex tex = self->tex [skey->tile]; 2416 self->tex [skey.tile].unused = 0;
1989 int px = (((int)skey->x) - 1) * T;
1990 int py = (((int)skey->y) - 1) * T;
1991 int border = bits & 15;
1992 int corner = (bits >> 8) & ~(bits >> 4) & 15;
1993 float dx = tex.s * .0625f; // 16 images/row
1994 float dy = tex.t * .5f ; // 2 images/column
1995 2417
1996 if (tex.name)
1997 {
1998 // this time avoiding texture state changes
1999 // save gobs of state changes.
2000 if (key.texname != tex.name)
2001 {
2002 glEnd (); 2418 glEnd ();
2003 glBindTexture (GL_TEXTURE_2D, key.texname = tex.name); 2419 glBindTexture (GL_TEXTURE_2D, key.texname = tex.name);
2004 glBegin (GL_QUADS); 2420 glBegin (GL_QUADS);
2005 } 2421 }
2006 2422
2007 if (border) 2423 if (border)
2008 { 2424 {
2009 float ox = border * dx; 2425 float ox = border * dx;
2010 2426
2011 glTexCoord2f (ox , 0.f ); glVertex2i (px , py ); 2427 glTexCoord2f (ox , 0.f ); glVertex2i (px , py );
2012 glTexCoord2f (ox , dy ); glVertex2i (px , py + T); 2428 glTexCoord2f (ox , dy ); glVertex2i (px , py + Th);
2013 glTexCoord2f (ox + dx, dy ); glVertex2i (px + T, py + T); 2429 glTexCoord2f (ox + dx, dy ); glVertex2i (px + Tw, py + Th);
2014 glTexCoord2f (ox + dx, 0.f ); glVertex2i (px + T, py ); 2430 glTexCoord2f (ox + dx, 0.f ); glVertex2i (px + Tw, py );
2015 } 2431 }
2016 2432
2017 if (corner) 2433 if (corner)
2018 { 2434 {
2019 float ox = corner * dx; 2435 float ox = corner * dx;
2020 2436
2021 glTexCoord2f (ox , dy ); glVertex2i (px , py ); 2437 glTexCoord2f (ox , dy ); glVertex2i (px , py );
2022 glTexCoord2f (ox , dy * 2.f); glVertex2i (px , py + T); 2438 glTexCoord2f (ox , dy * 2.f); glVertex2i (px , py + Th);
2023 glTexCoord2f (ox + dx, dy * 2.f); glVertex2i (px + T, py + T); 2439 glTexCoord2f (ox + dx, dy * 2.f); glVertex2i (px + Tw, py + Th);
2024 glTexCoord2f (ox + dx, dy ); glVertex2i (px + T, py ); 2440 glTexCoord2f (ox + dx, dy ); glVertex2i (px + Tw, py );
2025 }
2026 }
2027 } 2441 }
2028 } 2442 }
2029 } 2443 }
2030 } 2444 }
2031 2445
2032 glEnd (); 2446 glEnd ();
2033 glDisable (GL_TEXTURE_2D); 2447 glDisable (GL_TEXTURE_2D);
2034 key.texname = -1; 2448 key.texname = -1;
2035 } 2449 }
2036
2037 hv_clear (smooth);
2038 } 2450 }
2039 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
2040 glDisable (GL_BLEND); 2472 glDisable (GL_BLEND);
2041 rc_free (rc);
2042 2473
2043 // top layer: overlays such as the health bar 2474 // top layer: overlays such as the health bar
2044 for (y = 0; y < sh; y++) 2475 for (y = 0; y < sh; y++)
2045 if (0 <= y + my && y + my < self->rows) 2476 if (0 <= y + my && y + my < self->rows)
2046 { 2477 {
2049 for (x = 0; x < sw; x++) 2480 for (x = 0; x < sw; x++)
2050 if (row->c0 <= x + mx && x + mx < row->c1) 2481 if (row->c0 <= x + mx && x + mx < row->c1)
2051 { 2482 {
2052 mapcell *cell = row->col + (x + mx - row->c0); 2483 mapcell *cell = row->col + (x + mx - row->c0);
2053 2484
2054 int px = x * T; 2485 int px = x * Tw;
2055 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 }
2056 2493
2057 if (cell->stat_hp) 2494 if (cell->stat_hp)
2058 { 2495 {
2059 int width = cell->stat_width * T; 2496 int width = cell->stat_width * Tw;
2060 int thick = (sh * T / 32 + 27) / 28 + 1 + cell->stat_width; 2497 int thick = (sh * Th / 32 + 27) / 28 + 1 + cell->stat_width;
2061 2498
2062 glColor3ub (0, 0, 0); 2499 glColor3ub (0, 0, 0);
2063 glRectf (px + 1, py - thick - 2, 2500 glRectf (px + 1, py - thick - 2,
2064 px + width - 1, py); 2501 px + width - 1, py);
2065 2502
2071 } 2508 }
2072 } 2509 }
2073} 2510}
2074 2511
2075void 2512void
2076draw_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)
2077 CODE: 2514 CODE:
2078{ 2515{
2079 static float color[16][3] = { 2516 static float color[16][3] = {
2080 { 0.00F, 0.00F, 0.00F }, 2517 { 0.00f, 0.00f, 0.00f },
2081 { 1.00F, 1.00F, 1.00F }, 2518 { 1.00f, 1.00f, 1.00f },
2082 { 0.00F, 0.00F, 0.55F }, 2519 { 0.00f, 0.00f, 0.55f },
2083 { 1.00F, 0.00F, 0.00F }, 2520 { 1.00f, 0.00f, 0.00f },
2084 2521
2085 { 1.00F, 0.54F, 0.00F }, 2522 { 1.00f, 0.54f, 0.00f },
2086 { 0.11F, 0.56F, 1.00F }, 2523 { 0.11f, 0.56f, 1.00f },
2087 { 0.93F, 0.46F, 0.00F }, 2524 { 0.93f, 0.46f, 0.00f },
2088 { 0.18F, 0.54F, 0.34F }, 2525 { 0.18f, 0.54f, 0.34f },
2089 2526
2090 { 0.56F, 0.73F, 0.56F }, 2527 { 0.56f, 0.73f, 0.56f },
2091 { 0.80F, 0.80F, 0.80F }, 2528 { 0.80f, 0.80f, 0.80f },
2092 { 0.55F, 0.41F, 0.13F }, 2529 { 0.55f, 0.41f, 0.13f },
2093 { 0.99F, 0.77F, 0.26F }, 2530 { 0.99f, 0.77f, 0.26f },
2094 2531
2095 { 0.74F, 0.65F, 0.41F }, 2532 { 0.74f, 0.65f, 0.41f },
2096 2533
2097 { 0.00F, 1.00F, 1.00F }, 2534 { 0.00f, 1.00f, 1.00f },
2098 { 1.00F, 0.00F, 1.00F }, 2535 { 1.00f, 0.00f, 1.00f },
2099 { 1.00F, 1.00F, 0.00F }, 2536 { 1.00f, 1.00f, 0.00f },
2100 }; 2537 };
2101 2538
2102 int x, y; 2539 int x, y;
2103 2540
2104 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 */
2105 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 2548 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2106 glEnable (GL_BLEND); 2549 glEnable (GL_BLEND);
2107 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2550 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2108 glBegin (GL_QUADS); 2551 glBegin (GL_QUADS);
2109 2552
2110 for (y = 0; y < h; y++) 2553 for (y = 0; y < h; y++)
2114 2557
2115 if (m) 2558 if (m)
2116 { 2559 {
2117 float *c = color [m & 15]; 2560 float *c = color [m & 15];
2118 2561
2119 float tx1 = m & 0x40 ? 0.5 : 0.; 2562 float tx1 = m & 0x40 ? 0.5f : 0.f;
2120 float tx2 = tx1 + 0.5; 2563 float tx2 = tx1 + 0.5f;
2121 2564
2122 glColor4f (c[0], c[1], c[2], 0.75); 2565 glColor4f (c[0], c[1], c[2], 1);
2123 glTexCoord2f (tx1, 0.); glVertex2i (x , y ); 2566 glTexCoord2f (tx1, 0.); glVertex2i (x , y );
2124 glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1); 2567 glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
2125 glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1); 2568 glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
2126 glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y ); 2569 glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
2127 } 2570 }
2135void 2578void
2136fow_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)
2137 PPCODE: 2580 PPCODE:
2138{ 2581{
2139 int x, y; 2582 int x, y;
2140 int sw1 = sw + 2; 2583 int sw1 = sw + 2;
2141 int sh1 = sh + 2; 2584 int sh1 = sh + 2;
2142 int sh3 = sh * 3; 2585 int sh3 = sh * 3;
2143 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);
2144 uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1); 2589 uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1);
2145 SV *darkness3_sv = sv_2mortal (newSV (sw34 * sh3)); 2590 memset (darkness1, 0, sw1*sh1);
2146 uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv);
2147 2591
2148 SvPOK_only (darkness3_sv); 2592 SvPOK_only (darkness3_sv);
2149 SvCUR_set (darkness3_sv, sw34 * sh3); 2593 SvCUR_set (darkness3_sv, sw3 * sh3);
2150 2594
2151 mx += self->x - 1; 2595 mx += self->x - 1;
2152 my += self->y - 1; 2596 my += self->y - 1;
2153
2154 memset (darkness1, 255, sw1 * sh1);
2155 2597
2156 for (y = 0; y < sh1; y++) 2598 for (y = 0; y < sh1; y++)
2157 if (0 <= y + my && y + my < self->rows) 2599 if (0 <= y + my && y + my < self->rows)
2158 { 2600 {
2159 maprow *row = self->row + (y + my); 2601 maprow *row = self->row + (y + my);
2162 if (row->c0 <= x + mx && x + mx < row->c1) 2604 if (row->c0 <= x + mx && x + mx < row->c1)
2163 { 2605 {
2164 mapcell *cell = row->col + (x + mx - row->c0); 2606 mapcell *cell = row->col + (x + mx - row->c0);
2165 2607
2166 darkness1 [y * sw1 + x] = cell->darkness 2608 darkness1 [y * sw1 + x] = cell->darkness
2167 ? 255 - (cell->darkness - 1) 2609 ? DARKNESS_ADJUST (255 - (cell->darkness - 1))
2168 : 255 - FOW_DARKNESS; 2610 : DARKNESS_ADJUST (255 - FOW_DARKNESS);
2169 } 2611 }
2170 } 2612 }
2171 2613
2172 for (y = 0; y < sh; ++y) 2614 for (y = 0; y < sh; ++y)
2173 for (x = 0; x < sw; ++x) 2615 for (x = 0; x < sw; ++x)
2192 2634
2193 uint8_t r13 = (d13 + d23 + d12) / 3; 2635 uint8_t r13 = (d13 + d23 + d12) / 3;
2194 uint8_t r23 = d23; 2636 uint8_t r23 = d23;
2195 uint8_t r33 = (d23 + d33 + d32) / 3; 2637 uint8_t r33 = (d23 + d33 + d32) / 3;
2196 2638
2197 darkness3 [(y * 3 ) * sw34 + (x * 3 )] = MAX (d22, r11); 2639 darkness3 [(y * 3 ) * sw3 + (x * 3 )] = MAX (d22, r11);
2198 darkness3 [(y * 3 ) * sw34 + (x * 3 + 1)] = MAX (d22, r21); 2640 darkness3 [(y * 3 ) * sw3 + (x * 3 + 1)] = MAX (d22, r21);
2199 darkness3 [(y * 3 ) * sw34 + (x * 3 + 2)] = MAX (d22, r31); 2641 darkness3 [(y * 3 ) * sw3 + (x * 3 + 2)] = MAX (d22, r31);
2200 darkness3 [(y * 3 + 1) * sw34 + (x * 3 )] = MAX (d22, r12); 2642 darkness3 [(y * 3 + 1) * sw3 + (x * 3 )] = MAX (d22, r12);
2201 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 */
2202 darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 2)] = MAX (d22, r32); 2644 darkness3 [(y * 3 + 1) * sw3 + (x * 3 + 2)] = MAX (d22, r32);
2203 darkness3 [(y * 3 + 2) * sw34 + (x * 3 )] = MAX (d22, r13); 2645 darkness3 [(y * 3 + 2) * sw3 + (x * 3 )] = MAX (d22, r13);
2204 darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 1)] = MAX (d22, r23); 2646 darkness3 [(y * 3 + 2) * sw3 + (x * 3 + 1)] = MAX (d22, r23);
2205 darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 2)] = MAX (d22, r33); 2647 darkness3 [(y * 3 + 2) * sw3 + (x * 3 + 2)] = MAX (d22, r33);
2206 } 2648 }
2207 2649
2208 free (darkness1); 2650 free (darkness1);
2209 2651
2210 EXTEND (SP, 3); 2652 EXTEND (SP, 3);
2211 PUSHs (sv_2mortal (newSViv (sw34))); 2653 PUSHs (sv_2mortal (newSViv (sw3)));
2212 PUSHs (sv_2mortal (newSViv (sh3))); 2654 PUSHs (sv_2mortal (newSViv (sh3)));
2213 PUSHs (darkness3_sv); 2655 PUSHs (darkness3_sv);
2214} 2656}
2215 2657
2216SV * 2658SV *
2279 else 2721 else
2280 *data++ = 0; 2722 *data++ = 0;
2281 } 2723 }
2282 } 2724 }
2283 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 {
2284 SvPOK_only (data_sv); 2729 SvPOK_only (data_sv);
2285 SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv)); 2730 SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
2731 }
2732
2286 RETVAL = data_sv; 2733 RETVAL = data_sv;
2287} 2734}
2288 OUTPUT: 2735 OUTPUT:
2289 RETVAL 2736 RETVAL
2290 2737
2291void 2738void
2292set_rect (DC::Map self, int x0, int y0, uint8_t *data) 2739set_rect (DC::Map self, int x0, int y0, SV *data_sv)
2293 PPCODE: 2740 PPCODE:
2294{ 2741{
2295 int x, y, z; 2742 int x, y, z;
2296 int w, h; 2743 int w, h;
2297 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;
2298 2755
2299 if (*data++ != 0) 2756 if (*data++ != 0)
2300 XSRETURN_EMPTY; /* version mismatch */ 2757 XSRETURN_EMPTY; /* version mismatch */
2301 2758
2302 w = *data++ << 8; w |= *data++; 2759 w = *data++ << 8; w |= *data++;
2317 { 2774 {
2318 maprow *row = map_get_row (self, y); 2775 maprow *row = map_get_row (self, y);
2319 2776
2320 for (x = x0; x < x1; x++) 2777 for (x = x0; x < x1; x++)
2321 { 2778 {
2779 uint8_t flags;
2780
2781 if (data + 7 >= end)
2782 XSRETURN_EMPTY;
2783
2322 uint8_t flags = *data++; 2784 flags = *data++;
2323 2785
2324 if (flags) 2786 if (flags)
2325 { 2787 {
2326 mapcell *cell = row_get_cell (row, x); 2788 mapcell *cell = row_get_cell (row, x);
2327 tileid tile[3] = { 0, 0, 0 }; 2789 tileid tile[3] = { 0, 0, 0 };
2330 if (flags & 2) { tile[1] = *data++ << 8; tile[1] |= *data++; } 2792 if (flags & 2) { tile[1] = *data++ << 8; tile[1] |= *data++; }
2331 if (flags & 4) { tile[2] = *data++ << 8; tile[2] |= *data++; } 2793 if (flags & 4) { tile[2] = *data++ << 8; tile[2] |= *data++; }
2332 2794
2333 if (cell->darkness == 0) 2795 if (cell->darkness == 0)
2334 { 2796 {
2335 cell->darkness = 0; 2797 /*cell->darkness = 0;*/
2798 EXTEND (SP, 3);
2336 2799
2337 for (z = 0; z <= 2; z++) 2800 for (z = 0; z <= 2; z++)
2338 { 2801 {
2339 tileid t = tile [z]; 2802 tileid t = tile [z];
2340 2803
2341 if (t >= self->texs || (t && !self->tex [t].name)) 2804 if (t >= self->texs || (t && !self->tex [t].name))
2342 { 2805 {
2343 XPUSHs (sv_2mortal (newSViv (t))); 2806 PUSHs (sv_2mortal (newSViv (t)));
2344 need_texid (self, t); 2807 need_texid (self, t);
2345 } 2808 }
2346 2809
2347 cell->tile [z] = t; 2810 cell->tile [z] = t;
2348 } 2811 }
2353} 2816}
2354 2817
2355MODULE = Deliantra::Client PACKAGE = DC::RW 2818MODULE = Deliantra::Client PACKAGE = DC::RW
2356 2819
2357DC::RW 2820DC::RW
2358new (SV *class, SV *data_sv) 2821new (SV *klass, SV *data_sv)
2359 CODE: 2822 CODE:
2360{ 2823{
2361 STRLEN datalen; 2824 STRLEN datalen;
2362 char *data = SvPVbyte (data_sv, datalen); 2825 char *data = SvPVbyte (data_sv, datalen);
2363 2826
2365} 2828}
2366 OUTPUT: 2829 OUTPUT:
2367 RETVAL 2830 RETVAL
2368 2831
2369DC::RW 2832DC::RW
2370new_from_file (SV *class, const char *path, const char *mode = "rb") 2833new_from_file (SV *klass, const char *path, const char *mode = "rb")
2371 CODE: 2834 CODE:
2372 RETVAL = SDL_RWFromFile (path, mode); 2835 RETVAL = SDL_RWFromFile (path, mode);
2373 OUTPUT: 2836 OUTPUT:
2374 RETVAL 2837 RETVAL
2375 2838
2393 if (RETVAL < 0) 2856 if (RETVAL < 0)
2394 { 2857 {
2395 RETVAL = Mix_GroupOldest (-1); 2858 RETVAL = Mix_GroupOldest (-1);
2396 2859
2397 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)
2398 XSRETURN_UNDEF; 2866 XSRETURN_UNDEF;
2399 2867 }
2868 else
2400 Mix_HaltChannel (RETVAL); 2869 Mix_HaltChannel (RETVAL);
2401 } 2870 }
2402 2871
2403 Mix_UnregisterAllEffects (RETVAL); 2872 Mix_UnregisterAllEffects (RETVAL);
2404 Mix_Volume (RETVAL, 128); 2873 Mix_Volume (RETVAL, 128);
2405} 2874}
2452void 2921void
2453set_position_r (DC::Channel self, int dx, int dy, int maxdistance) 2922set_position_r (DC::Channel self, int dx, int dy, int maxdistance)
2454 CODE: 2923 CODE:
2455{ 2924{
2456 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));
2457 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;
2458 Mix_SetPosition (self, angle, CLAMP (distance, 0, 255)); 2927 Mix_SetPosition (self, angle, CLAMP (distance, 0, 255));
2459} 2928}
2460 2929
2461void 2930void
2462set_reverse_stereo (DC::Channel self, int flip) 2931set_reverse_stereo (DC::Channel self, int flip)
2465 2934
2466MODULE = Deliantra::Client PACKAGE = DC::MixChunk 2935MODULE = Deliantra::Client PACKAGE = DC::MixChunk
2467 2936
2468PROTOTYPES: DISABLE 2937PROTOTYPES: DISABLE
2469 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
2470DC::MixChunk 2951DC::MixChunk
2471new (SV *class, DC::RW rwops) 2952new (SV *klass, DC::RW rwops)
2472 CODE: 2953 CODE:
2473 RETVAL = Mix_LoadWAV_RW (rwops, 1); 2954 RETVAL = Mix_LoadWAV_RW (rwops, 1);
2474 OUTPUT: 2955 OUTPUT:
2475 RETVAL 2956 RETVAL
2476 2957
2506 OUTPUT: 2987 OUTPUT:
2507 RETVAL 2988 RETVAL
2508 2989
2509MODULE = Deliantra::Client PACKAGE = DC::MixMusic 2990MODULE = Deliantra::Client PACKAGE = DC::MixMusic
2510 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
2511int 3004int
2512volume (int volume = -1) 3005volume (int volume = -1)
2513 PROTOTYPE: ;$ 3006 PROTOTYPE: ;$
2514 CODE: 3007 CODE:
2515 if (items > 0) 3008 if (items > 0)
2526void 3019void
2527halt () 3020halt ()
2528 CODE: 3021 CODE:
2529 Mix_HaltMusic (); 3022 Mix_HaltMusic ();
2530 3023
3024int
3025playing ()
3026 CODE:
3027 RETVAL = Mix_PlayingMusic ();
3028 OUTPUT:
3029 RETVAL
3030
2531DC::MixMusic 3031DC::MixMusic
2532new (SV *class, DC::RW rwops) 3032new (SV *klass, DC::RW rwops)
2533 CODE: 3033 CODE:
2534 RETVAL = Mix_LoadMUS_RW (rwops); 3034 RETVAL = Mix_LoadMUS_RW (rwops);
2535 OUTPUT: 3035 OUTPUT:
2536 RETVAL 3036 RETVAL
2537 3037
2565 } *civ, const_iv[] = { 3065 } *civ, const_iv[] = {
2566# define const_iv(name) { # name, (IV)name } 3066# define const_iv(name) { # name, (IV)name }
2567 const_iv (GL_VENDOR), 3067 const_iv (GL_VENDOR),
2568 const_iv (GL_VERSION), 3068 const_iv (GL_VERSION),
2569 const_iv (GL_EXTENSIONS), 3069 const_iv (GL_EXTENSIONS),
3070 const_iv (GL_MAX_TEXTURE_UNITS),
2570 const_iv (GL_COLOR_MATERIAL), 3071 const_iv (GL_COLOR_MATERIAL),
2571 const_iv (GL_SMOOTH), 3072 const_iv (GL_SMOOTH),
2572 const_iv (GL_FLAT), 3073 const_iv (GL_FLAT),
2573 const_iv (GL_DITHER), 3074 const_iv (GL_DITHER),
2574 const_iv (GL_BLEND), 3075 const_iv (GL_BLEND),
2586 const_iv (GL_ZERO), 3087 const_iv (GL_ZERO),
2587 const_iv (GL_SRC_ALPHA), 3088 const_iv (GL_SRC_ALPHA),
2588 const_iv (GL_DST_ALPHA), 3089 const_iv (GL_DST_ALPHA),
2589 const_iv (GL_ONE_MINUS_SRC_ALPHA), 3090 const_iv (GL_ONE_MINUS_SRC_ALPHA),
2590 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),
2591 const_iv (GL_SRC_ALPHA_SATURATE), 3096 const_iv (GL_SRC_ALPHA_SATURATE),
2592 const_iv (GL_RGB), 3097 const_iv (GL_RGB),
2593 const_iv (GL_RGBA), 3098 const_iv (GL_RGBA),
2594 const_iv (GL_RGBA4), 3099 const_iv (GL_RGBA4),
2595 const_iv (GL_RGBA8), 3100 const_iv (GL_RGBA8),
2663 const_iv (GL_NICEST), 3168 const_iv (GL_NICEST),
2664 const_iv (GL_V2F), 3169 const_iv (GL_V2F),
2665 const_iv (GL_V3F), 3170 const_iv (GL_V3F),
2666 const_iv (GL_T2F_V3F), 3171 const_iv (GL_T2F_V3F),
2667 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),
2668# undef const_iv 3176# undef const_iv
2669 }; 3177 };
2670 3178
2671 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--)
2672 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 3180 newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv));
2673 3181
2674 texture_av = newAV (); 3182 texture_av = newAV ();
2675 AvREAL_off (texture_av); 3183 AvREAL_off (texture_av);
2676} 3184}
2677 3185
2679disable_GL_EXT_blend_func_separate () 3187disable_GL_EXT_blend_func_separate ()
2680 CODE: 3188 CODE:
2681 gl.BlendFuncSeparate = 0; 3189 gl.BlendFuncSeparate = 0;
2682 gl.BlendFuncSeparateEXT = 0; 3190 gl.BlendFuncSeparateEXT = 0;
2683 3191
2684char * 3192void
3193apple_nvidia_bug (int enable)
3194
3195const char *
2685gl_vendor () 3196gl_vendor ()
2686 CODE: 3197 CODE:
2687 RETVAL = (char *)glGetString (GL_VENDOR); 3198 RETVAL = (const char *)glGetString (GL_VENDOR);
2688 OUTPUT: 3199 OUTPUT:
2689 RETVAL 3200 RETVAL
2690 3201
2691char * 3202const char *
2692gl_version () 3203gl_version ()
2693 CODE: 3204 CODE:
2694 RETVAL = (char *)glGetString (GL_VERSION); 3205 RETVAL = (const char *)glGetString (GL_VERSION);
2695 OUTPUT: 3206 OUTPUT:
2696 RETVAL 3207 RETVAL
2697 3208
2698char * 3209const char *
2699gl_extensions () 3210gl_extensions ()
2700 CODE: 3211 CODE:
2701 RETVAL = (char *)glGetString (GL_EXTENSIONS); 3212 RETVAL = (const char *)glGetString (GL_EXTENSIONS);
2702 OUTPUT: 3213 OUTPUT:
2703 RETVAL 3214 RETVAL
2704 3215
2705const char *glGetString (GLenum pname) 3216const char *glGetString (GLenum pname)
3217 CODE:
3218 RETVAL = (const char *)glGetString (pname);
3219 OUTPUT:
3220 RETVAL
2706 3221
2707GLint glGetInteger (GLenum pname) 3222GLint glGetInteger (GLenum pname)
2708 CODE: 3223 CODE:
2709 glGetIntegerv (pname, &RETVAL); 3224 glGetIntegerv (pname, &RETVAL);
2710 OUTPUT: 3225 OUTPUT:
2718 3233
2719int glGetError () 3234int glGetError ()
2720 3235
2721void glFinish () 3236void glFinish ()
2722 3237
3238void glFlush ()
3239
2723void glClear (int mask) 3240void glClear (int mask)
2724 3241
2725void glClearColor (float r, float g, float b, float a = 1.0) 3242void glClearColor (float r, float g, float b, float a = 1.0)
2726 PROTOTYPE: @ 3243 PROTOTYPE: @
2727 3244
2736void glBlendFunc (int sfactor, int dfactor) 3253void glBlendFunc (int sfactor, int dfactor)
2737 3254
2738void glBlendFuncSeparate (int sa, int da, int saa, int daa) 3255void glBlendFuncSeparate (int sa, int da, int saa, int daa)
2739 CODE: 3256 CODE:
2740 gl_BlendFuncSeparate (sa, da, saa, daa); 3257 gl_BlendFuncSeparate (sa, da, saa, daa);
3258
3259# void glBlendEquation (int se)
2741 3260
2742void glDepthMask (int flag) 3261void glDepthMask (int flag)
2743 3262
2744void glLogicOp (int opcode) 3263void glLogicOp (int opcode)
2745 3264
2780void glRotate (float angle, float x, float y, float z) 3299void glRotate (float angle, float x, float y, float z)
2781 CODE: 3300 CODE:
2782 glRotatef (angle, x, y, z); 3301 glRotatef (angle, x, y, z);
2783 3302
2784void 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: @
2785 ALIAS: 3305 ALIAS:
2786 glColor_premultiply = 1 3306 glColor_premultiply = 1
2787 CODE: 3307 CODE:
2788 if (ix) 3308 if (ix)
2789 { 3309 {
2895 3415
2896void glEndList () 3416void glEndList ()
2897 3417
2898void glCallList (int list) 3418void glCallList (int list)
2899 3419
3420void c_init ()
3421 CODE:
3422 glPixelStorei (GL_PACK_ALIGNMENT , 1);
3423 glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
3424
2900MODULE = Deliantra::Client PACKAGE = DC::UI::Base 3425MODULE = Deliantra::Client PACKAGE = DC::UI::Base
2901 3426
2902PROTOTYPES: DISABLE 3427PROTOTYPES: DISABLE
2903 3428
2904void 3429void
2905find_widget (SV *self, NV x, NV y) 3430find_widget (SV *self, NV x, NV y)
2906 PPCODE: 3431 PPCODE:
2907{ 3432{
2908 if (within_widget (self, x, y)) 3433 if (within_widget (self, x, y))
2909 XPUSHs (self); 3434 XPUSHs (self);
2910} 3435}
2911 3436
2912BOOT: 3437BOOT:
2913{ 3438{
2921 3446
2922void 3447void
2923draw (SV *self) 3448draw (SV *self)
2924 CODE: 3449 CODE:
2925{ 3450{
2926 HV *hv; 3451 HV *hv;
2927 SV **svp; 3452 SV **svp;
2928 NV x, y, w, h; 3453 NV x, y, w, h;
2929 SV *draw_x_sv = GvSV (draw_x_gv); 3454 SV *draw_x_sv = GvSV (draw_x_gv);
2930 SV *draw_y_sv = GvSV (draw_y_gv); 3455 SV *draw_y_sv = GvSV (draw_y_gv);
2931 SV *draw_w_sv = GvSV (draw_w_gv); 3456 SV *draw_w_sv = GvSV (draw_w_gv);
2932 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