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.259 by root, Tue May 20 02:47:21 2008 UTC vs.
Revision 1.303 by root, Thu Apr 22 11:18:04 2010 UTC

19 19
20#ifdef _WIN32 20#ifdef _WIN32
21# undef pipe 21# undef pipe
22// microsoft vs. C 22// microsoft vs. C
23# define sqrtf(x) sqrt(x) 23# define sqrtf(x) sqrt(x)
24# define roundf(x) (int)(x)
25# define atan2f(x,y) atan2(x,y) 24# define atan2f(x,y) atan2(x,y)
26# define M_PI 3.14159265f 25# define M_PI 3.14159265f
27#endif 26#endif
28 27
29#include <assert.h> 28#include <assert.h>
38#include <SDL_thread.h> 37#include <SDL_thread.h>
39#include <SDL_endian.h> 38#include <SDL_endian.h>
40#include <SDL_image.h> 39#include <SDL_image.h>
41#include <SDL_mixer.h> 40#include <SDL_mixer.h>
42#include <SDL_opengl.h> 41#include <SDL_opengl.h>
42
43/* work around os x broken headers */
44#ifdef __MACOSX__
45typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
46typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
47typedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t);
48#endif
43 49
44#define PANGO_ENABLE_BACKEND 50#define PANGO_ENABLE_BACKEND
45#define G_DISABLE_CAST_CHECKS 51#define G_DISABLE_CAST_CHECKS
46 52
47#include <glib/gmacros.h> 53#include <glib/gmacros.h>
65# include <netinet/in.h> 71# include <netinet/in.h>
66# include <netinet/tcp.h> 72# include <netinet/tcp.h>
67# include <inttypes.h> 73# include <inttypes.h>
68#endif 74#endif
69 75
76#if __GNUC__ >= 4
77# define expect(expr,value) __builtin_expect ((expr),(value))
78#else
79# define expect(expr,value) (expr)
80#endif
81
82#define expect_false(expr) expect ((expr) != 0, 0)
83#define expect_true(expr) expect ((expr) != 0, 1)
84
70#define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, object replacement character */ 85#define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, object replacement character */
71 86
87/* this is used as fow flag as well, so has to have a different value */
88/* then anything that is computed by incoming darkness */
72#define FOW_DARKNESS 32 89#define FOW_DARKNESS 50
90#define DARKNESS_ADJUST(n) (n)
73 91
74#define MAP_EXTEND_X 32 92#define MAP_EXTEND_X 32
75#define MAP_EXTEND_Y 512 93#define MAP_EXTEND_Y 512
76 94
77#define MIN_FONT_HEIGHT 10 95#define MIN_FONT_HEIGHT 10
78 96
79/* mask out modifiers we are not interested in */ 97/* mask out modifiers we are not interested in */
80#define MOD_MASK (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_META) 98#define MOD_MASK (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_META)
81 99
82#if 0 100#define KMOD_LRAM 0x10000 // our extension
83# define PARACHUTE SDL_INIT_NOPARACHUTE 101
84#else 102#define TEXID_SPEECH 1
85# define PARACHUTE 0 103#define TEXID_NOFACE 2
86#endif
87 104
88static AV *texture_av; 105static AV *texture_av;
89 106
90static struct 107static struct
91{ 108{
223 int w, h; 240 int w, h;
224 float s, t; 241 float s, t;
225 uint8_t r, g, b, a; 242 uint8_t r, g, b, a;
226 tileid smoothtile; 243 tileid smoothtile;
227 uint8_t smoothlevel; 244 uint8_t smoothlevel;
245 uint8_t unused; /* set to zero on use */
228} maptex; 246} maptex;
229 247
230typedef struct { 248typedef struct {
231 uint32_t player; 249 uint32_t player;
232 tileid tile[3]; 250 tileid tile[3];
364 self->oy = 0; 382 self->oy = 0;
365 self->row = 0; 383 self->row = 0;
366 self->rows = 0; 384 self->rows = 0;
367} 385}
368 386
387#define CELL_CLEAR(cell) \
388 do { \
389 if ((cell)->player) \
390 (cell)->tile [2] = 0; \
391 (cell)->darkness = 0; \
392 (cell)->stat_hp = 0; \
393 (cell)->flags = 0; \
394 (cell)->player = 0; \
395 } while (0)
396
369static void 397static void
370map_blank (DC__Map self, int x0, int y0, int w, int h) 398map_blank (DC__Map self, int x0, int y0, int w, int h)
371{ 399{
372 int x, y; 400 int x, y;
373 maprow *row; 401 maprow *row;
387 if (x >= row->c1) 415 if (x >= row->c1)
388 break; 416 break;
389 417
390 cell = row->col + x - row->c0; 418 cell = row->col + x - row->c0;
391 419
392 cell->darkness = 0; 420 CELL_CLEAR (cell);
393 cell->stat_hp = 0;
394 cell->flags = 0;
395 cell->player = 0;
396 } 421 }
397 } 422 }
398} 423}
399 424
400typedef struct { 425typedef struct {
511 if (!svp || !SvTRUE (*svp)) 536 if (!svp || !SvTRUE (*svp))
512 return 0; 537 return 0;
513 538
514 return 1; 539 return 1;
515} 540}
541
542/******************************************************************************/
543
544/* process keyboard modifiers */
545static int
546mod_munge (int mod)
547{
548 mod &= MOD_MASK;
549
550 if (mod & (KMOD_META | KMOD_ALT))
551 mod |= KMOD_LRAM;
552
553 return mod;
554}
555
556static void
557deliantra_main ()
558{
559 char *argv[] = { 0 };
560 call_argv ("::main", G_DISCARD | G_VOID, argv);
561}
562
563#ifdef __MACOSX__
564 /* to due surprising braindamage on the side of SDL design, we
565 * do some mind-boggling hack here: SDL requires a custom main()
566 * on OS X, so... we provide one and call the original main(), which,
567 * due to share dlibrary magic, calls -lSDLmain's main, not perl's main,
568 * and which calls our main (== SDL_main) back.
569 */
570 extern C_LINKAGE int
571 main (int argc, char *argv[])
572 {
573 deliantra_main ();
574 }
575
576 #undef main
577
578 extern C_LINKAGE int main (int argc, char *argv[]);
579
580 static void
581 SDL_braino (void)
582 {
583 char *argv[] = { "deliantra client", 0 };
584 (main) (1, argv);
585 }
586#else
587 static void
588 SDL_braino (void)
589 {
590 deliantra_main ();
591 }
592#endif
516 593
517MODULE = Deliantra::Client PACKAGE = DC 594MODULE = Deliantra::Client PACKAGE = DC
518 595
519PROTOTYPES: ENABLE 596PROTOTYPES: ENABLE
520 597
549 const_iv (SDL_USEREVENT), 626 const_iv (SDL_USEREVENT),
550 627
551 const_iv (SDL_APPINPUTFOCUS), 628 const_iv (SDL_APPINPUTFOCUS),
552 const_iv (SDL_APPMOUSEFOCUS), 629 const_iv (SDL_APPMOUSEFOCUS),
553 const_iv (SDL_APPACTIVE), 630 const_iv (SDL_APPACTIVE),
631
632
633 const_iv (SDLK_UNKNOWN),
634 const_iv (SDLK_FIRST),
635 const_iv (SDLK_BACKSPACE),
636 const_iv (SDLK_TAB),
637 const_iv (SDLK_CLEAR),
638 const_iv (SDLK_RETURN),
639 const_iv (SDLK_PAUSE),
640 const_iv (SDLK_ESCAPE),
641 const_iv (SDLK_SPACE),
642 const_iv (SDLK_EXCLAIM),
643 const_iv (SDLK_QUOTEDBL),
644 const_iv (SDLK_HASH),
645 const_iv (SDLK_DOLLAR),
646 const_iv (SDLK_AMPERSAND),
647 const_iv (SDLK_QUOTE),
648 const_iv (SDLK_LEFTPAREN),
649 const_iv (SDLK_RIGHTPAREN),
650 const_iv (SDLK_ASTERISK),
651 const_iv (SDLK_PLUS),
652 const_iv (SDLK_COMMA),
653 const_iv (SDLK_MINUS),
654 const_iv (SDLK_PERIOD),
655 const_iv (SDLK_SLASH),
656 const_iv (SDLK_0),
657 const_iv (SDLK_1),
658 const_iv (SDLK_2),
659 const_iv (SDLK_3),
660 const_iv (SDLK_4),
661 const_iv (SDLK_5),
662 const_iv (SDLK_6),
663 const_iv (SDLK_7),
664 const_iv (SDLK_8),
665 const_iv (SDLK_9),
666 const_iv (SDLK_COLON),
667 const_iv (SDLK_SEMICOLON),
668 const_iv (SDLK_LESS),
669 const_iv (SDLK_EQUALS),
670 const_iv (SDLK_GREATER),
671 const_iv (SDLK_QUESTION),
672 const_iv (SDLK_AT),
673
674 const_iv (SDLK_LEFTBRACKET),
675 const_iv (SDLK_BACKSLASH),
676 const_iv (SDLK_RIGHTBRACKET),
677 const_iv (SDLK_CARET),
678 const_iv (SDLK_UNDERSCORE),
679 const_iv (SDLK_BACKQUOTE),
680 const_iv (SDLK_DELETE),
554 681
555 const_iv (SDLK_FIRST), 682 const_iv (SDLK_FIRST),
556 const_iv (SDLK_LAST), 683 const_iv (SDLK_LAST),
557 const_iv (SDLK_KP0), 684 const_iv (SDLK_KP0),
558 const_iv (SDLK_KP1), 685 const_iv (SDLK_KP1),
634 const_iv (KMOD_RMETA), 761 const_iv (KMOD_RMETA),
635 const_iv (KMOD_NUM), 762 const_iv (KMOD_NUM),
636 const_iv (KMOD_CAPS), 763 const_iv (KMOD_CAPS),
637 const_iv (KMOD_MODE), 764 const_iv (KMOD_MODE),
638 765
766 const_iv (KMOD_LRAM),
767
639 const_iv (MIX_DEFAULT_FORMAT), 768 const_iv (MIX_DEFAULT_FORMAT),
769
770 const_iv (SDL_INIT_TIMER),
771 const_iv (SDL_INIT_AUDIO),
772 const_iv (SDL_INIT_VIDEO),
773 const_iv (SDL_INIT_CDROM),
774 const_iv (SDL_INIT_JOYSTICK),
775 const_iv (SDL_INIT_EVERYTHING),
776 const_iv (SDL_INIT_NOPARACHUTE),
777 const_iv (SDL_INIT_EVENTTHREAD),
778
779 const_iv (SDL_GL_RED_SIZE),
780 const_iv (SDL_GL_GREEN_SIZE),
781 const_iv (SDL_GL_BLUE_SIZE),
782 const_iv (SDL_GL_ALPHA_SIZE),
783 const_iv (SDL_GL_DOUBLEBUFFER),
784 const_iv (SDL_GL_BUFFER_SIZE),
785 const_iv (SDL_GL_DEPTH_SIZE),
786 const_iv (SDL_GL_STENCIL_SIZE),
787 const_iv (SDL_GL_ACCUM_RED_SIZE),
788 const_iv (SDL_GL_ACCUM_GREEN_SIZE),
789 const_iv (SDL_GL_ACCUM_BLUE_SIZE),
790 const_iv (SDL_GL_ACCUM_ALPHA_SIZE),
791 const_iv (SDL_GL_STEREO),
792 const_iv (SDL_GL_MULTISAMPLEBUFFERS),
793 const_iv (SDL_GL_MULTISAMPLESAMPLES),
794 const_iv (SDL_GL_ACCELERATED_VISUAL),
795 const_iv (SDL_GL_SWAP_CONTROL),
796
797 const_iv (FOW_DARKNESS)
640# undef const_iv 798# undef const_iv
641 }; 799 };
642 800
643 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) 801 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
644 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 802 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
665NV ceil (NV x) 823NV ceil (NV x)
666 824
667IV minpot (UV n) 825IV minpot (UV n)
668 826
669IV popcount (UV n) 827IV popcount (UV n)
828
829NV distance (NV dx, NV dy)
830 CODE:
831 RETVAL = pow (dx * dx + dy * dy, 0.5);
832 OUTPUT:
833 RETVAL
670 834
671void 835void
672pango_init () 836pango_init ()
673 CODE: 837 CODE:
674{ 838{
680 pango_context_set_language (opengl_context, pango_language_from_string ("en")); 844 pango_context_set_language (opengl_context, pango_language_from_string ("en"));
681 /*pango_context_set_base_dir (opengl_context, PANGO_DIRECTION_WEAK_LTR);*/ 845 /*pango_context_set_base_dir (opengl_context, PANGO_DIRECTION_WEAK_LTR);*/
682#endif 846#endif
683} 847}
684 848
685char *
686SDL_GetError () 849char *SDL_GetError ()
687 850
688int 851void SDL_braino ()
689SDL_Init (U32 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | PARACHUTE)
690 852
691void 853int SDL_Init (U32 flags)
854
855int SDL_InitSubSystem (U32 flags)
856
857void SDL_QuitSubSystem (U32 flags)
858
692SDL_Quit () 859void SDL_Quit ()
860
861int SDL_GL_SetAttribute (int attr, int value)
862
863int SDL_GL_GetAttribute (int attr)
864 CODE:
865 if (SDL_GL_GetAttribute (attr, &RETVAL))
866 XSRETURN_UNDEF;
867 OUTPUT:
868 RETVAL
693 869
694void 870void
695SDL_ListModes (int rgb, int alpha) 871SDL_ListModes (int rgb, int alpha)
696 PPCODE: 872 PPCODE:
697{ 873{
709 SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0); 885 SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0);
710 SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE , 0); 886 SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE , 0);
711 SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0); 887 SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0);
712 888
713 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1); 889 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
714#if SDL_VERSION_ATLEAST(1,2,10)
715 SDL_GL_SetAttribute (SDL_GL_ACCELERATED_VISUAL, 1);
716 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1); 890 SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
717#endif
718 891
719 m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL); 892 m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL);
720 893
721 if (m && m != (SDL_Rect **)-1) 894 if (m && m != (SDL_Rect **)-1)
722 while (*m) 895 while (*m)
723 { 896 {
724 if ((*m)->w >= 800 && (*m)->h >= 480) 897 if ((*m)->w >= 400 && (*m)->h >= 300)
725 { 898 {
726 AV *av = newAV (); 899 AV *av = newAV ();
727 av_push (av, newSViv ((*m)->w)); 900 av_push (av, newSViv ((*m)->w));
728 av_push (av, newSViv ((*m)->h)); 901 av_push (av, newSViv ((*m)->h));
729 av_push (av, newSViv (rgb)); 902 av_push (av, newSViv (rgb));
757 930
758 SDL_WM_SetCaption ("Deliantra MORPG Client " VERSION, "Deliantra"); 931 SDL_WM_SetCaption ("Deliantra MORPG Client " VERSION, "Deliantra");
759#define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name); 932#define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name);
760#include "glfunc.h" 933#include "glfunc.h"
761#undef GL_FUNC 934#undef GL_FUNC
935
936 if (!gl.ActiveTexture ) gl.ActiveTexture = gl.ActiveTextureARB;
937 if (!gl.MultiTexCoord2f) gl.MultiTexCoord2f = gl.MultiTexCoord2fARB;
762 } 938 }
763} 939}
764 OUTPUT: 940 OUTPUT:
765 RETVAL 941 RETVAL
766 942
792 { 968 {
793 case SDL_KEYDOWN: 969 case SDL_KEYDOWN:
794 case SDL_KEYUP: 970 case SDL_KEYUP:
795 hv_store (hv, "state", 5, newSViv (ev.key.state), 0); 971 hv_store (hv, "state", 5, newSViv (ev.key.state), 0);
796 hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0); 972 hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0);
797 hv_store (hv, "mod", 3, newSViv (ev.key.keysym.mod & MOD_MASK), 0); 973 hv_store (hv, "mod", 3, newSViv (mod_munge (ev.key.keysym.mod)), 0);
798 hv_store (hv, "cmod", 4, newSViv (SDL_GetModState () & MOD_MASK), 0); /* current mode */ 974 hv_store (hv, "cmod", 4, newSViv (mod_munge (SDL_GetModState ())), 0); /* current mode */
799 hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0); 975 hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0);
800 break; 976 break;
801 977
802 case SDL_ACTIVEEVENT: 978 case SDL_ACTIVEEVENT:
803 hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0); 979 hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0);
821 x = ev.motion.x; 997 x = ev.motion.x;
822 y = ev.motion.y; 998 y = ev.motion.y;
823 SDL_PeepEvents (&ev, 1, SDL_GETEVENT, SDL_EVENTMASK (SDL_MOUSEMOTION)); 999 SDL_PeepEvents (&ev, 1, SDL_GETEVENT, SDL_EVENTMASK (SDL_MOUSEMOTION));
824 } 1000 }
825 1001
826 hv_store (hv, "mod", 3, newSViv (SDL_GetModState () & MOD_MASK), 0); 1002 hv_store (hv, "mod", 3, newSViv (mod_munge (SDL_GetModState ())), 0);
827 hv_store (hv, "state", 5, newSViv (state), 0); 1003 hv_store (hv, "state", 5, newSViv (state), 0);
828 hv_store (hv, "x", 1, newSViv (x), 0); 1004 hv_store (hv, "x", 1, newSViv (x), 0);
829 hv_store (hv, "y", 1, newSViv (y), 0); 1005 hv_store (hv, "y", 1, newSViv (y), 0);
830 hv_store (hv, "xrel", 4, newSViv (xrel), 0); 1006 hv_store (hv, "xrel", 4, newSViv (xrel), 0);
831 hv_store (hv, "yrel", 4, newSViv (yrel), 0); 1007 hv_store (hv, "yrel", 4, newSViv (yrel), 0);
850 } 1026 }
851 1027
852 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("DC::UI::Event", 1)))); 1028 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("DC::UI::Event", 1))));
853 } 1029 }
854} 1030}
1031
1032char *
1033SDL_AudioDriverName ()
1034 CODE:
1035{
1036 char buf [256];
1037 if (!SDL_AudioDriverName (buf, sizeof (buf)))
1038 XSRETURN_UNDEF;
1039
1040 RETVAL = buf;
1041}
1042 OUTPUT:
1043 RETVAL
855 1044
856int 1045int
857Mix_OpenAudio (int frequency = 44100, int format = MIX_DEFAULT_FORMAT, int channels = 2, int chunksize = 4096) 1046Mix_OpenAudio (int frequency = 44100, int format = MIX_DEFAULT_FORMAT, int channels = 2, int chunksize = 4096)
858 POSTCALL: 1047 POSTCALL:
859 Mix_HookMusicFinished (music_finished); 1048 Mix_HookMusicFinished (music_finished);
1047#if DEBUG 1236#if DEBUG
1048 VALGRIND_DO_LEAK_CHECK; 1237 VALGRIND_DO_LEAK_CHECK;
1049#endif 1238#endif
1050} 1239}
1051 1240
1241int
1242SvREFCNT (SV *sv)
1243 CODE:
1244 RETVAL = SvREFCNT (sv);
1245 OUTPUT:
1246 RETVAL
1247
1052MODULE = Deliantra::Client PACKAGE = DC::Font 1248MODULE = Deliantra::Client PACKAGE = DC::Font
1053 1249
1054PROTOTYPES: DISABLE 1250PROTOTYPES: DISABLE
1055 1251
1056DC::Font 1252DC::Font
1485 if (ix) 1681 if (ix)
1486 { 1682 {
1487 glDisable (GL_ALPHA_TEST); 1683 glDisable (GL_ALPHA_TEST);
1488 glDisable (GL_BLEND); 1684 glDisable (GL_BLEND);
1489 } 1685 }
1686}
1687
1688void
1689draw_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)
1690 PROTOTYPE: @
1691 CODE:
1692{
1693 glEnable (GL_BLEND);
1694 glBlendFunc (intensity ? GL_SRC_ALPHA : GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1695 glEnable (GL_TEXTURE_2D);
1696 glBindTexture (GL_TEXTURE_2D, name1);
1697
1698 glColor3f (intensity, intensity, intensity);
1699 glPushMatrix ();
1700 glScalef (1./3, 1./3, 1.);
1701
1702 if (blend > 0.f)
1703 {
1704 float dx3 = dx * -3.f / w;
1705 float dy3 = dy * -3.f / h;
1706 GLfloat env_color[4] = { 0., 0., 0., blend };
1707
1708 /* interpolate the two shadow textures */
1709 /* stage 0 == rgb(glcolor) + alpha(t0) */
1710 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1711
1712 /* stage 1 == rgb(glcolor) + alpha(interpolate t0, t1, texenv) */
1713 gl.ActiveTexture (GL_TEXTURE1);
1714 glEnable (GL_TEXTURE_2D);
1715 glBindTexture (GL_TEXTURE_2D, name2);
1716 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
1717
1718 /* rgb == rgb(glcolor) */
1719 glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
1720 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
1721 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
1722
1723 /* alpha = interpolate t0, t1 by env_alpha */
1724 glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, env_color);
1725
1726 glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_INTERPOLATE);
1727 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
1728 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
1729
1730 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS);
1731 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
1732
1733 glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_CONSTANT);
1734 glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA);
1735
1736 glBegin (GL_QUADS);
1737 gl.MultiTexCoord2f (GL_TEXTURE0, 0, 0); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 , dy3 ); glVertex2i (0, 0);
1738 gl.MultiTexCoord2f (GL_TEXTURE0, 0, t); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 , dy3 + t); glVertex2i (0, h);
1739 gl.MultiTexCoord2f (GL_TEXTURE0, s, t); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 + s, dy3 + t); glVertex2i (w, h);
1740 gl.MultiTexCoord2f (GL_TEXTURE0, s, 0); gl.MultiTexCoord2f (GL_TEXTURE1, dx3 + s, dy3 ); glVertex2i (w, 0);
1741 glEnd ();
1742
1743 glDisable (GL_TEXTURE_2D);
1744 gl.ActiveTexture (GL_TEXTURE0);
1745 }
1746 else
1747 {
1748 /* simple blending of one texture, also opengl <1.3 path */
1749 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1750
1751 glBegin (GL_QUADS);
1752 glTexCoord2f (0, 0); glVertex2f (0, 0);
1753 glTexCoord2f (0, t); glVertex2f (0, h);
1754 glTexCoord2f (s, t); glVertex2f (w, h);
1755 glTexCoord2f (s, 0); glVertex2f (w, 0);
1756 glEnd ();
1757 }
1758
1759 /* draw ?-marks or equivalent, this is very clumsy code :/ */
1760 {
1761 int x, y;
1762 int dx3 = dx * 3;
1763 int dy3 = dy * 3;
1764
1765 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1766 glBindTexture (GL_TEXTURE_2D, hidden_tex);
1767 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1768 glTranslatef (-1., -1., 0);
1769 glBegin (GL_QUADS);
1770
1771 for (y = 1; y < h; y += 3)
1772 {
1773 int y1 = y - dy3;
1774 int y1valid = y1 >= 0 && y1 < h;
1775
1776 for (x = 1; x < w; x += 3)
1777 {
1778 int x1 = x - dx3;
1779 uint8_t h1 = data1 [x + y * w] == DARKNESS_ADJUST (255 - FOW_DARKNESS);
1780 uint8_t h2;
1781
1782 if (y1valid && x1 >= 0 && x1 < w)
1783 h2 = data2 [x1 + y1 * w] == DARKNESS_ADJUST (255 - FOW_DARKNESS);
1784 else
1785 h2 = 1; /* out of range == invisible */
1786
1787 if (h1 || h2)
1788 {
1789 float alpha = h1 == h2 ? 1.f : h1 ? 1.f - blend : blend;
1790 glColor4f (1., 1., 1., alpha);
1791
1792 glTexCoord2f (0, 0.); glVertex2i (x , y );
1793 glTexCoord2f (0, 1.); glVertex2i (x , y + 3);
1794 glTexCoord2f (1, 1.); glVertex2i (x + 3, y + 3);
1795 glTexCoord2f (1, 0.); glVertex2i (x + 3, y );
1796 }
1797 }
1798 }
1799 }
1800
1801 glEnd ();
1802
1803 glPopMatrix ();
1804
1805 glDisable (GL_TEXTURE_2D);
1806 glDisable (GL_BLEND);
1490} 1807}
1491 1808
1492IV texture_valid_2d (GLint internalformat, GLsizei w, GLsizei h, GLenum format, GLenum type) 1809IV texture_valid_2d (GLint internalformat, GLsizei w, GLsizei h, GLenum format, GLenum type)
1493 CODE: 1810 CODE:
1494{ 1811{
1600 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 1917 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1601 // use uglier nearest interpolation because linear suffers 1918 // use uglier nearest interpolation because linear suffers
1602 // from transparent color bleeding and ugly wrapping effects. 1919 // from transparent color bleeding and ugly wrapping effects.
1603 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1920 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1604} 1921}
1922
1923void
1924expire_textures (DC::Map self, int texid, int count)
1925 PPCODE:
1926 for (; texid < self->texs && count; ++texid, --count)
1927 {
1928 maptex *tex = self->tex + texid;
1929
1930 if (tex->name)
1931 {
1932 if (tex->unused)
1933 {
1934 tex->name = 0;
1935 tex->unused = 0;
1936 XPUSHs (sv_2mortal (newSViv (texid)));
1937 }
1938 else
1939 tex->unused = 1;
1940 }
1941 }
1605 1942
1606int 1943int
1607ox (DC::Map self) 1944ox (DC::Map self)
1608 ALIAS: 1945 ALIAS:
1609 oy = 1 1946 oy = 1
1687 uint8_t ext, cmd; 2024 uint8_t ext, cmd;
1688 2025
1689 do 2026 do
1690 { 2027 {
1691 ext = *data++; 2028 ext = *data++;
1692 cmd = ext & 0x3f; 2029 cmd = ext & 0x7f;
1693 2030
1694 if (cmd < 4) 2031 if (cmd < 4)
1695 cell->darkness = 255 - ext * 64 + 1; 2032 cell->darkness = 255 - ext * 64 + 1; /* make sure this doesn't collide with FOW_DARKNESS */
1696 else if (cmd == 5) // health 2033 else if (cmd == 5) // health
1697 { 2034 {
1698 cell->stat_width = 1; 2035 cell->stat_width = 1;
1699 cell->stat_hp = *data++; 2036 cell->stat_hp = *data++;
1700 } 2037 }
1701 else if (cmd == 6) // monster width 2038 else if (cmd == 6) // monster width
1702 cell->stat_width = *data++ + 1; 2039 cell->stat_width = *data++ + 1;
1703 else if (cmd == 0x47) 2040 else if (cmd == 0x47)
1704 { 2041 {
1705 if (*data == 4) 2042 if (*data == 1) cell->player = data [1];
1706 ; // decode player count 2043 else if (*data == 2) cell->player = data [2] + (data [1] << 8);
2044 else if (*data == 3) cell->player = data [3] + (data [2] << 8) + (data [1] << 16);
2045 else if (*data == 4) cell->player = data [4] + (data [3] << 8) + (data [2] << 16) + (data [1] << 24);
1707 2046
1708 data += *data + 1; 2047 data += *data + 1;
1709 } 2048 }
1710 else if (cmd == 8) // cell flags 2049 else if (cmd == 8) // cell flags
1711 cell->flags = *data++; 2050 cell->flags = *data++;
1728 cell->tile [z] = self->face2tile [face]; 2067 cell->tile [z] = self->face2tile [face];
1729 2068
1730 if (cell->tile [z]) 2069 if (cell->tile [z])
1731 { 2070 {
1732 maptex *tex = self->tex + cell->tile [z]; 2071 maptex *tex = self->tex + cell->tile [z];
2072 tex->unused = 0;
1733 if (!tex->name) 2073 if (!tex->name)
1734 av_push (missing, newSViv (cell->tile [z])); 2074 av_push (missing, newSViv (cell->tile [z]));
1735 2075
1736 if (tex->smoothtile) 2076 if (tex->smoothtile)
1737 { 2077 {
1738 maptex *smooth = self->tex + tex->smoothtile; 2078 maptex *smooth = self->tex + tex->smoothtile;
2079 smooth->unused = 0;
1739 if (!smooth->name) 2080 if (!smooth->name)
1740 av_push (missing, newSViv (tex->smoothtile)); 2081 av_push (missing, newSViv (tex->smoothtile));
1741 } 2082 }
1742 } 2083 }
1743 } 2084 }
1744 } 2085 }
1745 else 2086 else
1746 cell->darkness = 0; 2087 CELL_CLEAR (cell);
1747 } 2088 }
1748} 2089}
1749 OUTPUT: 2090 OUTPUT:
1750 RETVAL 2091 RETVAL
1751 2092
1803} 2144}
1804 OUTPUT: 2145 OUTPUT:
1805 RETVAL 2146 RETVAL
1806 2147
1807void 2148void
1808draw (DC::Map self, int mx, int my, int sw, int sh, int T) 2149draw (DC::Map self, int mx, int my, int sw, int sh, int T, U32 player = 0xffffffff, int sdx = 0, int sdy = 0)
1809 CODE: 2150 CODE:
1810{ 2151{
1811 int x, y, z; 2152 int x, y, z;
1812 2153
1813 HV *smooth = (HV *)sv_2mortal ((SV *)newHV ()); 2154 HV *smooth = (HV *)sv_2mortal ((SV *)newHV ());
1814 uint32_t smooth_level[256 / 32]; // one bit for every possible smooth level 2155 uint32_t smooth_level[256 / 32]; // one bit for every possible smooth level
1815 static uint8_t smooth_max[256][256]; // egad, fast and wasteful on memory (64k) 2156 static uint8_t smooth_max[256][256]; // egad, fast and wasteful on memory (64k)
1816 smooth_key skey; 2157 smooth_key skey;
1817 2158 int pl_x, pl_y;
2159 maptex pl_tex;
1818 rc_t *rc = rc_alloc (); 2160 rc_t *rc = rc_alloc ();
2161 rc_t *rc_ov = rc_alloc ();
1819 rc_key_t key; 2162 rc_key_t key;
1820 rc_array_t *arr; 2163 rc_array_t *arr;
1821 2164
2165 pl_tex.name = 0;
2166
1822 // thats current max. sorry. 2167 // that's current max. sorry.
1823 if (sw > 255) sw = 255; 2168 if (sw > 255) sw = 255;
1824 if (sh > 255) sh = 255; 2169 if (sh > 255) sh = 255;
1825 2170
1826 // clear key, in case of extra padding 2171 // clear key, in case of extra padding
1827 memset (&skey, 0, sizeof (skey)); 2172 memset (&skey, 0, sizeof (skey));
1831 key.g = 255; 2176 key.g = 255;
1832 key.b = 255; 2177 key.b = 255;
1833 key.a = 255; 2178 key.a = 255;
1834 key.mode = GL_QUADS; 2179 key.mode = GL_QUADS;
1835 key.format = GL_T2F_V3F; 2180 key.format = GL_T2F_V3F;
1836 key.texname = -1;
1837 2181
1838 mx += self->x; 2182 mx += self->x;
1839 my += self->y; 2183 my += self->y;
1840 2184
1841 // first pass: determine smooth_max 2185 // first pass: determine smooth_max
1865 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 2209 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1866 2210
1867 for (z = 0; z <= 2; z++) 2211 for (z = 0; z <= 2; z++)
1868 { 2212 {
1869 memset (smooth_level, 0, sizeof (smooth_level)); 2213 memset (smooth_level, 0, sizeof (smooth_level));
2214 key.texname = -1;
1870 2215
1871 for (y = 0; y < sh; y++) 2216 for (y = 0; y < sh; y++)
1872 if (0 <= y + my && y + my < self->rows) 2217 if (0 <= y + my && y + my < self->rows)
1873 { 2218 {
1874 maprow *row = self->row + (y + my); 2219 maprow *row = self->row + (y + my);
1884 maptex tex = self->tex [tile]; 2229 maptex tex = self->tex [tile];
1885 int px, py; 2230 int px, py;
1886 2231
1887 if (key.texname != tex.name) 2232 if (key.texname != tex.name)
1888 { 2233 {
2234 self->tex [tile].unused = 0;
2235
1889 if (!tex.name) 2236 if (!tex.name)
1890 tex = self->tex [2]; /* missing, replace by noface */ 2237 tex = self->tex [TEXID_NOFACE]; /* missing, replace by noface */
1891 2238
1892 key.texname = tex.name; 2239 key.texname = tex.name;
1893 arr = rc_array (rc, &key); 2240 arr = rc_array (rc, &key);
1894 } 2241 }
1895 2242
1896 px = (x + 1) * T - tex.w; 2243 px = (x + 1) * T - tex.w;
1897 py = (y + 1) * T - tex.h; 2244 py = (y + 1) * T - tex.h;
2245
2246 if (expect_false (cell->player == player) && expect_false (z == 2))
2247 {
2248 pl_x = px;
2249 pl_y = py;
2250 pl_tex = tex;
2251 continue;
2252 }
1898 2253
1899 rc_t2f_v3f (arr, 0 , 0 , px , py , 0); 2254 rc_t2f_v3f (arr, 0 , 0 , px , py , 0);
1900 rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0); 2255 rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0);
1901 rc_t2f_v3f (arr, tex.s, tex.t, px + tex.w, py + tex.h, 0); 2256 rc_t2f_v3f (arr, tex.s, tex.t, px + tex.w, py + tex.h, 0);
1902 rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0); 2257 rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0);
1903
1904 if (cell->flags && z == 2)
1905 {
1906 // overlays such as the speech bubble, probably more to come
1907 if (cell->flags & 1)
1908 {
1909 maptex tex = self->tex [1];
1910 int px = x * T + T * 2 / 32;
1911 int py = y * T - T * 6 / 32;
1912
1913 if (tex.name)
1914 {
1915 if (key.texname != tex.name)
1916 {
1917 key.texname = tex.name;
1918 arr = rc_array (rc, &key);
1919 }
1920
1921 rc_t2f_v3f (arr, 0 , 0 , px , py , 0);
1922 rc_t2f_v3f (arr, 0 , tex.t, px , py + T, 0);
1923 rc_t2f_v3f (arr, tex.s, tex.t, px + T, py + T, 0);
1924 rc_t2f_v3f (arr, tex.s, 0 , px + T, py , 0);
1925 }
1926 }
1927 }
1928 2258
1929 // update smooth hash 2259 // update smooth hash
1930 if (tex.smoothtile) 2260 if (tex.smoothtile)
1931 { 2261 {
1932 skey.tile = tex.smoothtile; 2262 skey.tile = tex.smoothtile;
1961 // corners 2291 // corners
1962 skey.x = x + 2; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0100); 2292 skey.x = x + 2; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0100);
1963 skey.x = x ; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0200); 2293 skey.x = x ; skey.y = y + 2; smooth_or_bits (smooth, &skey, 0x0200);
1964 skey.x = x ; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0400); 2294 skey.x = x ; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0400);
1965 skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0800); 2295 skey.x = x + 2; skey.y = y ; smooth_or_bits (smooth, &skey, 0x0800);
2296 }
2297 }
2298
2299 if (expect_false (z == 2) && expect_false (cell->flags))
2300 {
2301 // overlays such as the speech bubble, probably more to come
2302 if (cell->flags & 1)
2303 {
2304 rc_key_t key_ov = key;
2305 maptex tex = self->tex [TEXID_SPEECH];
2306 rc_array_t *arr;
2307 int px = x * T + T * 2 / 32;
2308 int py = y * T - T * 6 / 32;
2309
2310 key_ov.texname = tex.name;
2311 arr = rc_array (rc_ov, &key_ov);
2312
2313 rc_t2f_v3f (arr, 0 , 0 , px , py , 0);
2314 rc_t2f_v3f (arr, 0 , tex.t, px , py + T, 0);
2315 rc_t2f_v3f (arr, tex.s, tex.t, px + T, py + T, 0);
2316 rc_t2f_v3f (arr, tex.s, 0 , px + T, py , 0);
1966 } 2317 }
1967 } 2318 }
1968 } 2319 }
1969 } 2320 }
1970 2321
2010 { 2361 {
2011 // this time avoiding texture state changes 2362 // this time avoiding texture state changes
2012 // save gobs of state changes. 2363 // save gobs of state changes.
2013 if (key.texname != tex.name) 2364 if (key.texname != tex.name)
2014 { 2365 {
2366 self->tex [skey->tile].unused = 0;
2367
2015 glEnd (); 2368 glEnd ();
2016 glBindTexture (GL_TEXTURE_2D, key.texname = tex.name); 2369 glBindTexture (GL_TEXTURE_2D, key.texname = tex.name);
2017 glBegin (GL_QUADS); 2370 glBegin (GL_QUADS);
2018 } 2371 }
2019 2372
2048 } 2401 }
2049 2402
2050 hv_clear (smooth); 2403 hv_clear (smooth);
2051 } 2404 }
2052 2405
2406 if (pl_tex.name)
2407 {
2408 maptex tex = pl_tex;
2409 int px = pl_x + sdx;
2410 int py = pl_y + sdy;
2411
2412 key.texname = tex.name;
2413 arr = rc_array (rc, &key);
2414
2415 rc_t2f_v3f (arr, 0 , 0 , px , py , 0);
2416 rc_t2f_v3f (arr, 0 , tex.t, px , py + tex.h, 0);
2417 rc_t2f_v3f (arr, tex.s, tex.t, px + tex.w, py + tex.h, 0);
2418 rc_t2f_v3f (arr, tex.s, 0 , px + tex.w, py , 0);
2419
2420 rc_draw (rc);
2421 }
2422
2423 rc_draw (rc_ov);
2424 rc_clear (rc_ov);
2425
2053 glDisable (GL_BLEND); 2426 glDisable (GL_BLEND);
2054 rc_free (rc); 2427 rc_free (rc);
2428 rc_free (rc_ov);
2055 2429
2056 // top layer: overlays such as the health bar 2430 // top layer: overlays such as the health bar
2057 for (y = 0; y < sh; y++) 2431 for (y = 0; y < sh; y++)
2058 if (0 <= y + my && y + my < self->rows) 2432 if (0 <= y + my && y + my < self->rows)
2059 { 2433 {
2064 { 2438 {
2065 mapcell *cell = row->col + (x + mx - row->c0); 2439 mapcell *cell = row->col + (x + mx - row->c0);
2066 2440
2067 int px = x * T; 2441 int px = x * T;
2068 int py = y * T; 2442 int py = y * T;
2443
2444 if (expect_false (cell->player == player))
2445 {
2446 px += sdx;
2447 py += sdy;
2448 }
2069 2449
2070 if (cell->stat_hp) 2450 if (cell->stat_hp)
2071 { 2451 {
2072 int width = cell->stat_width * T; 2452 int width = cell->stat_width * T;
2073 int thick = (sh * T / 32 + 27) / 28 + 1 + cell->stat_width; 2453 int thick = (sh * T / 32 + 27) / 28 + 1 + cell->stat_width;
2084 } 2464 }
2085 } 2465 }
2086} 2466}
2087 2467
2088void 2468void
2089draw_magicmap (DC::Map self, int dx, int dy, int w, int h, unsigned char *data) 2469draw_magicmap (DC::Map self, int w, int h, unsigned char *data)
2090 CODE: 2470 CODE:
2091{ 2471{
2092 static float color[16][3] = { 2472 static float color[16][3] = {
2093 { 0.00F, 0.00F, 0.00F }, 2473 { 0.00f, 0.00f, 0.00f },
2094 { 1.00F, 1.00F, 1.00F }, 2474 { 1.00f, 1.00f, 1.00f },
2095 { 0.00F, 0.00F, 0.55F }, 2475 { 0.00f, 0.00f, 0.55f },
2096 { 1.00F, 0.00F, 0.00F }, 2476 { 1.00f, 0.00f, 0.00f },
2097 2477
2098 { 1.00F, 0.54F, 0.00F }, 2478 { 1.00f, 0.54f, 0.00f },
2099 { 0.11F, 0.56F, 1.00F }, 2479 { 0.11f, 0.56f, 1.00f },
2100 { 0.93F, 0.46F, 0.00F }, 2480 { 0.93f, 0.46f, 0.00f },
2101 { 0.18F, 0.54F, 0.34F }, 2481 { 0.18f, 0.54f, 0.34f },
2102 2482
2103 { 0.56F, 0.73F, 0.56F }, 2483 { 0.56f, 0.73f, 0.56f },
2104 { 0.80F, 0.80F, 0.80F }, 2484 { 0.80f, 0.80f, 0.80f },
2105 { 0.55F, 0.41F, 0.13F }, 2485 { 0.55f, 0.41f, 0.13f },
2106 { 0.99F, 0.77F, 0.26F }, 2486 { 0.99f, 0.77f, 0.26f },
2107 2487
2108 { 0.74F, 0.65F, 0.41F }, 2488 { 0.74f, 0.65f, 0.41f },
2109 2489
2110 { 0.00F, 1.00F, 1.00F }, 2490 { 0.00f, 1.00f, 1.00f },
2111 { 1.00F, 0.00F, 1.00F }, 2491 { 1.00f, 0.00f, 1.00f },
2112 { 1.00F, 1.00F, 0.00F }, 2492 { 1.00f, 1.00f, 0.00f },
2113 }; 2493 };
2114 2494
2115 int x, y; 2495 int x, y;
2116 2496
2117 glEnable (GL_TEXTURE_2D); 2497 glEnable (GL_TEXTURE_2D);
2498 /* GL_REPLACE would be correct, as we don't need to modulate alpha,
2499 * but the nvidia driver (185.18.14) mishandles alpha textures
2500 * and takes the colour from god knows where instead of using
2501 * Cp. MODULATE results in the same colour, but slightly different
2502 * alpha, but atcually gives us the correct colour with nvidia.
2503 */
2118 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 2504 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2119 glEnable (GL_BLEND); 2505 glEnable (GL_BLEND);
2120 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2506 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2121 glBegin (GL_QUADS); 2507 glBegin (GL_QUADS);
2122 2508
2123 for (y = 0; y < h; y++) 2509 for (y = 0; y < h; y++)
2127 2513
2128 if (m) 2514 if (m)
2129 { 2515 {
2130 float *c = color [m & 15]; 2516 float *c = color [m & 15];
2131 2517
2132 float tx1 = m & 0x40 ? 0.5 : 0.; 2518 float tx1 = m & 0x40 ? 0.5f : 0.f;
2133 float tx2 = tx1 + 0.5; 2519 float tx2 = tx1 + 0.5f;
2134 2520
2135 glColor4f (c[0], c[1], c[2], 0.75); 2521 glColor4f (c[0], c[1], c[2], 1);
2136 glTexCoord2f (tx1, 0.); glVertex2i (x , y ); 2522 glTexCoord2f (tx1, 0.); glVertex2i (x , y );
2137 glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1); 2523 glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
2138 glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1); 2524 glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
2139 glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y ); 2525 glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
2140 } 2526 }
2148void 2534void
2149fow_texture (DC::Map self, int mx, int my, int sw, int sh) 2535fow_texture (DC::Map self, int mx, int my, int sw, int sh)
2150 PPCODE: 2536 PPCODE:
2151{ 2537{
2152 int x, y; 2538 int x, y;
2153 int sw1 = sw + 2; 2539 int sw1 = sw + 2;
2154 int sh1 = sh + 2; 2540 int sh1 = sh + 2;
2155 int sh3 = sh * 3; 2541 int sh3 = sh * 3;
2156 int sw34 = (sw * 3 + 3) & ~3; 2542 int sw3 = sw * 3;
2157 uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1); 2543 uint8_t *darkness1 = (uint8_t *)malloc (sw1 * sh1);
2158 SV *darkness3_sv = sv_2mortal (newSV (sw34 * sh3)); 2544 SV *darkness3_sv = sv_2mortal (newSV (sw3 * sh3));
2159 uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv); 2545 uint8_t *darkness3 = (uint8_t *)SvPVX (darkness3_sv);
2160 2546
2161 SvPOK_only (darkness3_sv); 2547 SvPOK_only (darkness3_sv);
2162 SvCUR_set (darkness3_sv, sw34 * sh3); 2548 SvCUR_set (darkness3_sv, sw3 * sh3);
2163 2549
2164 mx += self->x - 1; 2550 mx += self->x - 1;
2165 my += self->y - 1; 2551 my += self->y - 1;
2166
2167 memset (darkness1, 255, sw1 * sh1);
2168 2552
2169 for (y = 0; y < sh1; y++) 2553 for (y = 0; y < sh1; y++)
2170 if (0 <= y + my && y + my < self->rows) 2554 if (0 <= y + my && y + my < self->rows)
2171 { 2555 {
2172 maprow *row = self->row + (y + my); 2556 maprow *row = self->row + (y + my);
2175 if (row->c0 <= x + mx && x + mx < row->c1) 2559 if (row->c0 <= x + mx && x + mx < row->c1)
2176 { 2560 {
2177 mapcell *cell = row->col + (x + mx - row->c0); 2561 mapcell *cell = row->col + (x + mx - row->c0);
2178 2562
2179 darkness1 [y * sw1 + x] = cell->darkness 2563 darkness1 [y * sw1 + x] = cell->darkness
2180 ? 255 - (cell->darkness - 1) 2564 ? DARKNESS_ADJUST (255 - (cell->darkness - 1))
2181 : 255 - FOW_DARKNESS; 2565 : DARKNESS_ADJUST (255 - FOW_DARKNESS);
2182 } 2566 }
2183 } 2567 }
2184 2568
2185 for (y = 0; y < sh; ++y) 2569 for (y = 0; y < sh; ++y)
2186 for (x = 0; x < sw; ++x) 2570 for (x = 0; x < sw; ++x)
2205 2589
2206 uint8_t r13 = (d13 + d23 + d12) / 3; 2590 uint8_t r13 = (d13 + d23 + d12) / 3;
2207 uint8_t r23 = d23; 2591 uint8_t r23 = d23;
2208 uint8_t r33 = (d23 + d33 + d32) / 3; 2592 uint8_t r33 = (d23 + d33 + d32) / 3;
2209 2593
2210 darkness3 [(y * 3 ) * sw34 + (x * 3 )] = MAX (d22, r11); 2594 darkness3 [(y * 3 ) * sw3 + (x * 3 )] = MAX (d22, r11);
2211 darkness3 [(y * 3 ) * sw34 + (x * 3 + 1)] = MAX (d22, r21); 2595 darkness3 [(y * 3 ) * sw3 + (x * 3 + 1)] = MAX (d22, r21);
2212 darkness3 [(y * 3 ) * sw34 + (x * 3 + 2)] = MAX (d22, r31); 2596 darkness3 [(y * 3 ) * sw3 + (x * 3 + 2)] = MAX (d22, r31);
2213 darkness3 [(y * 3 + 1) * sw34 + (x * 3 )] = MAX (d22, r12); 2597 darkness3 [(y * 3 + 1) * sw3 + (x * 3 )] = MAX (d22, r12);
2214 darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 1)] = MAX (d22, r22); 2598 darkness3 [(y * 3 + 1) * sw3 + (x * 3 + 1)] = MAX (d22, r22); /* this MUST be == d22 */
2215 darkness3 [(y * 3 + 1) * sw34 + (x * 3 + 2)] = MAX (d22, r32); 2599 darkness3 [(y * 3 + 1) * sw3 + (x * 3 + 2)] = MAX (d22, r32);
2216 darkness3 [(y * 3 + 2) * sw34 + (x * 3 )] = MAX (d22, r13); 2600 darkness3 [(y * 3 + 2) * sw3 + (x * 3 )] = MAX (d22, r13);
2217 darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 1)] = MAX (d22, r23); 2601 darkness3 [(y * 3 + 2) * sw3 + (x * 3 + 1)] = MAX (d22, r23);
2218 darkness3 [(y * 3 + 2) * sw34 + (x * 3 + 2)] = MAX (d22, r33); 2602 darkness3 [(y * 3 + 2) * sw3 + (x * 3 + 2)] = MAX (d22, r33);
2219 } 2603 }
2220 2604
2221 free (darkness1); 2605 free (darkness1);
2222 2606
2223 EXTEND (SP, 3); 2607 EXTEND (SP, 3);
2224 PUSHs (sv_2mortal (newSViv (sw34))); 2608 PUSHs (sv_2mortal (newSViv (sw3)));
2225 PUSHs (sv_2mortal (newSViv (sh3))); 2609 PUSHs (sv_2mortal (newSViv (sh3)));
2226 PUSHs (darkness3_sv); 2610 PUSHs (darkness3_sv);
2227} 2611}
2228 2612
2229SV * 2613SV *
2292 else 2676 else
2293 *data++ = 0; 2677 *data++ = 0;
2294 } 2678 }
2295 } 2679 }
2296 2680
2681 /* if size is w*h + 5 then no data has been found */
2297 if (data - (uint8_t *)SvPVX (data_sv) == w * h + 5) 2682 if (data - (uint8_t *)SvPVX (data_sv) != w * h + 5)
2298 {
2299 SvREFCNT_dec (data_sv);
2300 RETVAL = &PL_sv_undef;
2301 }
2302 else
2303 { 2683 {
2304 SvPOK_only (data_sv); 2684 SvPOK_only (data_sv);
2305 SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv)); 2685 SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
2306 RETVAL = data_sv;
2307 } 2686 }
2687
2688 RETVAL = data_sv;
2308} 2689}
2309 OUTPUT: 2690 OUTPUT:
2310 RETVAL 2691 RETVAL
2311 2692
2312void 2693void
2318 int x1, y1; 2699 int x1, y1;
2319 STRLEN len; 2700 STRLEN len;
2320 uint8_t *data, *end; 2701 uint8_t *data, *end;
2321 2702
2322 len = SvLEN (data_sv); 2703 len = SvLEN (data_sv);
2323 SvGROW (data_sv, len + 7); // reserve at least 7+ bytes more 2704 SvGROW (data_sv, len + 8); // reserve at least 7+ bytes more
2324 data = SvPVbyte_nolen (data_sv); 2705 data = SvPVbyte_nolen (data_sv);
2325 end = data + len + 7; 2706 end = data + len + 8;
2326 2707
2327 if (len < 5) 2708 if (len < 5)
2328 XSRETURN_EMPTY; 2709 XSRETURN_EMPTY;
2329 2710
2330 if (*data++ != 0) 2711 if (*data++ != 0)
2366 if (flags & 2) { tile[1] = *data++ << 8; tile[1] |= *data++; } 2747 if (flags & 2) { tile[1] = *data++ << 8; tile[1] |= *data++; }
2367 if (flags & 4) { tile[2] = *data++ << 8; tile[2] |= *data++; } 2748 if (flags & 4) { tile[2] = *data++ << 8; tile[2] |= *data++; }
2368 2749
2369 if (cell->darkness == 0) 2750 if (cell->darkness == 0)
2370 { 2751 {
2371 cell->darkness = 0; 2752 /*cell->darkness = 0;*/
2753 EXTEND (SP, 3);
2372 2754
2373 for (z = 0; z <= 2; z++) 2755 for (z = 0; z <= 2; z++)
2374 { 2756 {
2375 tileid t = tile [z]; 2757 tileid t = tile [z];
2376 2758
2377 if (t >= self->texs || (t && !self->tex [t].name)) 2759 if (t >= self->texs || (t && !self->tex [t].name))
2378 { 2760 {
2379 XPUSHs (sv_2mortal (newSViv (t))); 2761 PUSHs (sv_2mortal (newSViv (t)));
2380 need_texid (self, t); 2762 need_texid (self, t);
2381 } 2763 }
2382 2764
2383 cell->tile [z] = t; 2765 cell->tile [z] = t;
2384 } 2766 }
2429 if (RETVAL < 0) 2811 if (RETVAL < 0)
2430 { 2812 {
2431 RETVAL = Mix_GroupOldest (-1); 2813 RETVAL = Mix_GroupOldest (-1);
2432 2814
2433 if (RETVAL < 0) 2815 if (RETVAL < 0)
2816 {
2817 // happens sometimes, maybe it just stopped playing(?)
2818 RETVAL = Mix_GroupAvailable (-1);
2819
2820 if (RETVAL < 0)
2434 XSRETURN_UNDEF; 2821 XSRETURN_UNDEF;
2435 2822 }
2823 else
2436 Mix_HaltChannel (RETVAL); 2824 Mix_HaltChannel (RETVAL);
2437 } 2825 }
2438 2826
2439 Mix_UnregisterAllEffects (RETVAL); 2827 Mix_UnregisterAllEffects (RETVAL);
2440 Mix_Volume (RETVAL, 128); 2828 Mix_Volume (RETVAL, 128);
2441} 2829}
2488void 2876void
2489set_position_r (DC::Channel self, int dx, int dy, int maxdistance) 2877set_position_r (DC::Channel self, int dx, int dy, int maxdistance)
2490 CODE: 2878 CODE:
2491{ 2879{
2492 int distance = sqrtf (dx * dx + dy * dy) * (255.f / sqrtf (maxdistance * maxdistance)); 2880 int distance = sqrtf (dx * dx + dy * dy) * (255.f / sqrtf (maxdistance * maxdistance));
2493 int angle = 360 + (int)roundf (atan2f (dx, -dy) * 180.f / (float)M_PI); 2881 int angle = atan2f (dx, -dy) * 180.f / (float)M_PI + 360.f;
2494 Mix_SetPosition (self, angle, CLAMP (distance, 0, 255)); 2882 Mix_SetPosition (self, angle, CLAMP (distance, 0, 255));
2495} 2883}
2496 2884
2497void 2885void
2498set_reverse_stereo (DC::Channel self, int flip) 2886set_reverse_stereo (DC::Channel self, int flip)
2500 Mix_SetReverseStereo (self, flip); 2888 Mix_SetReverseStereo (self, flip);
2501 2889
2502MODULE = Deliantra::Client PACKAGE = DC::MixChunk 2890MODULE = Deliantra::Client PACKAGE = DC::MixChunk
2503 2891
2504PROTOTYPES: DISABLE 2892PROTOTYPES: DISABLE
2893
2894void
2895decoders ()
2896 PPCODE:
2897#if SDL_MIXER_MAJOR_VERSION > 1 || SDL_MIXER_MINOR_VERSION > 2 || SDL_MIXER_PATCHLEVEL >= 10
2898 int i, num = Mix_GetNumChunkDecoders ();
2899 EXTEND (SP, num);
2900 for (i = 0; i < num; ++i)
2901 PUSHs (sv_2mortal (newSVpv (Mix_GetChunkDecoder (i), 0)));
2902#else
2903 XPUSHs (sv_2mortal (newSVpv ("(sdl mixer too old)", 0)));
2904#endif
2505 2905
2506DC::MixChunk 2906DC::MixChunk
2507new (SV *class, DC::RW rwops) 2907new (SV *class, DC::RW rwops)
2508 CODE: 2908 CODE:
2509 RETVAL = Mix_LoadWAV_RW (rwops, 1); 2909 RETVAL = Mix_LoadWAV_RW (rwops, 1);
2542 OUTPUT: 2942 OUTPUT:
2543 RETVAL 2943 RETVAL
2544 2944
2545MODULE = Deliantra::Client PACKAGE = DC::MixMusic 2945MODULE = Deliantra::Client PACKAGE = DC::MixMusic
2546 2946
2947void
2948decoders ()
2949 PPCODE:
2950#if SDL_MIXER_MAJOR_VERSION > 1 || SDL_MIXER_MINOR_VERSION > 2 || SDL_MIXER_PATCHLEVEL >= 10
2951 int i, num = Mix_GetNumMusicDecoders ();
2952 EXTEND (SP, num);
2953 for (i = 0; i < num; ++i)
2954 PUSHs (sv_2mortal (newSVpv (Mix_GetMusicDecoder (i), 0)));
2955#else
2956 XPUSHs (sv_2mortal (newSVpv ("(sdl mixer too old)", 0)));
2957#endif
2958
2547int 2959int
2548volume (int volume = -1) 2960volume (int volume = -1)
2549 PROTOTYPE: ;$ 2961 PROTOTYPE: ;$
2550 CODE: 2962 CODE:
2551 if (items > 0) 2963 if (items > 0)
2561 2973
2562void 2974void
2563halt () 2975halt ()
2564 CODE: 2976 CODE:
2565 Mix_HaltMusic (); 2977 Mix_HaltMusic ();
2978
2979int
2980playing ()
2981 CODE:
2982 RETVAL = Mix_PlayingMusic ();
2983 OUTPUT:
2984 RETVAL
2566 2985
2567DC::MixMusic 2986DC::MixMusic
2568new (SV *class, DC::RW rwops) 2987new (SV *class, DC::RW rwops)
2569 CODE: 2988 CODE:
2570 RETVAL = Mix_LoadMUS_RW (rwops); 2989 RETVAL = Mix_LoadMUS_RW (rwops);
2601 } *civ, const_iv[] = { 3020 } *civ, const_iv[] = {
2602# define const_iv(name) { # name, (IV)name } 3021# define const_iv(name) { # name, (IV)name }
2603 const_iv (GL_VENDOR), 3022 const_iv (GL_VENDOR),
2604 const_iv (GL_VERSION), 3023 const_iv (GL_VERSION),
2605 const_iv (GL_EXTENSIONS), 3024 const_iv (GL_EXTENSIONS),
3025 const_iv (GL_MAX_TEXTURE_UNITS),
2606 const_iv (GL_COLOR_MATERIAL), 3026 const_iv (GL_COLOR_MATERIAL),
2607 const_iv (GL_SMOOTH), 3027 const_iv (GL_SMOOTH),
2608 const_iv (GL_FLAT), 3028 const_iv (GL_FLAT),
2609 const_iv (GL_DITHER), 3029 const_iv (GL_DITHER),
2610 const_iv (GL_BLEND), 3030 const_iv (GL_BLEND),
2622 const_iv (GL_ZERO), 3042 const_iv (GL_ZERO),
2623 const_iv (GL_SRC_ALPHA), 3043 const_iv (GL_SRC_ALPHA),
2624 const_iv (GL_DST_ALPHA), 3044 const_iv (GL_DST_ALPHA),
2625 const_iv (GL_ONE_MINUS_SRC_ALPHA), 3045 const_iv (GL_ONE_MINUS_SRC_ALPHA),
2626 const_iv (GL_ONE_MINUS_DST_ALPHA), 3046 const_iv (GL_ONE_MINUS_DST_ALPHA),
3047 const_iv (GL_SRC_COLOR),
3048 const_iv (GL_DST_COLOR),
3049 const_iv (GL_ONE_MINUS_SRC_COLOR),
3050 const_iv (GL_ONE_MINUS_DST_COLOR),
2627 const_iv (GL_SRC_ALPHA_SATURATE), 3051 const_iv (GL_SRC_ALPHA_SATURATE),
2628 const_iv (GL_RGB), 3052 const_iv (GL_RGB),
2629 const_iv (GL_RGBA), 3053 const_iv (GL_RGBA),
2630 const_iv (GL_RGBA4), 3054 const_iv (GL_RGBA4),
2631 const_iv (GL_RGBA8), 3055 const_iv (GL_RGBA8),
2699 const_iv (GL_NICEST), 3123 const_iv (GL_NICEST),
2700 const_iv (GL_V2F), 3124 const_iv (GL_V2F),
2701 const_iv (GL_V3F), 3125 const_iv (GL_V3F),
2702 const_iv (GL_T2F_V3F), 3126 const_iv (GL_T2F_V3F),
2703 const_iv (GL_T2F_N3F_V3F), 3127 const_iv (GL_T2F_N3F_V3F),
3128 const_iv (GL_FUNC_ADD),
3129 const_iv (GL_FUNC_SUBTRACT),
3130 const_iv (GL_FUNC_REVERSE_SUBTRACT),
2704# undef const_iv 3131# undef const_iv
2705 }; 3132 };
2706 3133
2707 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) 3134 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
2708 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 3135 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
2715disable_GL_EXT_blend_func_separate () 3142disable_GL_EXT_blend_func_separate ()
2716 CODE: 3143 CODE:
2717 gl.BlendFuncSeparate = 0; 3144 gl.BlendFuncSeparate = 0;
2718 gl.BlendFuncSeparateEXT = 0; 3145 gl.BlendFuncSeparateEXT = 0;
2719 3146
3147void
3148apple_nvidia_bug (int enable)
3149
2720char * 3150char *
2721gl_vendor () 3151gl_vendor ()
2722 CODE: 3152 CODE:
2723 RETVAL = (char *)glGetString (GL_VENDOR); 3153 RETVAL = (char *)glGetString (GL_VENDOR);
2724 OUTPUT: 3154 OUTPUT:
2772void glBlendFunc (int sfactor, int dfactor) 3202void glBlendFunc (int sfactor, int dfactor)
2773 3203
2774void glBlendFuncSeparate (int sa, int da, int saa, int daa) 3204void glBlendFuncSeparate (int sa, int da, int saa, int daa)
2775 CODE: 3205 CODE:
2776 gl_BlendFuncSeparate (sa, da, saa, daa); 3206 gl_BlendFuncSeparate (sa, da, saa, daa);
3207
3208# void glBlendEquation (int se)
2777 3209
2778void glDepthMask (int flag) 3210void glDepthMask (int flag)
2779 3211
2780void glLogicOp (int opcode) 3212void glLogicOp (int opcode)
2781 3213
2816void glRotate (float angle, float x, float y, float z) 3248void glRotate (float angle, float x, float y, float z)
2817 CODE: 3249 CODE:
2818 glRotatef (angle, x, y, z); 3250 glRotatef (angle, x, y, z);
2819 3251
2820void glColor (float r, float g, float b, float a = 1.0) 3252void glColor (float r, float g, float b, float a = 1.0)
3253 PROTOTYPE: @
2821 ALIAS: 3254 ALIAS:
2822 glColor_premultiply = 1 3255 glColor_premultiply = 1
2823 CODE: 3256 CODE:
2824 if (ix) 3257 if (ix)
2825 { 3258 {
2930void glNewList (int list, int mode = GL_COMPILE) 3363void glNewList (int list, int mode = GL_COMPILE)
2931 3364
2932void glEndList () 3365void glEndList ()
2933 3366
2934void glCallList (int list) 3367void glCallList (int list)
3368
3369void c_init ()
3370 CODE:
3371 glPixelStorei (GL_PACK_ALIGNMENT , 1);
3372 glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
2935 3373
2936MODULE = Deliantra::Client PACKAGE = DC::UI::Base 3374MODULE = Deliantra::Client PACKAGE = DC::UI::Base
2937 3375
2938PROTOTYPES: DISABLE 3376PROTOTYPES: DISABLE
2939 3377

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines