ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.146
Committed: Sat Aug 19 02:49:53 2006 UTC (17 years, 8 months ago) by root
Branch: MAIN
Changes since 1.145: +9 -3 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.142 uint8_t 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.29 while (data < data_end)
1279     {
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     if (ext < 4)
1311 root 1.142 cell->darkness = 255 - ext * 64 + 1;
1312     else if (ext == 5) // health
1313     cell->stat_hp = *data++;
1314 root 1.144 else if (ext & 0x40) // unknown, multibyte => skip
1315     data += *data + 1;
1316 root 1.141 }
1317     while (cmd & 0x80);
1318     }
1319     else
1320 root 1.142 cell->darkness = *data++ + 1;
1321 root 1.141 }
1322 root 1.29
1323     if (flags & 4)
1324     {
1325 root 1.42 cell->face [0] = self->face [(data [0] << 8) + data [1]]; data += 2;
1326 root 1.29 }
1327    
1328     if (flags & 2)
1329     {
1330 root 1.42 cell->face [1] = self->face [(data [0] << 8) + data [1]]; data += 2;
1331 root 1.29 }
1332    
1333     if (flags & 1)
1334     {
1335 root 1.42 cell->face [2] = self->face [(data [0] << 8) + data [1]]; data += 2;
1336 root 1.29 }
1337     }
1338     else
1339 root 1.146 {
1340     cell->darkness = 0;
1341     cell->stat_hp = 0;
1342     }
1343 root 1.29 }
1344 root 1.28 }
1345    
1346 root 1.40 SV *
1347 root 1.133 mapmap (CFPlus::Map self, int x0, int y0, int w, int h)
1348 root 1.40 CODE:
1349     {
1350 root 1.55 int x1, x;
1351     int y1, y;
1352 root 1.40 int z;
1353     SV *map_sv = newSV (w * h * sizeof (uint32_t));
1354     uint32_t *map = (uint32_t *)SvPVX (map_sv);
1355    
1356     SvPOK_only (map_sv);
1357     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
1358    
1359 root 1.55 x0 += self->x; x1 = x0 + w;
1360     y0 += self->y; y1 = y0 + h;
1361 root 1.40
1362     for (y = y0; y < y1; y++)
1363     {
1364     maprow *row = 0 <= y && y < self->rows
1365     ? self->row + y
1366     : 0;
1367    
1368     for (x = x0; x < x1; x++)
1369     {
1370     int r = 32, g = 32, b = 32, a = 192;
1371    
1372     if (row && row->c0 <= x && x < row->c1)
1373     {
1374     mapcell *cell = row->col + (x - row->c0);
1375    
1376     for (z = 0; z <= 0; z++)
1377     {
1378 root 1.42 mapface face = cell->face [z];
1379 root 1.40
1380     if (face)
1381     {
1382 root 1.42 maptex tex = self->tex [face];
1383 root 1.40 int a0 = 255 - tex.a;
1384     int a1 = tex.a;
1385    
1386     r = (r * a0 + tex.r * a1) / 255;
1387     g = (g * a0 + tex.g * a1) / 255;
1388     b = (b * a0 + tex.b * a1) / 255;
1389     a = (a * a0 + tex.a * a1) / 255;
1390     }
1391     }
1392     }
1393    
1394     *map++ = (r )
1395     | (g << 8)
1396     | (b << 16)
1397     | (a << 24);
1398     }
1399     }
1400    
1401     RETVAL = map_sv;
1402     }
1403     OUTPUT:
1404     RETVAL
1405    
1406 root 1.30 void
1407 root 1.133 draw (CFPlus::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1408 root 1.116 CODE:
1409 root 1.30 {
1410 root 1.48 int vx, vy;
1411     int x, y, z;
1412     int last_name;
1413     mapface face;
1414    
1415 root 1.120 vx = self->x + self->w / 2 - sw / 2 - shift_x;
1416     vy = self->y + self->h / 2 - sh / 2 - shift_y;
1417 root 1.38
1418 root 1.42 /*
1419     int vx = self->vx = self->w >= sw
1420     ? self->x + (self->w - sw) / 2
1421     : MIN (self->x, MAX (self->x + self->w - sw + 1, self->vx));
1422    
1423     int vy = self->vy = self->h >= sh
1424     ? self->y + (self->h - sh) / 2
1425     : MIN (self->y, MAX (self->y + self->h - sh + 1, self->vy));
1426     */
1427 root 1.30
1428     glColor4ub (255, 255, 255, 255);
1429    
1430 root 1.117 glEnable (GL_BLEND);
1431 root 1.30 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1432     glEnable (GL_TEXTURE_2D);
1433     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1434    
1435 root 1.48 glBegin (GL_QUADS);
1436 root 1.30
1437 root 1.48 last_name = 0;
1438 root 1.30
1439     for (z = 0; z < 3; z++)
1440     for (y = 0; y < sh; y++)
1441     if (0 <= y + vy && y + vy < self->rows)
1442     {
1443     maprow *row = self->row + (y + vy);
1444    
1445     for (x = 0; x < sw; x++)
1446     if (row->c0 <= x + vx && x + vx < row->c1)
1447     {
1448     mapcell *cell = row->col + (x + vx - row->c0);
1449 root 1.32
1450 root 1.48 face = cell->face [z];
1451 root 1.30
1452 root 1.145 if (face && face < self->texs)
1453 root 1.30 {
1454 root 1.42 maptex tex = self->tex [face];
1455 root 1.30
1456     int px = (x + 1) * 32 - tex.w;
1457     int py = (y + 1) * 32 - tex.h;
1458    
1459     if (last_name != tex.name)
1460     {
1461     glEnd ();
1462     last_name = tex.name;
1463     glBindTexture (GL_TEXTURE_2D, last_name);
1464     glBegin (GL_QUADS);
1465     }
1466    
1467     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1468     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1469     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1470     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1471     }
1472     }
1473     }
1474    
1475     glEnd ();
1476 root 1.32
1477 root 1.34 glDisable (GL_TEXTURE_2D);
1478     glDisable (GL_BLEND);
1479 root 1.143
1480 root 1.145 // top layer: overlays such as the health bar
1481 root 1.143 for (y = 0; y < sh; y++)
1482     if (0 <= y + vy && y + vy < self->rows)
1483     {
1484     maprow *row = self->row + (y + vy);
1485    
1486     for (x = 0; x < sw; x++)
1487     if (row->c0 <= x + vx && x + vx < row->c1)
1488     {
1489     mapcell *cell = row->col + (x + vx - row->c0);
1490    
1491     int px = x * 32;
1492     int py = y * 32;
1493    
1494     if (cell->stat_hp)
1495     {
1496 root 1.145 int width = sh / 28 + 1;
1497    
1498 root 1.143 glColor3ub (0, 0, 0);
1499 root 1.145 glRectf (px + 1, py, px + 31, py + width + 2);
1500 root 1.143
1501 root 1.145 glColor3ub (cell->stat_hp, 255 - cell->stat_hp, 0);
1502     glRectf (px + 2, py + 1, px + 30 - cell->stat_hp * 28 / 255, py + width + 1);
1503 root 1.143 }
1504     }
1505     }
1506 root 1.116 }
1507    
1508     void
1509 root 1.133 draw_magicmap (CFPlus::Map self, int dx, int dy, int w, int h, unsigned char *data)
1510 root 1.117 CODE:
1511     {
1512     static float color[16][3] = {
1513 root 1.123 { 0.00F, 0.00F, 0.00F },
1514     { 1.00F, 1.00F, 1.00F },
1515     { 0.00F, 0.00F, 0.55F },
1516     { 1.00F, 0.00F, 0.00F },
1517    
1518     { 1.00F, 0.54F, 0.00F },
1519     { 0.11F, 0.56F, 1.00F },
1520     { 0.93F, 0.46F, 0.00F },
1521     { 0.18F, 0.54F, 0.34F },
1522    
1523     { 0.56F, 0.73F, 0.56F },
1524     { 0.80F, 0.80F, 0.80F },
1525     { 0.55F, 0.41F, 0.13F },
1526     { 0.99F, 0.77F, 0.26F },
1527    
1528     { 0.74F, 0.65F, 0.41F },
1529    
1530     { 0.00F, 1.00F, 1.00F },
1531     { 1.00F, 0.00F, 1.00F },
1532     { 1.00F, 1.00F, 0.00F },
1533 root 1.117 };
1534    
1535     int x, y;
1536    
1537     glEnable (GL_TEXTURE_2D);
1538     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1539     glEnable (GL_BLEND);
1540     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1541     glBegin (GL_QUADS);
1542    
1543     for (y = 0; y < h; y++)
1544     for (x = 0; x < w; x++)
1545     {
1546     unsigned char m = data [x + y * w];
1547    
1548 root 1.118 if (m)
1549     {
1550     float *c = color [m & 15];
1551    
1552     float tx1 = m & 0x40 ? 0.5 : 0.;
1553     float tx2 = tx1 + 0.5;
1554    
1555     glColor4f (c[0], c[1], c[2], 0.75);
1556     glTexCoord2f (tx1, 0.); glVertex2i (x , y );
1557     glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
1558     glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
1559     glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
1560     }
1561 root 1.117 }
1562    
1563     glEnd ();
1564     glDisable (GL_BLEND);
1565     glDisable (GL_TEXTURE_2D);
1566     }
1567    
1568     void
1569 root 1.133 fow_texture (CFPlus::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1570 root 1.116 PPCODE:
1571     {
1572     int vx, vy;
1573     int x, y;
1574     int sw4 = (sw + 3) & ~3;
1575     SV *darkness_sv = sv_2mortal (newSV (sw4 * sh));
1576     uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv);
1577    
1578     memset (darkness, 255, sw4 * sh);
1579     SvPOK_only (darkness_sv);
1580     SvCUR_set (darkness_sv, sw4 * sh);
1581    
1582     vx = self->x + (self->w - sw + 1) / 2 - shift_x;
1583     vy = self->y + (self->h - sh + 1) / 2 - shift_y;
1584    
1585     for (y = 0; y < sh; y++)
1586     if (0 <= y + vy && y + vy < self->rows)
1587     {
1588     maprow *row = self->row + (y + vy);
1589    
1590     for (x = 0; x < sw; x++)
1591     if (row->c0 <= x + vx && x + vx < row->c1)
1592     {
1593     mapcell *cell = row->col + (x + vx - row->c0);
1594    
1595 root 1.142 darkness[y * sw4 + x] = cell->darkness
1596 root 1.143 ? 255 - (cell->darkness - 1)
1597 root 1.142 : 255 - FOW_DARKNESS;
1598 root 1.116 }
1599     }
1600 root 1.34
1601 root 1.32 EXTEND (SP, 3);
1602     PUSHs (sv_2mortal (newSViv (sw4)));
1603     PUSHs (sv_2mortal (newSViv (sh)));
1604     PUSHs (darkness_sv);
1605 root 1.30 }
1606    
1607 root 1.42 SV *
1608 root 1.133 get_rect (CFPlus::Map self, int x0, int y0, int w, int h)
1609 root 1.42 CODE:
1610     {
1611     int x, y, x1, y1;
1612     SV *data_sv = newSV (w * h * 7 + 5);
1613     uint8_t *data = (uint8_t *)SvPVX (data_sv);
1614    
1615     *data++ = 0; /* version 0 format */
1616     *data++ = w >> 8; *data++ = w;
1617     *data++ = h >> 8; *data++ = h;
1618    
1619     // we need to do this 'cause we don't keep an absolute coord system for rows
1620 root 1.55 // TODO: treat rows as we treat columns
1621 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1622     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1623    
1624     x0 += self->x - self->ox;
1625     y0 += self->y - self->oy;
1626    
1627     x1 = x0 + w;
1628     y1 = y0 + h;
1629    
1630     for (y = y0; y < y1; y++)
1631     {
1632     maprow *row = 0 <= y && y < self->rows
1633     ? self->row + y
1634     : 0;
1635    
1636     for (x = x0; x < x1; x++)
1637     {
1638     if (row && row->c0 <= x && x < row->c1)
1639     {
1640     mapcell *cell = row->col + (x - row->c0);
1641     uint8_t flags = 0;
1642    
1643     if (cell->face [0]) flags |= 1;
1644     if (cell->face [1]) flags |= 2;
1645     if (cell->face [2]) flags |= 4;
1646    
1647     *data++ = flags;
1648    
1649     if (flags & 1)
1650     {
1651     *data++ = cell->face [0] >> 8;
1652     *data++ = cell->face [0];
1653     }
1654    
1655     if (flags & 2)
1656     {
1657     *data++ = cell->face [1] >> 8;
1658     *data++ = cell->face [1];
1659     }
1660    
1661     if (flags & 4)
1662     {
1663     *data++ = cell->face [2] >> 8;
1664     *data++ = cell->face [2];
1665     }
1666     }
1667     else
1668     *data++ = 0;
1669     }
1670     }
1671    
1672     SvPOK_only (data_sv);
1673     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
1674     RETVAL = data_sv;
1675     }
1676     OUTPUT:
1677     RETVAL
1678    
1679     void
1680 root 1.133 set_rect (CFPlus::Map self, int x0, int y0, uint8_t *data)
1681 root 1.42 PPCODE:
1682     {
1683     int x, y, z;
1684 root 1.48 int w, h;
1685 root 1.42 int x1, y1;
1686    
1687     if (*data++ != 0)
1688     return; /* version mismatch */
1689    
1690 root 1.48 w = *data++ << 8; w |= *data++;
1691     h = *data++ << 8; h |= *data++;
1692 root 1.42
1693     // we need to do this 'cause we don't keep an absolute coord system for rows
1694 root 1.55 // TODO: treat rows as we treat columns
1695 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1696     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1697    
1698     x0 += self->x - self->ox;
1699     y0 += self->y - self->oy;
1700    
1701     x1 = x0 + w;
1702     y1 = y0 + h;
1703    
1704     for (y = y0; y < y1; y++)
1705     {
1706     maprow *row = map_get_row (self, y);
1707    
1708     for (x = x0; x < x1; x++)
1709     {
1710     uint8_t flags = *data++;
1711    
1712     if (flags)
1713     {
1714     mapface face[3] = { 0, 0, 0 };
1715    
1716     mapcell *cell = row_get_cell (row, x);
1717    
1718     if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; }
1719     if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; }
1720     if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; }
1721    
1722 root 1.143 if (cell->darkness == 0)
1723 root 1.42 {
1724 root 1.142 cell->darkness = 0;
1725 root 1.42
1726     for (z = 0; z <= 2; z++)
1727     {
1728     cell->face[z] = face[z];
1729    
1730     if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name))
1731     XPUSHs (sv_2mortal (newSViv (face[z])));
1732     }
1733     }
1734     }
1735     }
1736     }
1737     }
1738    
1739 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixChunk
1740 root 1.52
1741 root 1.133 CFPlus::MixChunk
1742 root 1.52 new_from_file (SV *class, char *path)
1743     CODE:
1744     RETVAL = Mix_LoadWAV (path);
1745     OUTPUT:
1746     RETVAL
1747    
1748     void
1749 root 1.133 DESTROY (CFPlus::MixChunk self)
1750 root 1.52 CODE:
1751     Mix_FreeChunk (self);
1752    
1753     int
1754 root 1.133 volume (CFPlus::MixChunk self, int volume = -1)
1755 root 1.52 CODE:
1756     RETVAL = Mix_VolumeChunk (self, volume);
1757     OUTPUT:
1758     RETVAL
1759    
1760     int
1761 root 1.133 play (CFPlus::MixChunk self, int channel = -1, int loops = 0, int ticks = -1)
1762 root 1.52 CODE:
1763     RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
1764     OUTPUT:
1765     RETVAL
1766    
1767 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixMusic
1768 root 1.52
1769     int
1770     volume (int volume = -1)
1771     CODE:
1772     RETVAL = Mix_VolumeMusic (volume);
1773     OUTPUT:
1774     RETVAL
1775    
1776 root 1.133 CFPlus::MixMusic
1777 root 1.52 new_from_file (SV *class, char *path)
1778     CODE:
1779     RETVAL = Mix_LoadMUS (path);
1780     OUTPUT:
1781     RETVAL
1782    
1783     void
1784 root 1.133 DESTROY (CFPlus::MixMusic self)
1785 root 1.52 CODE:
1786     Mix_FreeMusic (self);
1787    
1788     int
1789 root 1.133 play (CFPlus::MixMusic self, int loops = -1)
1790 root 1.52 CODE:
1791     RETVAL = Mix_PlayMusic (self, loops);
1792     OUTPUT:
1793     RETVAL
1794    
1795 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::OpenGL
1796 root 1.54
1797     BOOT:
1798     {
1799 root 1.133 HV *stash = gv_stashpv ("CFPlus::OpenGL", 1);
1800 root 1.54 static const struct {
1801     const char *name;
1802     IV iv;
1803     } *civ, const_iv[] = {
1804     # define const_iv(name) { # name, (IV)name }
1805     const_iv (GL_COLOR_MATERIAL),
1806     const_iv (GL_SMOOTH),
1807     const_iv (GL_FLAT),
1808 root 1.69 const_iv (GL_DITHER),
1809 root 1.54 const_iv (GL_BLEND),
1810 root 1.89 const_iv (GL_CULL_FACE),
1811 root 1.69 const_iv (GL_SCISSOR_TEST),
1812 root 1.89 const_iv (GL_DEPTH_TEST),
1813     const_iv (GL_ALPHA_TEST),
1814     const_iv (GL_NORMALIZE),
1815     const_iv (GL_RESCALE_NORMAL),
1816 root 1.119 const_iv (GL_FRONT),
1817     const_iv (GL_BACK),
1818 root 1.54 const_iv (GL_AND),
1819 root 1.67 const_iv (GL_ONE),
1820     const_iv (GL_ZERO),
1821 root 1.54 const_iv (GL_SRC_ALPHA),
1822 root 1.104 const_iv (GL_DST_ALPHA),
1823 root 1.54 const_iv (GL_ONE_MINUS_SRC_ALPHA),
1824 root 1.67 const_iv (GL_ONE_MINUS_DST_ALPHA),
1825 root 1.104 const_iv (GL_SRC_ALPHA_SATURATE),
1826 root 1.54 const_iv (GL_RGB),
1827     const_iv (GL_RGBA),
1828 root 1.115 const_iv (GL_RGBA4),
1829     const_iv (GL_RGBA8),
1830     const_iv (GL_RGB5_A1),
1831 root 1.54 const_iv (GL_UNSIGNED_BYTE),
1832 root 1.89 const_iv (GL_UNSIGNED_SHORT),
1833     const_iv (GL_UNSIGNED_INT),
1834 root 1.54 const_iv (GL_ALPHA),
1835 root 1.86 const_iv (GL_INTENSITY),
1836 root 1.76 const_iv (GL_LUMINANCE),
1837 root 1.86 const_iv (GL_LUMINANCE_ALPHA),
1838 root 1.54 const_iv (GL_FLOAT),
1839     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1840     const_iv (GL_COMPILE),
1841     const_iv (GL_TEXTURE_1D),
1842     const_iv (GL_TEXTURE_2D),
1843     const_iv (GL_TEXTURE_ENV),
1844     const_iv (GL_TEXTURE_MAG_FILTER),
1845     const_iv (GL_TEXTURE_MIN_FILTER),
1846     const_iv (GL_TEXTURE_ENV_MODE),
1847     const_iv (GL_TEXTURE_WRAP_S),
1848     const_iv (GL_TEXTURE_WRAP_T),
1849 root 1.98 const_iv (GL_REPEAT),
1850 root 1.54 const_iv (GL_CLAMP),
1851 root 1.98 const_iv (GL_CLAMP_TO_EDGE),
1852 root 1.54 const_iv (GL_NEAREST),
1853     const_iv (GL_LINEAR),
1854 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
1855     const_iv (GL_LINEAR_MIPMAP_NEAREST),
1856     const_iv (GL_NEAREST_MIPMAP_LINEAR),
1857     const_iv (GL_LINEAR_MIPMAP_LINEAR),
1858     const_iv (GL_GENERATE_MIPMAP),
1859 root 1.54 const_iv (GL_MODULATE),
1860 root 1.69 const_iv (GL_DECAL),
1861 root 1.54 const_iv (GL_REPLACE),
1862 root 1.89 const_iv (GL_DEPTH_BUFFER_BIT),
1863 root 1.54 const_iv (GL_COLOR_BUFFER_BIT),
1864     const_iv (GL_PROJECTION),
1865     const_iv (GL_MODELVIEW),
1866     const_iv (GL_COLOR_LOGIC_OP),
1867 root 1.69 const_iv (GL_SEPARABLE_2D),
1868 root 1.54 const_iv (GL_CONVOLUTION_2D),
1869     const_iv (GL_CONVOLUTION_BORDER_MODE),
1870     const_iv (GL_CONSTANT_BORDER),
1871     const_iv (GL_LINES),
1872 root 1.138 const_iv (GL_LINE_STRIP),
1873 root 1.89 const_iv (GL_LINE_LOOP),
1874 root 1.54 const_iv (GL_QUADS),
1875 root 1.89 const_iv (GL_QUAD_STRIP),
1876     const_iv (GL_TRIANGLES),
1877     const_iv (GL_TRIANGLE_STRIP),
1878     const_iv (GL_TRIANGLE_FAN),
1879 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1880     const_iv (GL_FASTEST),
1881 root 1.89 const_iv (GL_V2F),
1882     const_iv (GL_V3F),
1883     const_iv (GL_T2F_V3F),
1884     const_iv (GL_T2F_N3F_V3F),
1885 root 1.54 # undef const_iv
1886     };
1887    
1888     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1889     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1890     }
1891    
1892 root 1.97 char *
1893     gl_vendor ()
1894     CODE:
1895     RETVAL = (char *)glGetString (GL_VENDOR);
1896     OUTPUT:
1897     RETVAL
1898    
1899     char *
1900     gl_version ()
1901     CODE:
1902     RETVAL = (char *)glGetString (GL_VERSION);
1903     OUTPUT:
1904     RETVAL
1905    
1906     char *
1907     gl_extensions ()
1908     CODE:
1909     RETVAL = (char *)glGetString (GL_EXTENSIONS);
1910     OUTPUT:
1911     RETVAL
1912    
1913 root 1.54 int glGetError ()
1914    
1915 root 1.114 void glFinish ()
1916    
1917 root 1.54 void glClear (int mask)
1918    
1919     void glClearColor (float r, float g, float b, float a = 1.0)
1920     PROTOTYPE: @
1921    
1922     void glEnable (int cap)
1923    
1924     void glDisable (int cap)
1925    
1926     void glShadeModel (int mode)
1927    
1928     void glHint (int target, int mode)
1929    
1930     void glBlendFunc (int sfactor, int dfactor)
1931    
1932 root 1.103 void glBlendFuncSeparate (int sa, int da, int saa, int daa)
1933     CODE:
1934     gl_BlendFuncSeparate (sa, da, saa, daa);
1935    
1936 root 1.89 void glDepthMask (int flag)
1937    
1938 root 1.54 void glLogicOp (int opcode)
1939    
1940 root 1.68 void glColorMask (int red, int green, int blue, int alpha)
1941    
1942 root 1.54 void glMatrixMode (int mode)
1943    
1944     void glPushMatrix ()
1945    
1946     void glPopMatrix ()
1947    
1948     void glLoadIdentity ()
1949    
1950 root 1.119 void glDrawBuffer (int buffer)
1951    
1952     void glReadBuffer (int buffer)
1953    
1954 root 1.90 # near_ and far_ are due to microsofts buggy "c" compiler
1955     void glFrustum (double left, double right, double bottom, double top, double near_, double far_)
1956    
1957     # near_ and far_ are due to microsofts buggy "c" compiler
1958 root 1.64 void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
1959 root 1.54
1960     void glViewport (int x, int y, int width, int height)
1961    
1962 root 1.69 void glScissor (int x, int y, int width, int height)
1963    
1964 root 1.54 void glTranslate (float x, float y, float z = 0.)
1965     CODE:
1966     glTranslatef (x, y, z);
1967    
1968 root 1.62 void glScale (float x, float y, float z = 1.)
1969 root 1.54 CODE:
1970     glScalef (x, y, z);
1971    
1972     void glRotate (float angle, float x, float y, float z)
1973     CODE:
1974     glRotatef (angle, x, y, z);
1975    
1976     void glBegin (int mode)
1977    
1978     void glEnd ()
1979    
1980     void glColor (float r, float g, float b, float a = 1.0)
1981     PROTOTYPE: @
1982 root 1.103 ALIAS:
1983     glColor_premultiply = 1
1984 root 1.54 CODE:
1985 root 1.103 if (ix)
1986     {
1987     r *= a;
1988     g *= a;
1989     b *= a;
1990     }
1991 root 1.90 // microsoft visual "c" rounds instead of truncating...
1992 root 1.130 glColor4f (r, g, b, a);
1993 root 1.54
1994 root 1.89 void glInterleavedArrays (int format, int stride, char *data)
1995    
1996     void glDrawElements (int mode, int count, int type, char *indices)
1997    
1998     # 1.2 void glDrawRangeElements (int mode, int start, int end
1999    
2000 root 1.91 void glRasterPos (float x, float y, float z = 0.)
2001     CODE:
2002     glRasterPos3f (0, 0, z);
2003     glBitmap (0, 0, 0, 0, x, y, 0);
2004    
2005 root 1.54 void glVertex (float x, float y, float z = 0.)
2006     CODE:
2007     glVertex3f (x, y, z);
2008    
2009     void glTexCoord (float s, float t)
2010     CODE:
2011     glTexCoord2f (s, t);
2012    
2013     void glTexEnv (int target, int pname, float param)
2014     CODE:
2015     glTexEnvf (target, pname, param);
2016    
2017     void glTexParameter (int target, int pname, float param)
2018     CODE:
2019     glTexParameterf (target, pname, param);
2020    
2021     void glBindTexture (int target, int name)
2022    
2023     void glConvolutionParameter (int target, int pname, float params)
2024     CODE:
2025 root 1.103 if (gl.ConvolutionParameterf)
2026     gl.ConvolutionParameterf (target, pname, params);
2027 root 1.54
2028     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
2029 root 1.64 CODE:
2030 root 1.103 if (gl.ConvolutionFilter2D)
2031     gl.ConvolutionFilter2D (target, internalformat, width, height, format, type, data);
2032 root 1.54
2033 root 1.69 void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
2034     CODE:
2035 root 1.103 if (gl.SeparableFilter2D)
2036     gl.SeparableFilter2D (target, internalformat, width, height, format, type, row, column);
2037 root 1.69
2038 root 1.54 void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
2039    
2040     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
2041    
2042 root 1.91 void glDrawPixels (int width, int height, int format, int type, char *pixels)
2043 root 1.68
2044     void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
2045    
2046 root 1.54 int glGenTexture ()
2047     CODE:
2048     {
2049     GLuint name;
2050     glGenTextures (1, &name);
2051     RETVAL = name;
2052     }
2053     OUTPUT:
2054     RETVAL
2055    
2056     void glDeleteTexture (int name)
2057     CODE:
2058     {
2059     GLuint name_ = name;
2060     glDeleteTextures (1, &name_);
2061     }
2062    
2063     int glGenList ()
2064     CODE:
2065     RETVAL = glGenLists (1);
2066     OUTPUT:
2067     RETVAL
2068    
2069     void glDeleteList (int list)
2070     CODE:
2071     glDeleteLists (list, 1);
2072    
2073     void glNewList (int list, int mode = GL_COMPILE)
2074    
2075     void glEndList ()
2076    
2077     void glCallList (int list)
2078