ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.166
Committed: Fri Dec 8 15:07:08 2006 UTC (17 years, 5 months ago) by root
Branch: MAIN
Changes since 1.165: +1 -2 lines
Log Message:
less hacky equals more correct

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