ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.152
Committed: Sat Aug 19 18:18:36 2006 UTC (17 years, 8 months ago) by root
Branch: MAIN
CVS Tags: rel-0_51, rel-0_5
Changes since 1.151: +3 -4 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.48 #ifdef _WIN32
2 root 1.131 # define WIN32_LEAN_AND_MEAN
3 root 1.79 # define _WIN32_WINNT 0x0500 // needed to get win2000 api calls
4 root 1.48 # include <malloc.h>
5 root 1.79 # include <windows.h>
6 root 1.75 # pragma warning(disable:4244)
7 root 1.48 #endif
8    
9 root 1.1 #include "EXTERN.h"
10     #include "perl.h"
11     #include "XSUB.h"
12    
13 root 1.131 #ifdef _WIN32
14     # undef pipe
15     #endif
16    
17 root 1.80 #include <math.h>
18 root 1.5 #include <string.h>
19 root 1.25 #include <stdio.h>
20 root 1.111 #include <stdlib.h>
21 root 1.5
22 root 1.2 #include <SDL.h>
23 root 1.76 #include <SDL_endian.h>
24 root 1.23 #include <SDL_image.h>
25 root 1.52 #include <SDL_mixer.h>
26 root 1.3 #include <SDL_opengl.h>
27 root 1.5
28 root 1.124 #define PANGO_ENABLE_BACKEND
29     #define G_DISABLE_CAST_CHECKS
30    
31 root 1.30 #include <glib/gmacros.h>
32    
33 root 1.5 #include <pango/pango.h>
34    
35 root 1.48 #ifndef _WIN32
36     # include <sys/types.h>
37     # include <sys/socket.h>
38     # include <netinet/in.h>
39     # include <netinet/tcp.h>
40     # include <inttypes.h>
41     #else
42     typedef unsigned char uint8_t;
43     typedef unsigned short uint16_t;
44     typedef unsigned int uint32_t;
45     typedef signed char int8_t;
46     typedef signed short int16_t;
47     typedef signed int int32_t;
48     #endif
49 root 1.28
50 root 1.121 #define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, objetc replacement character */
51    
52 root 1.29 #define FOW_DARKNESS 32
53    
54     #define MAP_EXTEND_X 32
55     #define MAP_EXTEND_Y 512
56    
57 root 1.63 #define MIN_FONT_HEIGHT 10
58 root 1.58
59 root 1.127 #if 0
60 root 1.124 # define PARACHUTE SDL_INIT_NOPARACHUTE
61     #else
62     # define PARACHUTE 0
63     #endif
64    
65 root 1.103 static struct
66     {
67     #define GL_FUNC(ptr,name) ptr name;
68     #include "glfunc.h"
69     #undef GL_FUNC
70     } gl;
71    
72     static void gl_BlendFuncSeparate (GLenum sa, GLenum da, GLenum saa, GLenum daa)
73     {
74     if (gl.BlendFuncSeparate)
75     gl.BlendFuncSeparate (sa, da, saa, daa);
76     else if (gl.BlendFuncSeparateEXT)
77     gl.BlendFuncSeparateEXT (sa, da, saa, daa);
78     else
79     glBlendFunc (sa, da);
80     }
81 root 1.64
82 root 1.124 #include "texcache.c"
83    
84     #include "pango-font.c"
85     #include "pango-fontmap.c"
86     #include "pango-render.c"
87    
88 root 1.133 typedef Mix_Chunk *CFPlus__MixChunk;
89     typedef Mix_Music *CFPlus__MixMusic;
90 root 1.52
91 root 1.133 typedef PangoFontDescription *CFPlus__Font;
92 root 1.2
93 root 1.121 static int
94     shape_attr_p (PangoLayoutRun *run)
95     {
96     GSList *attrs = run->item->analysis.extra_attrs;
97    
98     while (attrs)
99     {
100     PangoAttribute *attr = attrs->data;
101    
102     if (attr->klass->type == PANGO_ATTR_SHAPE)
103     return 1;
104    
105     attrs = attrs->next;
106     }
107    
108     return 0;
109     }
110    
111 root 1.14 typedef struct cf_layout {
112 root 1.124 PangoLayout *pl;
113 root 1.76 float r, g, b, a; // default color for rgba mode
114 root 1.14 int base_height;
115 root 1.133 CFPlus__Font font;
116     } *CFPlus__Layout;
117 root 1.14
118 root 1.133 static CFPlus__Font default_font;
119 root 1.124 static PangoContext *opengl_context;
120     static PangoFontMap *opengl_fontmap;
121 root 1.61
122 root 1.14 static void
123 root 1.19 substitute_func (FcPattern *pattern, gpointer data)
124     {
125 root 1.108 FcPatternAddBool (pattern, FC_HINTING, 1);
126 root 1.110 #ifdef FC_HINT_STYLE
127 root 1.109 FcPatternAddBool (pattern, FC_HINT_STYLE, FC_HINT_FULL);
128 root 1.110 #endif
129 root 1.82 FcPatternAddBool (pattern, FC_AUTOHINT, 0);
130 root 1.19 }
131    
132     static void
133 root 1.133 layout_update_font (CFPlus__Layout self)
134 root 1.17 {
135 root 1.19 /* use a random scale factor to account for unknown descenders, 0.8 works
136     * reasonably well with bitstream vera
137     */
138 root 1.61 PangoFontDescription *font = self->font ? self->font : default_font;
139 root 1.46
140 root 1.61 pango_font_description_set_absolute_size (font,
141     MAX (MIN_FONT_HEIGHT, self->base_height) * (PANGO_SCALE * 8 / 10));
142 root 1.58
143 root 1.61 pango_layout_set_font_description (self->pl, font);
144 root 1.17 }
145    
146     static void
147 root 1.133 layout_get_pixel_size (CFPlus__Layout self, int *w, int *h)
148 root 1.14 {
149 root 1.139 PangoRectangle rect;
150 root 1.14
151 root 1.139 // get_pixel_* wrongly rounds down
152     pango_layout_get_extents (self->pl, 0, &rect);
153 root 1.76
154 root 1.139 rect.width = (rect.width + PANGO_SCALE - 1) / PANGO_SCALE;
155     rect.height = (rect.height + PANGO_SCALE - 1) / PANGO_SCALE;
156    
157     if (!rect.width) rect.width = 1;
158     if (!rect.height) rect.height = 1;
159    
160     *w = rect.width;
161     *h = rect.height;
162 root 1.14 }
163    
164 root 1.42 typedef uint16_t mapface;
165    
166 root 1.28 typedef struct {
167 root 1.30 GLint name;
168     int w, h;
169     float s, t;
170 root 1.39 uint8_t r, g, b, a;
171 root 1.42 } maptex;
172 root 1.30
173     typedef struct {
174 root 1.142 uint16_t darkness;
175 root 1.42 mapface face[3];
176 root 1.147 uint8_t stat_width, stat_hp;
177 root 1.28 } mapcell;
178    
179     typedef struct {
180 root 1.30 int32_t c0, c1;
181 root 1.28 mapcell *col;
182     } maprow;
183    
184     typedef struct map {
185     int x, y, w, h;
186 root 1.42 int ox, oy; /* offset to virtual global coordinate system */
187 root 1.28 int faces;
188 root 1.30 mapface *face;
189 root 1.28
190 root 1.42 int texs;
191     maptex *tex;
192    
193 root 1.48 int32_t rows;
194 root 1.28 maprow *row;
195 root 1.133 } *CFPlus__Map;
196 root 1.28
197 root 1.30 static char *
198     prepend (char *ptr, int sze, int inc)
199     {
200     char *p;
201    
202     New (0, p, sze + inc, char);
203     Zero (p, inc, char);
204     Move (ptr, p + inc, sze, char);
205     Safefree (ptr);
206    
207     return p;
208     }
209    
210     static char *
211     append (char *ptr, int sze, int inc)
212     {
213     Renew (ptr, sze + inc, char);
214     Zero (ptr + sze, inc, char);
215    
216     return ptr;
217     }
218    
219     #define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
220     #define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
221    
222 root 1.42 static maprow *
223 root 1.133 map_get_row (CFPlus__Map self, int y)
224 root 1.42 {
225     if (0 > y)
226     {
227     int extend = - y + MAP_EXTEND_Y;
228     Prepend (maprow, self->row, self->rows, extend);
229    
230     self->rows += extend;
231     self->y += extend;
232     y += extend;
233     }
234     else if (y >= self->rows)
235     {
236     int extend = y - self->rows + MAP_EXTEND_Y;
237     Append (maprow, self->row, self->rows, extend);
238     self->rows += extend;
239     }
240    
241     return self->row + y;
242     }
243    
244     static mapcell *
245     row_get_cell (maprow *row, int x)
246     {
247     if (!row->col)
248     {
249     Newz (0, row->col, MAP_EXTEND_X, mapcell);
250     row->c0 = x - MAP_EXTEND_X / 4;
251     row->c1 = row->c0 + MAP_EXTEND_X;
252     }
253    
254     if (row->c0 > x)
255     {
256     int extend = row->c0 - x + MAP_EXTEND_X;
257     Prepend (mapcell, row->col, row->c1 - row->c0, extend);
258     row->c0 -= extend;
259     }
260     else if (x >= row->c1)
261     {
262     int extend = x - row->c1 + MAP_EXTEND_X;
263     Append (mapcell, row->col, row->c1 - row->c0, extend);
264     row->c1 += extend;
265     }
266    
267     return row->col + (x - row->c0);
268     }
269    
270     static mapcell *
271 root 1.133 map_get_cell (CFPlus__Map self, int x, int y)
272 root 1.42 {
273     return row_get_cell (map_get_row (self, y), x);
274     }
275    
276 root 1.30 static void
277 root 1.133 map_clear (CFPlus__Map self)
278 root 1.30 {
279     int r;
280    
281     for (r = 0; r < self->rows; r++)
282     Safefree (self->row[r].col);
283    
284     Safefree (self->row);
285    
286     self->x = 0;
287     self->y = 0;
288 root 1.42 self->ox = 0;
289     self->oy = 0;
290 root 1.30 self->row = 0;
291     self->rows = 0;
292     }
293    
294 root 1.29 static void
295 root 1.133 map_blank (CFPlus__Map self, int x0, int y0, int w, int h)
296 root 1.29 {
297     int x, y;
298 root 1.48 maprow *row;
299 root 1.146 mapcell *cell;
300 root 1.29
301     for (y = y0; y < y0 + h; y++)
302 root 1.30 if (y >= 0)
303     {
304     if (y >= self->rows)
305     break;
306    
307 root 1.48 row = self->row + y;
308 root 1.30
309     for (x = x0; x < x0 + w; x++)
310     if (x >= row->c0)
311     {
312     if (x >= row->c1)
313     break;
314 root 1.29
315 root 1.146 cell = row->col + x - row->c0;
316    
317     cell->darkness = 0;
318     cell->stat_hp = 0;
319 root 1.30 }
320     }
321 root 1.29 }
322    
323 root 1.56 static void
324 root 1.75 music_finished (void)
325 root 1.56 {
326     SDL_UserEvent ev;
327    
328     ev.type = SDL_USEREVENT;
329     ev.code = 0;
330     ev.data1 = 0;
331     ev.data2 = 0;
332    
333 root 1.57 SDL_PushEvent ((SDL_Event *)&ev);
334 root 1.56 }
335    
336 root 1.71 static void
337     channel_finished (int channel)
338     {
339     SDL_UserEvent ev;
340    
341     ev.type = SDL_USEREVENT;
342     ev.code = 1;
343 root 1.74 ev.data1 = (void *)(long)channel;
344 root 1.71 ev.data2 = 0;
345    
346     SDL_PushEvent ((SDL_Event *)&ev);
347     }
348    
349 root 1.113 static unsigned int
350     minpot (unsigned int n)
351     {
352     if (!n)
353     return 0;
354    
355     --n;
356    
357     n |= n >> 1;
358     n |= n >> 2;
359     n |= n >> 4;
360     n |= n >> 8;
361     n |= n >> 16;
362    
363     return n + 1;
364     }
365    
366 root 1.133 MODULE = CFPlus PACKAGE = CFPlus
367 root 1.1
368 root 1.11 PROTOTYPES: ENABLE
369    
370 root 1.5 BOOT:
371     {
372 root 1.133 HV *stash = gv_stashpv ("CFPlus", 1);
373 root 1.51 static const struct {
374     const char *name;
375     IV iv;
376     } *civ, const_iv[] = {
377     # define const_iv(name) { # name, (IV)name }
378     const_iv (SDL_ACTIVEEVENT),
379     const_iv (SDL_KEYDOWN),
380     const_iv (SDL_KEYUP),
381     const_iv (SDL_MOUSEMOTION),
382     const_iv (SDL_MOUSEBUTTONDOWN),
383     const_iv (SDL_MOUSEBUTTONUP),
384     const_iv (SDL_JOYAXISMOTION),
385     const_iv (SDL_JOYBALLMOTION),
386     const_iv (SDL_JOYHATMOTION),
387     const_iv (SDL_JOYBUTTONDOWN),
388     const_iv (SDL_JOYBUTTONUP),
389     const_iv (SDL_QUIT),
390     const_iv (SDL_SYSWMEVENT),
391     const_iv (SDL_EVENT_RESERVEDA),
392     const_iv (SDL_EVENT_RESERVEDB),
393     const_iv (SDL_VIDEORESIZE),
394     const_iv (SDL_VIDEOEXPOSE),
395     const_iv (SDL_USEREVENT),
396     const_iv (SDLK_KP0),
397     const_iv (SDLK_KP1),
398     const_iv (SDLK_KP2),
399     const_iv (SDLK_KP3),
400     const_iv (SDLK_KP4),
401     const_iv (SDLK_KP5),
402     const_iv (SDLK_KP6),
403     const_iv (SDLK_KP7),
404     const_iv (SDLK_KP8),
405     const_iv (SDLK_KP9),
406     const_iv (SDLK_KP_PERIOD),
407     const_iv (SDLK_KP_DIVIDE),
408     const_iv (SDLK_KP_MULTIPLY),
409     const_iv (SDLK_KP_MINUS),
410     const_iv (SDLK_KP_PLUS),
411     const_iv (SDLK_KP_ENTER),
412     const_iv (SDLK_KP_EQUALS),
413     const_iv (SDLK_UP),
414     const_iv (SDLK_DOWN),
415     const_iv (SDLK_RIGHT),
416     const_iv (SDLK_LEFT),
417     const_iv (SDLK_INSERT),
418     const_iv (SDLK_HOME),
419     const_iv (SDLK_END),
420     const_iv (SDLK_PAGEUP),
421     const_iv (SDLK_PAGEDOWN),
422     const_iv (SDLK_F1),
423     const_iv (SDLK_F2),
424     const_iv (SDLK_F3),
425     const_iv (SDLK_F4),
426     const_iv (SDLK_F5),
427     const_iv (SDLK_F6),
428     const_iv (SDLK_F7),
429     const_iv (SDLK_F8),
430     const_iv (SDLK_F9),
431     const_iv (SDLK_F10),
432     const_iv (SDLK_F11),
433     const_iv (SDLK_F12),
434     const_iv (SDLK_F13),
435     const_iv (SDLK_F14),
436     const_iv (SDLK_F15),
437     const_iv (SDLK_NUMLOCK),
438     const_iv (SDLK_CAPSLOCK),
439     const_iv (SDLK_SCROLLOCK),
440     const_iv (SDLK_RSHIFT),
441     const_iv (SDLK_LSHIFT),
442     const_iv (SDLK_RCTRL),
443     const_iv (SDLK_LCTRL),
444     const_iv (SDLK_RALT),
445     const_iv (SDLK_LALT),
446     const_iv (SDLK_RMETA),
447     const_iv (SDLK_LMETA),
448     const_iv (SDLK_LSUPER),
449     const_iv (SDLK_RSUPER),
450     const_iv (SDLK_MODE),
451     const_iv (SDLK_COMPOSE),
452     const_iv (SDLK_HELP),
453     const_iv (SDLK_PRINT),
454     const_iv (SDLK_SYSREQ),
455     const_iv (SDLK_BREAK),
456     const_iv (SDLK_MENU),
457     const_iv (SDLK_POWER),
458     const_iv (SDLK_EURO),
459     const_iv (SDLK_UNDO),
460     const_iv (KMOD_NONE),
461     const_iv (KMOD_LSHIFT),
462     const_iv (KMOD_RSHIFT),
463     const_iv (KMOD_LCTRL),
464     const_iv (KMOD_RCTRL),
465     const_iv (KMOD_LALT),
466     const_iv (KMOD_RALT),
467     const_iv (KMOD_LMETA),
468     const_iv (KMOD_RMETA),
469     const_iv (KMOD_NUM),
470     const_iv (KMOD_CAPS),
471     const_iv (KMOD_MODE),
472     const_iv (KMOD_CTRL),
473     const_iv (KMOD_SHIFT),
474     const_iv (KMOD_ALT),
475     const_iv (KMOD_META)
476     # undef const_iv
477     };
478    
479     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
480     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
481 root 1.79 }
482 root 1.51
483 root 1.129 int
484     in_destruct ()
485     CODE:
486     RETVAL = PL_main_cv == Nullcv;
487     OUTPUT:
488     RETVAL
489    
490 root 1.116 NV floor (NV x)
491    
492     NV ceil (NV x)
493    
494 root 1.79 void
495     pango_init ()
496     CODE:
497     {
498 root 1.124 opengl_fontmap = pango_opengl_font_map_new ();
499     pango_opengl_font_map_set_default_substitute ((PangoOpenGLFontMap *)opengl_fontmap, substitute_func, 0, 0);
500     opengl_context = pango_opengl_font_map_create_context ((PangoOpenGLFontMap *)opengl_fontmap);
501 root 1.5 }
502    
503 root 1.51 int
504 root 1.124 SDL_Init (U32 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | PARACHUTE)
505 root 1.51
506     void
507     SDL_Quit ()
508    
509     void
510     SDL_ListModes ()
511     PPCODE:
512     {
513     SDL_Rect **m;
514    
515     SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
516     SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
517     SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
518 root 1.88 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 1);
519 root 1.51
520 root 1.88 SDL_GL_SetAttribute (SDL_GL_BUFFER_SIZE, 15);
521 root 1.115 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 0);
522 root 1.85
523 root 1.51 SDL_GL_SetAttribute (SDL_GL_ACCUM_RED_SIZE, 0);
524     SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0);
525     SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE, 0);
526     SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0);
527    
528     SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
529 root 1.134 #if SDL_VERSION_ATLEAST(1,2,10)
530 root 1.131 SDL_GL_SetAttribute (SDL_GL_ACCELERATED_VISUAL, 1);
531     SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);
532 root 1.134 #endif
533 root 1.51
534 root 1.53 SDL_EnableUNICODE (1);
535     SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
536    
537 root 1.51 m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL);
538    
539     if (m && m != (SDL_Rect **)-1)
540     while (*m)
541     {
542     AV *av = newAV ();
543     av_push (av, newSViv ((*m)->w));
544     av_push (av, newSViv ((*m)->h));
545     XPUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
546    
547     ++m;
548     }
549     }
550    
551 root 1.88 char *
552     SDL_GetError ()
553    
554 root 1.51 int
555     SDL_SetVideoMode (int w, int h, int fullscreen)
556     CODE:
557     RETVAL = !!SDL_SetVideoMode (
558     w, h, 0, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)
559     );
560 root 1.103 if (RETVAL)
561     {
562     SDL_WM_SetCaption ("Crossfire+ Client " VERSION, "Crossfire+");
563     # define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name);
564     # include "glfunc.h"
565     # undef GL_FUNC
566     }
567 root 1.51 OUTPUT:
568     RETVAL
569    
570 root 1.53 void
571 root 1.54 SDL_GL_SwapBuffers ()
572    
573 root 1.94 char *
574     SDL_GetKeyName (int sym)
575    
576 root 1.54 void
577 root 1.53 SDL_PollEvent ()
578     PPCODE:
579     {
580     SDL_Event ev;
581    
582     while (SDL_PollEvent (&ev))
583     {
584     HV *hv = newHV ();
585     hv_store (hv, "type", 4, newSViv (ev.type), 0);
586 root 1.70
587 root 1.53 switch (ev.type)
588     {
589     case SDL_KEYDOWN:
590     case SDL_KEYUP:
591     hv_store (hv, "state", 5, newSViv (ev.key.state), 0);
592     hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0);
593     hv_store (hv, "mod", 3, newSViv (ev.key.keysym.mod), 0);
594     hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0);
595     break;
596    
597     case SDL_ACTIVEEVENT:
598     hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0);
599     hv_store (hv, "state", 5, newSViv (ev.active.state), 0);
600     break;
601    
602     case SDL_MOUSEMOTION:
603 root 1.94 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0);
604 root 1.93
605 root 1.53 hv_store (hv, "state", 5, newSViv (ev.motion.state), 0);
606     hv_store (hv, "x", 1, newSViv (ev.motion.x), 0);
607     hv_store (hv, "y", 1, newSViv (ev.motion.y), 0);
608     hv_store (hv, "xrel", 4, newSViv (ev.motion.xrel), 0);
609     hv_store (hv, "yrel", 4, newSViv (ev.motion.yrel), 0);
610     break;
611    
612     case SDL_MOUSEBUTTONDOWN:
613     case SDL_MOUSEBUTTONUP:
614 root 1.94 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0);
615 root 1.93
616 root 1.53 hv_store (hv, "button", 6, newSViv (ev.button.button), 0);
617     hv_store (hv, "state", 5, newSViv (ev.button.state), 0);
618     hv_store (hv, "x", 1, newSViv (ev.button.x), 0);
619     hv_store (hv, "y", 1, newSViv (ev.button.y), 0);
620 root 1.70 break;
621 root 1.72
622     case SDL_USEREVENT:
623     hv_store (hv, "code", 4, newSViv (ev.user.code), 0);
624     hv_store (hv, "data1", 5, newSViv ((IV)ev.user.data1), 0);
625     hv_store (hv, "data2", 5, newSViv ((IV)ev.user.data2), 0);
626     break;
627 root 1.53 }
628    
629 root 1.133 XPUSHs (sv_2mortal (sv_bless (newRV_noinc ((SV *)hv), gv_stashpv ("CFPlus::UI::Event", 1))));
630 root 1.53 }
631     }
632 root 1.52
633     int
634 root 1.73 Mix_OpenAudio (int frequency = 48000, int format = MIX_DEFAULT_FORMAT, int channels = 1, int chunksize = 2048)
635 root 1.56 POSTCALL:
636     Mix_HookMusicFinished (music_finished);
637 root 1.71 Mix_ChannelFinished (channel_finished);
638 root 1.52
639     void
640     Mix_CloseAudio ()
641    
642     int
643     Mix_AllocateChannels (int numchans = -1)
644    
645 root 1.10 void
646     lowdelay (int fd, int val = 1)
647     CODE:
648 root 1.48 #ifndef _WIN32
649 root 1.10 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof (val));
650 root 1.48 #endif
651 root 1.10
652 root 1.5 void
653 root 1.13 add_font (char *file)
654     CODE:
655 root 1.129 FcConfigAppFontAddFile (0, (const FcChar8 *)file);
656 root 1.13
657     void
658 root 1.23 load_image_inline (SV *image_)
659     ALIAS:
660     load_image_file = 1
661     PPCODE:
662     {
663     STRLEN image_len;
664     char *image = (char *)SvPVbyte (image_, image_len);
665     SDL_Surface *surface, *surface2;
666     SDL_PixelFormat fmt;
667     SDL_RWops *rw = ix
668     ? SDL_RWFromFile (image, "r")
669     : SDL_RWFromConstMem (image, image_len);
670    
671     if (!rw)
672 root 1.41 croak ("load_image: %s", SDL_GetError ());
673 root 1.23
674     surface = IMG_Load_RW (rw, 1);
675     if (!surface)
676 root 1.41 croak ("load_image: %s", SDL_GetError ());
677 root 1.23
678     fmt.palette = NULL;
679     fmt.BitsPerPixel = 32;
680     fmt.BytesPerPixel = 4;
681 root 1.49 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
682 root 1.23 fmt.Rmask = 0x000000ff;
683     fmt.Gmask = 0x0000ff00;
684     fmt.Bmask = 0x00ff0000;
685     fmt.Amask = 0xff000000;
686 root 1.49 #else
687     fmt.Rmask = 0xff000000;
688     fmt.Gmask = 0x00ff0000;
689     fmt.Bmask = 0x0000ff00;
690     fmt.Amask = 0x000000ff;
691     #endif
692 root 1.23 fmt.Rloss = 0;
693     fmt.Gloss = 0;
694     fmt.Bloss = 0;
695     fmt.Aloss = 0;
696     fmt.Rshift = 0;
697     fmt.Gshift = 8;
698     fmt.Bshift = 16;
699     fmt.Ashift = 24;
700     fmt.colorkey = 0;
701     fmt.alpha = 0;
702    
703     surface2 = SDL_ConvertSurface (surface, &fmt, SDL_SWSURFACE);
704    
705 root 1.39 assert (surface2->pitch == surface2->w * 4);
706    
707 root 1.129 SDL_LockSurface (surface2);
708     EXTEND (SP, 6);
709 root 1.23 PUSHs (sv_2mortal (newSViv (surface2->w)));
710     PUSHs (sv_2mortal (newSViv (surface2->h)));
711     PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch)));
712 root 1.116 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
713 root 1.23 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
714 root 1.49 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
715 root 1.129 SDL_UnlockSurface (surface2);
716 root 1.23
717     SDL_FreeSurface (surface);
718     SDL_FreeSurface (surface2);
719     }
720    
721 root 1.25 void
722 root 1.39 average (int x, int y, uint32_t *data)
723     PPCODE:
724     {
725     uint32_t r = 0, g = 0, b = 0, a = 0;
726    
727     x = y = x * y;
728    
729     while (x--)
730     {
731     uint32_t p = *data++;
732    
733     r += (p ) & 255;
734     g += (p >> 8) & 255;
735     b += (p >> 16) & 255;
736     a += (p >> 24) & 255;
737     }
738    
739     EXTEND (SP, 4);
740 root 1.40 PUSHs (sv_2mortal (newSViv (r / y)));
741     PUSHs (sv_2mortal (newSViv (g / y)));
742     PUSHs (sv_2mortal (newSViv (b / y)));
743     PUSHs (sv_2mortal (newSViv (a / y)));
744 root 1.39 }
745    
746     void
747 root 1.66 error (char *message)
748     CODE:
749 root 1.86 fprintf (stderr, "ERROR: %s\n", message);
750 root 1.66 #ifdef _WIN32
751 root 1.86 MessageBox (0, message, "Crossfire+ Error", MB_OK | MB_ICONERROR);
752 root 1.66 #endif
753    
754     void
755 root 1.25 fatal (char *message)
756     CODE:
757 root 1.86 fprintf (stderr, "FATAL: %s\n", message);
758 root 1.50 #ifdef _WIN32
759 root 1.86 MessageBox (0, message, "Crossfire+ Fatal Error", MB_OK | MB_ICONERROR);
760 root 1.25 #endif
761 root 1.112 _exit (1);
762 root 1.111
763     void
764     _exit (int retval)
765     CODE:
766 root 1.112 _exit (retval);
767 root 1.25
768 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Font
769 root 1.61
770 root 1.133 CFPlus::Font
771 root 1.70 new_from_file (SV *class, char *path, int id = 0)
772 root 1.61 CODE:
773     {
774     int count;
775 root 1.70 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count);
776 root 1.61 RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
777     FcPatternDestroy (pattern);
778     }
779     OUTPUT:
780     RETVAL
781    
782     void
783 root 1.133 DESTROY (CFPlus::Font self)
784 root 1.61 CODE:
785     pango_font_description_free (self);
786    
787     void
788 root 1.133 make_default (CFPlus::Font self)
789 root 1.61 CODE:
790     default_font = self;
791    
792 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Layout
793 root 1.14
794 root 1.124 void
795 root 1.129 reset_glyph_cache ()
796 root 1.124 CODE:
797     tc_clear ();
798    
799 root 1.133 CFPlus::Layout
800 root 1.128 new (SV *class)
801 root 1.14 CODE:
802     New (0, RETVAL, 1, struct cf_layout);
803 root 1.76
804 root 1.124 RETVAL->pl = pango_layout_new (opengl_context);
805 root 1.76 RETVAL->r = 1.;
806     RETVAL->g = 1.;
807     RETVAL->b = 1.;
808     RETVAL->a = 1.;
809     RETVAL->base_height = MIN_FONT_HEIGHT;
810     RETVAL->font = 0;
811    
812 root 1.14 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
813 root 1.76 layout_update_font (RETVAL);
814 root 1.14 OUTPUT:
815     RETVAL
816    
817     void
818 root 1.133 DESTROY (CFPlus::Layout self)
819 root 1.14 CODE:
820     g_object_unref (self->pl);
821     Safefree (self);
822 root 1.13
823 root 1.8 void
824 root 1.133 set_text (CFPlus::Layout self, SV *text_)
825 root 1.35 CODE:
826     {
827     STRLEN textlen;
828     char *text = SvPVutf8 (text_, textlen);
829    
830     pango_layout_set_text (self->pl, text, textlen);
831     }
832    
833     void
834 root 1.133 set_markup (CFPlus::Layout self, SV *text_)
835 root 1.14 CODE:
836 root 1.5 {
837     STRLEN textlen;
838     char *text = SvPVutf8 (text_, textlen);
839 root 1.14
840     pango_layout_set_markup (self->pl, text, textlen);
841     }
842    
843 root 1.121 void
844 root 1.133 set_shapes (CFPlus::Layout self, ...)
845 root 1.121 CODE:
846     {
847     PangoAttrList *attrs = 0;
848     const char *text = pango_layout_get_text (self->pl);
849     const char *pos = text;
850 root 1.122 int arg = 4;
851 root 1.121
852     while (arg < items && (pos = strstr (pos, OBJ_STR)))
853     {
854 root 1.122 PangoRectangle inkrect, rect;
855 root 1.121 PangoAttribute *attr;
856    
857 root 1.122 int x = SvIV (ST (arg - 3));
858     int y = SvIV (ST (arg - 2));
859 root 1.121 int w = SvIV (ST (arg - 1));
860 root 1.122 int h = SvIV (ST (arg ));
861 root 1.121
862 root 1.122 inkrect.x = 0;
863     inkrect.y = 0;
864     inkrect.width = 0;
865     inkrect.height = 0;
866    
867     rect.x = x * PANGO_SCALE;
868     rect.y = y * PANGO_SCALE;
869     rect.width = w * PANGO_SCALE;
870 root 1.121 rect.height = h * PANGO_SCALE;
871    
872     if (!attrs)
873     attrs = pango_layout_get_attributes (self->pl);
874    
875 root 1.122 attr = pango_attr_shape_new (&inkrect, &rect);
876 root 1.121 attr->start_index = pos - text;
877     attr->end_index = attr->start_index + sizeof (OBJ_STR) - 1;
878     pango_attr_list_insert (attrs, attr);
879    
880 root 1.122 arg += 4;
881 root 1.121 pos += sizeof (OBJ_STR) - 1;
882     }
883    
884     if (attrs)
885     pango_layout_set_attributes (self->pl, attrs);
886     }
887    
888     void
889 root 1.133 get_shapes (CFPlus::Layout self)
890 root 1.121 PPCODE:
891     {
892     PangoLayoutIter *iter = pango_layout_get_iter (self->pl);
893    
894     do
895     {
896     PangoLayoutRun *run = pango_layout_iter_get_run (iter);
897    
898     if (run && shape_attr_p (run))
899     {
900     PangoRectangle extents;
901     pango_layout_iter_get_run_extents (iter, 0, &extents);
902    
903 root 1.129 EXTEND (SP, 2);
904 root 1.121 PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.x))));
905     PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.y))));
906     }
907     }
908     while (pango_layout_iter_next_run (iter));
909    
910     pango_layout_iter_free (iter);
911     }
912    
913     int
914 root 1.133 has_wrapped (CFPlus::Layout self)
915 root 1.121 CODE:
916     {
917     int lines = 1;
918     const char *text = pango_layout_get_text (self->pl);
919    
920     while (*text)
921     lines += *text++ == '\n';
922    
923     RETVAL = lines < pango_layout_get_line_count (self->pl);
924     }
925     OUTPUT:
926     RETVAL
927    
928 root 1.46 SV *
929 root 1.133 get_text (CFPlus::Layout self)
930 root 1.46 CODE:
931 root 1.47 RETVAL = newSVpv (pango_layout_get_text (self->pl), 0);
932 root 1.107 sv_utf8_decode (RETVAL);
933 root 1.46 OUTPUT:
934     RETVAL
935    
936 root 1.14 void
937 root 1.133 set_foreground (CFPlus::Layout self, float r, float g, float b, float a = 1.)
938 root 1.76 CODE:
939     self->r = r;
940     self->g = g;
941     self->b = b;
942     self->a = a;
943    
944     void
945 root 1.133 set_font (CFPlus::Layout self, CFPlus::Font font = 0)
946 root 1.61 CODE:
947     if (self->font != font)
948     {
949     self->font = font;
950     layout_update_font (self);
951     }
952    
953     void
954 root 1.133 set_height (CFPlus::Layout self, int base_height)
955 root 1.16 CODE:
956 root 1.61 if (self->base_height != base_height)
957     {
958     self->base_height = base_height;
959     layout_update_font (self);
960     }
961 root 1.16
962     void
963 root 1.133 set_width (CFPlus::Layout self, int max_width = -1)
964 root 1.14 CODE:
965     pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE);
966    
967     void
968 root 1.133 set_indent (CFPlus::Layout self, int indent)
969 root 1.84 CODE:
970     pango_layout_set_indent (self->pl, indent * PANGO_SCALE);
971    
972     void
973 root 1.133 set_spacing (CFPlus::Layout self, int spacing)
974 root 1.84 CODE:
975     pango_layout_set_spacing (self->pl, spacing * PANGO_SCALE);
976    
977     void
978 root 1.133 set_ellipsise (CFPlus::Layout self, int ellipsise)
979 root 1.84 CODE:
980     pango_layout_set_ellipsize (self->pl,
981     ellipsise == 1 ? PANGO_ELLIPSIZE_START
982     : ellipsise == 2 ? PANGO_ELLIPSIZE_MIDDLE
983     : ellipsise == 3 ? PANGO_ELLIPSIZE_END
984     : PANGO_ELLIPSIZE_NONE
985     );
986    
987     void
988 root 1.133 set_single_paragraph_mode (CFPlus::Layout self, int spm)
989 root 1.84 CODE:
990     pango_layout_set_single_paragraph_mode (self->pl, !!spm);
991    
992     void
993 root 1.133 size (CFPlus::Layout self)
994 root 1.14 PPCODE:
995     {
996     int w, h;
997    
998     layout_get_pixel_size (self, &w, &h);
999    
1000     EXTEND (SP, 2);
1001     PUSHs (sv_2mortal (newSViv (w)));
1002     PUSHs (sv_2mortal (newSViv (h)));
1003     }
1004    
1005 root 1.17 int
1006 root 1.133 descent (CFPlus::Layout self)
1007 root 1.122 CODE:
1008     {
1009     PangoRectangle rect;
1010     PangoLayoutLine *line = pango_layout_get_line (self->pl, 0);
1011     pango_layout_line_get_pixel_extents (line, 0, &rect);
1012     RETVAL = PANGO_DESCENT (rect);
1013     }
1014     OUTPUT:
1015     RETVAL
1016    
1017     int
1018 root 1.133 xy_to_index (CFPlus::Layout self, int x, int y)
1019 root 1.17 CODE:
1020     {
1021     int index, trailing;
1022     pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing);
1023     RETVAL = index;
1024     }
1025     OUTPUT:
1026     RETVAL
1027    
1028     void
1029 root 1.133 cursor_pos (CFPlus::Layout self, int index)
1030 root 1.17 PPCODE:
1031     {
1032     PangoRectangle strong_pos;
1033     pango_layout_get_cursor_pos (self->pl, index, &strong_pos, 0);
1034 root 1.30
1035 root 1.17 EXTEND (SP, 3);
1036     PUSHs (sv_2mortal (newSViv (strong_pos.x / PANGO_SCALE)));
1037     PUSHs (sv_2mortal (newSViv (strong_pos.y / PANGO_SCALE)));
1038     PUSHs (sv_2mortal (newSViv (strong_pos.height / PANGO_SCALE)));
1039     }
1040    
1041 root 1.14 void
1042 root 1.135 render (CFPlus::Layout self, float x, float y, int flags = 0)
1043 root 1.14 PPCODE:
1044 root 1.124 pango_opengl_render_layout_subpixel (
1045     self->pl,
1046     x * PANGO_SCALE, y * PANGO_SCALE,
1047 root 1.135 self->r, self->g, self->b, self->a,
1048     flags
1049 root 1.124 );
1050 root 1.11
1051 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Texture
1052 root 1.11
1053     void
1054 root 1.113 pad2pot (SV *data_, SV *w_, SV *h_)
1055     CODE:
1056     {
1057     int ow = SvIV (w_);
1058     int oh = SvIV (h_);
1059    
1060     if (ow && oh)
1061     {
1062     int nw = minpot (ow);
1063     int nh = minpot (oh);
1064    
1065     if (nw != ow || nh != oh)
1066     {
1067     if (SvOK (data_))
1068     {
1069     STRLEN datalen;
1070     char *data = SvPVbyte (data_, datalen);
1071     int bpp = datalen / (ow * oh);
1072     SV *result_ = sv_2mortal (newSV (nw * nh * bpp));
1073    
1074     SvPOK_only (result_);
1075     SvCUR_set (result_, nw * nh * bpp);
1076    
1077     memset (SvPVX (result_), 0, nw * nh * bpp);
1078     while (oh--)
1079     memcpy (SvPVX (result_) + oh * nw * bpp, data + oh * ow * bpp, ow * bpp);
1080    
1081     sv_setsv (data_, result_);
1082     }
1083    
1084     sv_setiv (w_, nw);
1085     sv_setiv (h_, nh);
1086     }
1087     }
1088     }
1089    
1090     void
1091 root 1.114 draw_quad (SV *self, float x, float y, float w = 0., float h = 0.)
1092 root 1.12 PROTOTYPE: $$$;$$
1093 root 1.76 ALIAS:
1094     draw_quad_alpha = 1
1095     draw_quad_alpha_premultiplied = 2
1096 root 1.11 CODE:
1097     {
1098 root 1.12 HV *hv = (HV *)SvRV (self);
1099 root 1.37 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
1100     float t = SvNV (*hv_fetch (hv, "t", 1, 1));
1101 root 1.12 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
1102    
1103     if (items < 5)
1104     {
1105 root 1.18 w = SvNV (*hv_fetch (hv, "w", 1, 1));
1106     h = SvNV (*hv_fetch (hv, "h", 1, 1));
1107 root 1.12 }
1108    
1109 root 1.76 if (ix)
1110     {
1111     glEnable (GL_BLEND);
1112 root 1.103
1113     if (ix == 2)
1114     glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1115     else
1116     gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1117 root 1.104 GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1118 root 1.103
1119 root 1.86 glEnable (GL_ALPHA_TEST);
1120     glAlphaFunc (GL_GREATER, 0.01f);
1121 root 1.76 }
1122    
1123 root 1.12 glBindTexture (GL_TEXTURE_2D, name);
1124 root 1.76
1125 root 1.12 glBegin (GL_QUADS);
1126 root 1.37 glTexCoord2f (0, 0); glVertex2f (x , y );
1127     glTexCoord2f (0, t); glVertex2f (x , y + h);
1128     glTexCoord2f (s, t); glVertex2f (x + w, y + h);
1129     glTexCoord2f (s, 0); glVertex2f (x + w, y );
1130 root 1.12 glEnd ();
1131 root 1.76
1132     if (ix)
1133 root 1.86 {
1134     glDisable (GL_ALPHA_TEST);
1135     glDisable (GL_BLEND);
1136     }
1137 root 1.11 }
1138 root 1.28
1139 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Map
1140 root 1.28
1141 root 1.133 CFPlus::Map
1142 root 1.28 new (SV *class, int map_width, int map_height)
1143     CODE:
1144     New (0, RETVAL, 1, struct map);
1145 root 1.42 RETVAL->x = 0;
1146     RETVAL->y = 0;
1147     RETVAL->w = map_width;
1148     RETVAL->h = map_height;
1149     RETVAL->ox = 0;
1150     RETVAL->oy = 0;
1151 root 1.30 RETVAL->faces = 8192;
1152     Newz (0, RETVAL->face, RETVAL->faces, mapface);
1153 root 1.42 RETVAL->texs = 8192;
1154     Newz (0, RETVAL->tex, RETVAL->texs, maptex);
1155 root 1.28 RETVAL->rows = 0;
1156     RETVAL->row = 0;
1157     OUTPUT:
1158     RETVAL
1159    
1160     void
1161 root 1.133 DESTROY (CFPlus::Map self)
1162 root 1.28 CODE:
1163     {
1164 root 1.30 map_clear (self);
1165 root 1.28 Safefree (self->face);
1166 root 1.111 Safefree (self->tex);
1167 root 1.29 Safefree (self);
1168     }
1169    
1170     void
1171 root 1.133 clear (CFPlus::Map self)
1172 root 1.30 CODE:
1173     map_clear (self);
1174    
1175     void
1176 root 1.133 set_face (CFPlus::Map self, int face, int texid)
1177 root 1.29 CODE:
1178     {
1179 root 1.42 while (self->faces <= face)
1180 root 1.28 {
1181 root 1.30 Append (mapface, self->face, self->faces, self->faces);
1182 root 1.29 self->faces *= 2;
1183     }
1184 root 1.28
1185 root 1.42 self->face [face] = texid;
1186     }
1187    
1188     void
1189 root 1.133 set_texture (CFPlus::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a)
1190 root 1.42 CODE:
1191     {
1192     while (self->texs <= texid)
1193     {
1194     Append (maptex, self->tex, self->texs, self->texs);
1195     self->texs *= 2;
1196     }
1197    
1198 root 1.48 {
1199     maptex *tex = self->tex + texid;
1200 root 1.39
1201 root 1.48 tex->name = name;
1202     tex->w = w;
1203     tex->h = h;
1204     tex->s = s;
1205     tex->t = t;
1206     tex->r = r;
1207     tex->g = g;
1208     tex->b = b;
1209     tex->a = a;
1210     }
1211 root 1.95
1212     // somewhat hackish, but for textures that require it, it really
1213     // improves the look, and most others don't suffer.
1214     glBindTexture (GL_TEXTURE_2D, name);
1215 root 1.99 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1216     //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1217     // use uglier nearest interpolation because linear suffers
1218     // from transparent color bleeding and ugly wrapping effects.
1219     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1220 root 1.29 }
1221    
1222 root 1.42 int
1223 root 1.133 ox (CFPlus::Map self)
1224 root 1.42 ALIAS:
1225     oy = 1
1226 root 1.101 x = 2
1227     y = 3
1228 root 1.102 w = 4
1229     h = 5
1230 root 1.42 CODE:
1231     switch (ix)
1232     {
1233     case 0: RETVAL = self->ox; break;
1234     case 1: RETVAL = self->oy; break;
1235 root 1.101 case 2: RETVAL = self->x; break;
1236     case 3: RETVAL = self->y; break;
1237 root 1.102 case 4: RETVAL = self->w; break;
1238     case 5: RETVAL = self->h; break;
1239 root 1.42 }
1240     OUTPUT:
1241     RETVAL
1242    
1243 root 1.29 void
1244 root 1.133 scroll (CFPlus::Map self, int dx, int dy)
1245 root 1.43 CODE:
1246     {
1247 root 1.44 if (dx > 0)
1248     map_blank (self, self->x, self->y, dx - 1, self->h);
1249     else if (dx < 0)
1250     map_blank (self, self->x + self->w + dx + 1, self->y, 1 - dx, self->h);
1251    
1252     if (dy > 0)
1253     map_blank (self, self->x, self->y, self->w, dy - 1);
1254     else if (dy < 0)
1255     map_blank (self, self->x, self->y + self->h + dy + 1, self->w, 1 - dy);
1256 root 1.43
1257 root 1.44 self->ox += dx; self->x += dx;
1258     self->oy += dy; self->y += dy;
1259 root 1.43
1260     while (self->y < 0)
1261     {
1262     Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
1263    
1264     self->rows += MAP_EXTEND_Y;
1265     self->y += MAP_EXTEND_Y;
1266     }
1267 root 1.44 }
1268 root 1.43
1269 root 1.44 void
1270 root 1.141 map1a_update (CFPlus::Map self, SV *data_, int extmap)
1271 root 1.44 CODE:
1272     {
1273 root 1.30 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1274     uint8_t *data_end = (uint8_t *)SvEND (data_);
1275 root 1.48 mapcell *cell;
1276     int x, y, flags;
1277 root 1.43
1278 root 1.150 while (data < data_end - 1)
1279 root 1.29 {
1280 root 1.48 flags = (data [0] << 8) + data [1]; data += 2;
1281 root 1.30
1282 root 1.120 x = self->x + ((flags >> 10) & 63);
1283     y = self->y + ((flags >> 4) & 63);
1284 root 1.29
1285 root 1.48 cell = map_get_cell (self, x, y);
1286 root 1.29
1287     if (flags & 15)
1288     {
1289 root 1.142 if (!cell->darkness)
1290 root 1.29 {
1291 root 1.142 cell->darkness = 256;
1292 root 1.29 cell->face [0] = 0;
1293     cell->face [1] = 0;
1294     cell->face [2] = 0;
1295     }
1296 root 1.45
1297 root 1.142 //TODO: don't trust server data to be in-range(!)
1298    
1299 root 1.141 if (flags & 8)
1300     {
1301     if (extmap)
1302     {
1303     uint8_t ext, cmd;
1304    
1305     do
1306     {
1307     ext = *data++;
1308 root 1.144 cmd = ext & 0x3f;
1309 root 1.141
1310 root 1.147 if (cmd < 4)
1311 root 1.142 cell->darkness = 255 - ext * 64 + 1;
1312 root 1.147 else if (cmd == 5) // health
1313     {
1314     cell->stat_width = 1;
1315     cell->stat_hp = *data++;
1316     }
1317     else if (cmd == 6) // monster width
1318     cell->stat_width = *data++ + 1;
1319 root 1.144 else if (ext & 0x40) // unknown, multibyte => skip
1320     data += *data + 1;
1321 root 1.147 else
1322     data++;
1323 root 1.141 }
1324 root 1.147 while (ext & 0x80);
1325 root 1.141 }
1326     else
1327 root 1.142 cell->darkness = *data++ + 1;
1328 root 1.141 }
1329 root 1.29
1330     if (flags & 4)
1331     {
1332 root 1.42 cell->face [0] = self->face [(data [0] << 8) + data [1]]; data += 2;
1333 root 1.29 }
1334    
1335     if (flags & 2)
1336     {
1337 root 1.42 cell->face [1] = self->face [(data [0] << 8) + data [1]]; data += 2;
1338 root 1.29 }
1339    
1340     if (flags & 1)
1341     {
1342 root 1.42 cell->face [2] = self->face [(data [0] << 8) + data [1]]; data += 2;
1343 root 1.29 }
1344     }
1345     else
1346 root 1.146 {
1347     cell->darkness = 0;
1348     cell->stat_hp = 0;
1349     }
1350 root 1.29 }
1351 root 1.28 }
1352    
1353 root 1.40 SV *
1354 root 1.133 mapmap (CFPlus::Map self, int x0, int y0, int w, int h)
1355 root 1.40 CODE:
1356     {
1357 root 1.55 int x1, x;
1358     int y1, y;
1359 root 1.40 int z;
1360     SV *map_sv = newSV (w * h * sizeof (uint32_t));
1361     uint32_t *map = (uint32_t *)SvPVX (map_sv);
1362    
1363     SvPOK_only (map_sv);
1364     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
1365    
1366 root 1.55 x0 += self->x; x1 = x0 + w;
1367     y0 += self->y; y1 = y0 + h;
1368 root 1.40
1369     for (y = y0; y < y1; y++)
1370     {
1371     maprow *row = 0 <= y && y < self->rows
1372     ? self->row + y
1373     : 0;
1374    
1375     for (x = x0; x < x1; x++)
1376     {
1377     int r = 32, g = 32, b = 32, a = 192;
1378    
1379     if (row && row->c0 <= x && x < row->c1)
1380     {
1381     mapcell *cell = row->col + (x - row->c0);
1382    
1383     for (z = 0; z <= 0; z++)
1384     {
1385 root 1.42 mapface face = cell->face [z];
1386 root 1.40
1387     if (face)
1388     {
1389 root 1.42 maptex tex = self->tex [face];
1390 root 1.40 int a0 = 255 - tex.a;
1391     int a1 = tex.a;
1392    
1393     r = (r * a0 + tex.r * a1) / 255;
1394     g = (g * a0 + tex.g * a1) / 255;
1395     b = (b * a0 + tex.b * a1) / 255;
1396     a = (a * a0 + tex.a * a1) / 255;
1397     }
1398     }
1399     }
1400    
1401     *map++ = (r )
1402     | (g << 8)
1403     | (b << 16)
1404     | (a << 24);
1405     }
1406     }
1407    
1408     RETVAL = map_sv;
1409     }
1410     OUTPUT:
1411     RETVAL
1412    
1413 root 1.30 void
1414 root 1.133 draw (CFPlus::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1415 root 1.116 CODE:
1416 root 1.30 {
1417 root 1.48 int vx, vy;
1418     int x, y, z;
1419     int last_name;
1420     mapface face;
1421    
1422 root 1.120 vx = self->x + self->w / 2 - sw / 2 - shift_x;
1423     vy = self->y + self->h / 2 - sh / 2 - shift_y;
1424 root 1.38
1425 root 1.42 /*
1426     int vx = self->vx = self->w >= sw
1427     ? self->x + (self->w - sw) / 2
1428     : MIN (self->x, MAX (self->x + self->w - sw + 1, self->vx));
1429    
1430     int vy = self->vy = self->h >= sh
1431     ? self->y + (self->h - sh) / 2
1432     : MIN (self->y, MAX (self->y + self->h - sh + 1, self->vy));
1433     */
1434 root 1.30
1435     glColor4ub (255, 255, 255, 255);
1436    
1437 root 1.117 glEnable (GL_BLEND);
1438 root 1.30 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1439     glEnable (GL_TEXTURE_2D);
1440     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1441    
1442 root 1.48 glBegin (GL_QUADS);
1443 root 1.30
1444 root 1.48 last_name = 0;
1445 root 1.30
1446     for (z = 0; z < 3; z++)
1447     for (y = 0; y < sh; y++)
1448     if (0 <= y + vy && y + vy < self->rows)
1449     {
1450     maprow *row = self->row + (y + vy);
1451    
1452     for (x = 0; x < sw; x++)
1453     if (row->c0 <= x + vx && x + vx < row->c1)
1454     {
1455     mapcell *cell = row->col + (x + vx - row->c0);
1456 root 1.32
1457 root 1.48 face = cell->face [z];
1458 root 1.30
1459 root 1.145 if (face && face < self->texs)
1460 root 1.30 {
1461 root 1.42 maptex tex = self->tex [face];
1462 root 1.30
1463     int px = (x + 1) * 32 - tex.w;
1464     int py = (y + 1) * 32 - tex.h;
1465    
1466     if (last_name != tex.name)
1467     {
1468     glEnd ();
1469     last_name = tex.name;
1470     glBindTexture (GL_TEXTURE_2D, last_name);
1471     glBegin (GL_QUADS);
1472     }
1473    
1474     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1475     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1476     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1477     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1478     }
1479     }
1480     }
1481    
1482     glEnd ();
1483 root 1.32
1484 root 1.34 glDisable (GL_TEXTURE_2D);
1485 root 1.152 glDisable (GL_BLEND);
1486 root 1.143
1487 root 1.145 // top layer: overlays such as the health bar
1488 root 1.143 for (y = 0; y < sh; y++)
1489     if (0 <= y + vy && y + vy < self->rows)
1490     {
1491     maprow *row = self->row + (y + vy);
1492    
1493     for (x = 0; x < sw; x++)
1494     if (row->c0 <= x + vx && x + vx < row->c1)
1495     {
1496     mapcell *cell = row->col + (x + vx - row->c0);
1497    
1498     int px = x * 32;
1499     int py = y * 32;
1500    
1501     if (cell->stat_hp)
1502     {
1503 root 1.147 int width = cell->stat_width * 32;
1504     int thick = sh / 28 + 1 + cell->stat_width;
1505 root 1.143
1506 root 1.152 glColor3ub (0, 0, 0);
1507 root 1.151 glRectf (px + 1, py - thick - 2,
1508     px + width - 1, py);
1509 root 1.147
1510 root 1.152 glColor3ub (cell->stat_hp, 255 - cell->stat_hp, 0);
1511 root 1.147 glRectf (px + 2,
1512 root 1.151 py - thick - 1,
1513     px + width - 2 - cell->stat_hp * (width - 4) / 255, py - 1);
1514 root 1.143 }
1515     }
1516     }
1517 root 1.116 }
1518    
1519     void
1520 root 1.133 draw_magicmap (CFPlus::Map self, int dx, int dy, int w, int h, unsigned char *data)
1521 root 1.117 CODE:
1522     {
1523     static float color[16][3] = {
1524 root 1.123 { 0.00F, 0.00F, 0.00F },
1525     { 1.00F, 1.00F, 1.00F },
1526     { 0.00F, 0.00F, 0.55F },
1527     { 1.00F, 0.00F, 0.00F },
1528    
1529     { 1.00F, 0.54F, 0.00F },
1530     { 0.11F, 0.56F, 1.00F },
1531     { 0.93F, 0.46F, 0.00F },
1532     { 0.18F, 0.54F, 0.34F },
1533    
1534     { 0.56F, 0.73F, 0.56F },
1535     { 0.80F, 0.80F, 0.80F },
1536     { 0.55F, 0.41F, 0.13F },
1537     { 0.99F, 0.77F, 0.26F },
1538    
1539     { 0.74F, 0.65F, 0.41F },
1540    
1541     { 0.00F, 1.00F, 1.00F },
1542     { 1.00F, 0.00F, 1.00F },
1543     { 1.00F, 1.00F, 0.00F },
1544 root 1.117 };
1545    
1546     int x, y;
1547    
1548     glEnable (GL_TEXTURE_2D);
1549     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1550     glEnable (GL_BLEND);
1551     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1552     glBegin (GL_QUADS);
1553    
1554     for (y = 0; y < h; y++)
1555     for (x = 0; x < w; x++)
1556     {
1557     unsigned char m = data [x + y * w];
1558    
1559 root 1.118 if (m)
1560     {
1561     float *c = color [m & 15];
1562    
1563     float tx1 = m & 0x40 ? 0.5 : 0.;
1564     float tx2 = tx1 + 0.5;
1565    
1566     glColor4f (c[0], c[1], c[2], 0.75);
1567     glTexCoord2f (tx1, 0.); glVertex2i (x , y );
1568     glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
1569     glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
1570     glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
1571     }
1572 root 1.117 }
1573    
1574     glEnd ();
1575     glDisable (GL_BLEND);
1576     glDisable (GL_TEXTURE_2D);
1577     }
1578    
1579     void
1580 root 1.133 fow_texture (CFPlus::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1581 root 1.116 PPCODE:
1582     {
1583     int vx, vy;
1584     int x, y;
1585     int sw4 = (sw + 3) & ~3;
1586     SV *darkness_sv = sv_2mortal (newSV (sw4 * sh));
1587     uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv);
1588    
1589     memset (darkness, 255, sw4 * sh);
1590     SvPOK_only (darkness_sv);
1591     SvCUR_set (darkness_sv, sw4 * sh);
1592    
1593     vx = self->x + (self->w - sw + 1) / 2 - shift_x;
1594     vy = self->y + (self->h - sh + 1) / 2 - shift_y;
1595    
1596     for (y = 0; y < sh; y++)
1597     if (0 <= y + vy && y + vy < self->rows)
1598     {
1599     maprow *row = self->row + (y + vy);
1600    
1601     for (x = 0; x < sw; x++)
1602     if (row->c0 <= x + vx && x + vx < row->c1)
1603     {
1604     mapcell *cell = row->col + (x + vx - row->c0);
1605    
1606 root 1.142 darkness[y * sw4 + x] = cell->darkness
1607 root 1.143 ? 255 - (cell->darkness - 1)
1608 root 1.142 : 255 - FOW_DARKNESS;
1609 root 1.116 }
1610     }
1611 root 1.34
1612 root 1.32 EXTEND (SP, 3);
1613     PUSHs (sv_2mortal (newSViv (sw4)));
1614     PUSHs (sv_2mortal (newSViv (sh)));
1615     PUSHs (darkness_sv);
1616 root 1.30 }
1617    
1618 root 1.42 SV *
1619 root 1.133 get_rect (CFPlus::Map self, int x0, int y0, int w, int h)
1620 root 1.42 CODE:
1621     {
1622     int x, y, x1, y1;
1623     SV *data_sv = newSV (w * h * 7 + 5);
1624     uint8_t *data = (uint8_t *)SvPVX (data_sv);
1625    
1626     *data++ = 0; /* version 0 format */
1627     *data++ = w >> 8; *data++ = w;
1628     *data++ = h >> 8; *data++ = h;
1629    
1630     // we need to do this 'cause we don't keep an absolute coord system for rows
1631 root 1.55 // TODO: treat rows as we treat columns
1632 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1633     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1634    
1635     x0 += self->x - self->ox;
1636     y0 += self->y - self->oy;
1637    
1638     x1 = x0 + w;
1639     y1 = y0 + h;
1640    
1641     for (y = y0; y < y1; y++)
1642     {
1643     maprow *row = 0 <= y && y < self->rows
1644     ? self->row + y
1645     : 0;
1646    
1647     for (x = x0; x < x1; x++)
1648     {
1649     if (row && row->c0 <= x && x < row->c1)
1650     {
1651     mapcell *cell = row->col + (x - row->c0);
1652     uint8_t flags = 0;
1653    
1654     if (cell->face [0]) flags |= 1;
1655     if (cell->face [1]) flags |= 2;
1656     if (cell->face [2]) flags |= 4;
1657    
1658     *data++ = flags;
1659    
1660     if (flags & 1)
1661     {
1662     *data++ = cell->face [0] >> 8;
1663     *data++ = cell->face [0];
1664     }
1665    
1666     if (flags & 2)
1667     {
1668     *data++ = cell->face [1] >> 8;
1669     *data++ = cell->face [1];
1670     }
1671    
1672     if (flags & 4)
1673     {
1674     *data++ = cell->face [2] >> 8;
1675     *data++ = cell->face [2];
1676     }
1677     }
1678     else
1679     *data++ = 0;
1680     }
1681     }
1682    
1683     SvPOK_only (data_sv);
1684     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
1685     RETVAL = data_sv;
1686     }
1687     OUTPUT:
1688     RETVAL
1689    
1690     void
1691 root 1.133 set_rect (CFPlus::Map self, int x0, int y0, uint8_t *data)
1692 root 1.42 PPCODE:
1693     {
1694     int x, y, z;
1695 root 1.48 int w, h;
1696 root 1.42 int x1, y1;
1697    
1698     if (*data++ != 0)
1699     return; /* version mismatch */
1700    
1701 root 1.48 w = *data++ << 8; w |= *data++;
1702     h = *data++ << 8; h |= *data++;
1703 root 1.42
1704     // we need to do this 'cause we don't keep an absolute coord system for rows
1705 root 1.55 // TODO: treat rows as we treat columns
1706 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1707     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1708    
1709     x0 += self->x - self->ox;
1710     y0 += self->y - self->oy;
1711    
1712     x1 = x0 + w;
1713     y1 = y0 + h;
1714    
1715     for (y = y0; y < y1; y++)
1716     {
1717     maprow *row = map_get_row (self, y);
1718    
1719     for (x = x0; x < x1; x++)
1720     {
1721     uint8_t flags = *data++;
1722    
1723     if (flags)
1724     {
1725     mapface face[3] = { 0, 0, 0 };
1726    
1727     mapcell *cell = row_get_cell (row, x);
1728    
1729     if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; }
1730     if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; }
1731     if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; }
1732    
1733 root 1.143 if (cell->darkness == 0)
1734 root 1.42 {
1735 root 1.142 cell->darkness = 0;
1736 root 1.42
1737     for (z = 0; z <= 2; z++)
1738     {
1739     cell->face[z] = face[z];
1740    
1741     if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name))
1742     XPUSHs (sv_2mortal (newSViv (face[z])));
1743     }
1744     }
1745     }
1746     }
1747     }
1748     }
1749    
1750 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixChunk
1751 root 1.52
1752 root 1.133 CFPlus::MixChunk
1753 root 1.52 new_from_file (SV *class, char *path)
1754     CODE:
1755     RETVAL = Mix_LoadWAV (path);
1756     OUTPUT:
1757     RETVAL
1758    
1759     void
1760 root 1.133 DESTROY (CFPlus::MixChunk self)
1761 root 1.52 CODE:
1762     Mix_FreeChunk (self);
1763    
1764     int
1765 root 1.133 volume (CFPlus::MixChunk self, int volume = -1)
1766 root 1.52 CODE:
1767     RETVAL = Mix_VolumeChunk (self, volume);
1768     OUTPUT:
1769     RETVAL
1770    
1771     int
1772 root 1.133 play (CFPlus::MixChunk self, int channel = -1, int loops = 0, int ticks = -1)
1773 root 1.52 CODE:
1774     RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
1775     OUTPUT:
1776     RETVAL
1777    
1778 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixMusic
1779 root 1.52
1780     int
1781     volume (int volume = -1)
1782     CODE:
1783     RETVAL = Mix_VolumeMusic (volume);
1784     OUTPUT:
1785     RETVAL
1786    
1787 root 1.133 CFPlus::MixMusic
1788 root 1.52 new_from_file (SV *class, char *path)
1789     CODE:
1790     RETVAL = Mix_LoadMUS (path);
1791     OUTPUT:
1792     RETVAL
1793    
1794     void
1795 root 1.133 DESTROY (CFPlus::MixMusic self)
1796 root 1.52 CODE:
1797     Mix_FreeMusic (self);
1798    
1799     int
1800 root 1.133 play (CFPlus::MixMusic self, int loops = -1)
1801 root 1.52 CODE:
1802     RETVAL = Mix_PlayMusic (self, loops);
1803     OUTPUT:
1804     RETVAL
1805    
1806 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::OpenGL
1807 root 1.54
1808     BOOT:
1809     {
1810 root 1.133 HV *stash = gv_stashpv ("CFPlus::OpenGL", 1);
1811 root 1.54 static const struct {
1812     const char *name;
1813     IV iv;
1814     } *civ, const_iv[] = {
1815     # define const_iv(name) { # name, (IV)name }
1816     const_iv (GL_COLOR_MATERIAL),
1817     const_iv (GL_SMOOTH),
1818     const_iv (GL_FLAT),
1819 root 1.69 const_iv (GL_DITHER),
1820 root 1.54 const_iv (GL_BLEND),
1821 root 1.89 const_iv (GL_CULL_FACE),
1822 root 1.69 const_iv (GL_SCISSOR_TEST),
1823 root 1.89 const_iv (GL_DEPTH_TEST),
1824     const_iv (GL_ALPHA_TEST),
1825     const_iv (GL_NORMALIZE),
1826     const_iv (GL_RESCALE_NORMAL),
1827 root 1.119 const_iv (GL_FRONT),
1828     const_iv (GL_BACK),
1829 root 1.54 const_iv (GL_AND),
1830 root 1.67 const_iv (GL_ONE),
1831     const_iv (GL_ZERO),
1832 root 1.54 const_iv (GL_SRC_ALPHA),
1833 root 1.104 const_iv (GL_DST_ALPHA),
1834 root 1.54 const_iv (GL_ONE_MINUS_SRC_ALPHA),
1835 root 1.67 const_iv (GL_ONE_MINUS_DST_ALPHA),
1836 root 1.104 const_iv (GL_SRC_ALPHA_SATURATE),
1837 root 1.54 const_iv (GL_RGB),
1838     const_iv (GL_RGBA),
1839 root 1.115 const_iv (GL_RGBA4),
1840     const_iv (GL_RGBA8),
1841     const_iv (GL_RGB5_A1),
1842 root 1.54 const_iv (GL_UNSIGNED_BYTE),
1843 root 1.89 const_iv (GL_UNSIGNED_SHORT),
1844     const_iv (GL_UNSIGNED_INT),
1845 root 1.54 const_iv (GL_ALPHA),
1846 root 1.86 const_iv (GL_INTENSITY),
1847 root 1.76 const_iv (GL_LUMINANCE),
1848 root 1.86 const_iv (GL_LUMINANCE_ALPHA),
1849 root 1.54 const_iv (GL_FLOAT),
1850     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1851     const_iv (GL_COMPILE),
1852     const_iv (GL_TEXTURE_1D),
1853     const_iv (GL_TEXTURE_2D),
1854     const_iv (GL_TEXTURE_ENV),
1855     const_iv (GL_TEXTURE_MAG_FILTER),
1856     const_iv (GL_TEXTURE_MIN_FILTER),
1857     const_iv (GL_TEXTURE_ENV_MODE),
1858     const_iv (GL_TEXTURE_WRAP_S),
1859     const_iv (GL_TEXTURE_WRAP_T),
1860 root 1.98 const_iv (GL_REPEAT),
1861 root 1.54 const_iv (GL_CLAMP),
1862 root 1.98 const_iv (GL_CLAMP_TO_EDGE),
1863 root 1.54 const_iv (GL_NEAREST),
1864     const_iv (GL_LINEAR),
1865 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
1866     const_iv (GL_LINEAR_MIPMAP_NEAREST),
1867     const_iv (GL_NEAREST_MIPMAP_LINEAR),
1868     const_iv (GL_LINEAR_MIPMAP_LINEAR),
1869     const_iv (GL_GENERATE_MIPMAP),
1870 root 1.54 const_iv (GL_MODULATE),
1871 root 1.69 const_iv (GL_DECAL),
1872 root 1.54 const_iv (GL_REPLACE),
1873 root 1.89 const_iv (GL_DEPTH_BUFFER_BIT),
1874 root 1.54 const_iv (GL_COLOR_BUFFER_BIT),
1875     const_iv (GL_PROJECTION),
1876     const_iv (GL_MODELVIEW),
1877     const_iv (GL_COLOR_LOGIC_OP),
1878 root 1.69 const_iv (GL_SEPARABLE_2D),
1879 root 1.54 const_iv (GL_CONVOLUTION_2D),
1880     const_iv (GL_CONVOLUTION_BORDER_MODE),
1881     const_iv (GL_CONSTANT_BORDER),
1882     const_iv (GL_LINES),
1883 root 1.138 const_iv (GL_LINE_STRIP),
1884 root 1.89 const_iv (GL_LINE_LOOP),
1885 root 1.54 const_iv (GL_QUADS),
1886 root 1.89 const_iv (GL_QUAD_STRIP),
1887     const_iv (GL_TRIANGLES),
1888     const_iv (GL_TRIANGLE_STRIP),
1889     const_iv (GL_TRIANGLE_FAN),
1890 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1891     const_iv (GL_FASTEST),
1892 root 1.89 const_iv (GL_V2F),
1893     const_iv (GL_V3F),
1894     const_iv (GL_T2F_V3F),
1895     const_iv (GL_T2F_N3F_V3F),
1896 root 1.54 # undef const_iv
1897     };
1898    
1899     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1900     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1901     }
1902    
1903 root 1.97 char *
1904     gl_vendor ()
1905     CODE:
1906     RETVAL = (char *)glGetString (GL_VENDOR);
1907     OUTPUT:
1908     RETVAL
1909    
1910     char *
1911     gl_version ()
1912     CODE:
1913     RETVAL = (char *)glGetString (GL_VERSION);
1914     OUTPUT:
1915     RETVAL
1916    
1917     char *
1918     gl_extensions ()
1919     CODE:
1920     RETVAL = (char *)glGetString (GL_EXTENSIONS);
1921     OUTPUT:
1922     RETVAL
1923    
1924 root 1.54 int glGetError ()
1925    
1926 root 1.114 void glFinish ()
1927    
1928 root 1.54 void glClear (int mask)
1929    
1930     void glClearColor (float r, float g, float b, float a = 1.0)
1931     PROTOTYPE: @
1932    
1933     void glEnable (int cap)
1934    
1935     void glDisable (int cap)
1936    
1937     void glShadeModel (int mode)
1938    
1939     void glHint (int target, int mode)
1940    
1941     void glBlendFunc (int sfactor, int dfactor)
1942    
1943 root 1.103 void glBlendFuncSeparate (int sa, int da, int saa, int daa)
1944     CODE:
1945     gl_BlendFuncSeparate (sa, da, saa, daa);
1946    
1947 root 1.89 void glDepthMask (int flag)
1948    
1949 root 1.54 void glLogicOp (int opcode)
1950    
1951 root 1.68 void glColorMask (int red, int green, int blue, int alpha)
1952    
1953 root 1.54 void glMatrixMode (int mode)
1954    
1955     void glPushMatrix ()
1956    
1957     void glPopMatrix ()
1958    
1959     void glLoadIdentity ()
1960    
1961 root 1.119 void glDrawBuffer (int buffer)
1962    
1963     void glReadBuffer (int buffer)
1964    
1965 root 1.90 # near_ and far_ are due to microsofts buggy "c" compiler
1966     void glFrustum (double left, double right, double bottom, double top, double near_, double far_)
1967    
1968     # near_ and far_ are due to microsofts buggy "c" compiler
1969 root 1.64 void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
1970 root 1.54
1971     void glViewport (int x, int y, int width, int height)
1972    
1973 root 1.69 void glScissor (int x, int y, int width, int height)
1974    
1975 root 1.54 void glTranslate (float x, float y, float z = 0.)
1976     CODE:
1977     glTranslatef (x, y, z);
1978    
1979 root 1.62 void glScale (float x, float y, float z = 1.)
1980 root 1.54 CODE:
1981     glScalef (x, y, z);
1982    
1983     void glRotate (float angle, float x, float y, float z)
1984     CODE:
1985     glRotatef (angle, x, y, z);
1986    
1987     void glBegin (int mode)
1988    
1989     void glEnd ()
1990    
1991     void glColor (float r, float g, float b, float a = 1.0)
1992     PROTOTYPE: @
1993 root 1.103 ALIAS:
1994     glColor_premultiply = 1
1995 root 1.54 CODE:
1996 root 1.103 if (ix)
1997     {
1998     r *= a;
1999     g *= a;
2000     b *= a;
2001     }
2002 root 1.90 // microsoft visual "c" rounds instead of truncating...
2003 root 1.130 glColor4f (r, g, b, a);
2004 root 1.54
2005 root 1.89 void glInterleavedArrays (int format, int stride, char *data)
2006    
2007     void glDrawElements (int mode, int count, int type, char *indices)
2008    
2009     # 1.2 void glDrawRangeElements (int mode, int start, int end
2010    
2011 root 1.91 void glRasterPos (float x, float y, float z = 0.)
2012     CODE:
2013     glRasterPos3f (0, 0, z);
2014     glBitmap (0, 0, 0, 0, x, y, 0);
2015    
2016 root 1.54 void glVertex (float x, float y, float z = 0.)
2017     CODE:
2018     glVertex3f (x, y, z);
2019    
2020     void glTexCoord (float s, float t)
2021     CODE:
2022     glTexCoord2f (s, t);
2023    
2024     void glTexEnv (int target, int pname, float param)
2025     CODE:
2026     glTexEnvf (target, pname, param);
2027    
2028     void glTexParameter (int target, int pname, float param)
2029     CODE:
2030     glTexParameterf (target, pname, param);
2031    
2032     void glBindTexture (int target, int name)
2033    
2034     void glConvolutionParameter (int target, int pname, float params)
2035     CODE:
2036 root 1.103 if (gl.ConvolutionParameterf)
2037     gl.ConvolutionParameterf (target, pname, params);
2038 root 1.54
2039     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
2040 root 1.64 CODE:
2041 root 1.103 if (gl.ConvolutionFilter2D)
2042     gl.ConvolutionFilter2D (target, internalformat, width, height, format, type, data);
2043 root 1.54
2044 root 1.69 void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
2045     CODE:
2046 root 1.103 if (gl.SeparableFilter2D)
2047     gl.SeparableFilter2D (target, internalformat, width, height, format, type, row, column);
2048 root 1.69
2049 root 1.54 void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
2050    
2051     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
2052    
2053 root 1.91 void glDrawPixels (int width, int height, int format, int type, char *pixels)
2054 root 1.68
2055     void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
2056    
2057 root 1.54 int glGenTexture ()
2058     CODE:
2059     {
2060     GLuint name;
2061     glGenTextures (1, &name);
2062     RETVAL = name;
2063     }
2064     OUTPUT:
2065     RETVAL
2066    
2067     void glDeleteTexture (int name)
2068     CODE:
2069     {
2070     GLuint name_ = name;
2071     glDeleteTextures (1, &name_);
2072     }
2073    
2074     int glGenList ()
2075     CODE:
2076     RETVAL = glGenLists (1);
2077     OUTPUT:
2078     RETVAL
2079    
2080     void glDeleteList (int list)
2081     CODE:
2082     glDeleteLists (list, 1);
2083    
2084     void glNewList (int list, int mode = GL_COMPILE)
2085    
2086     void glEndList ()
2087    
2088     void glCallList (int list)
2089