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.294 by root, Sat Dec 19 05:06:56 2009 UTC vs.
Revision 1.327 by root, Sun Nov 18 12:01:50 2018 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines