ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.164
Committed: Tue Nov 7 22:41:27 2006 UTC (17 years, 6 months ago) by root
Branch: MAIN
Changes since 1.163: +28 -34 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.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     RETVAL = index;
1055     }
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.135 render (CFPlus::Layout self, float x, float y, int flags = 0)
1074 root 1.14 PPCODE:
1075 root 1.124 pango_opengl_render_layout_subpixel (
1076     self->pl,
1077     x * PANGO_SCALE, y * PANGO_SCALE,
1078 root 1.135 self->r, self->g, self->b, self->a,
1079     flags
1080 root 1.124 );
1081 root 1.11
1082 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Texture
1083 root 1.11
1084     void
1085 root 1.113 pad2pot (SV *data_, SV *w_, SV *h_)
1086     CODE:
1087     {
1088     int ow = SvIV (w_);
1089     int oh = SvIV (h_);
1090    
1091     if (ow && oh)
1092     {
1093     int nw = minpot (ow);
1094     int nh = minpot (oh);
1095    
1096     if (nw != ow || nh != oh)
1097     {
1098     if (SvOK (data_))
1099     {
1100     STRLEN datalen;
1101     char *data = SvPVbyte (data_, datalen);
1102     int bpp = datalen / (ow * oh);
1103     SV *result_ = sv_2mortal (newSV (nw * nh * bpp));
1104    
1105     SvPOK_only (result_);
1106     SvCUR_set (result_, nw * nh * bpp);
1107    
1108     memset (SvPVX (result_), 0, nw * nh * bpp);
1109     while (oh--)
1110     memcpy (SvPVX (result_) + oh * nw * bpp, data + oh * ow * bpp, ow * bpp);
1111    
1112     sv_setsv (data_, result_);
1113     }
1114    
1115     sv_setiv (w_, nw);
1116     sv_setiv (h_, nh);
1117     }
1118     }
1119     }
1120    
1121     void
1122 root 1.114 draw_quad (SV *self, float x, float y, float w = 0., float h = 0.)
1123 root 1.12 PROTOTYPE: $$$;$$
1124 root 1.76 ALIAS:
1125     draw_quad_alpha = 1
1126     draw_quad_alpha_premultiplied = 2
1127 root 1.11 CODE:
1128     {
1129 root 1.12 HV *hv = (HV *)SvRV (self);
1130 root 1.37 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
1131     float t = SvNV (*hv_fetch (hv, "t", 1, 1));
1132 root 1.12 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
1133    
1134     if (items < 5)
1135     {
1136 root 1.18 w = SvNV (*hv_fetch (hv, "w", 1, 1));
1137     h = SvNV (*hv_fetch (hv, "h", 1, 1));
1138 root 1.12 }
1139    
1140 root 1.76 if (ix)
1141     {
1142     glEnable (GL_BLEND);
1143 root 1.103
1144     if (ix == 2)
1145     glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1146     else
1147     gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1148 root 1.104 GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1149 root 1.103
1150 root 1.86 glEnable (GL_ALPHA_TEST);
1151     glAlphaFunc (GL_GREATER, 0.01f);
1152 root 1.76 }
1153    
1154 root 1.12 glBindTexture (GL_TEXTURE_2D, name);
1155 root 1.76
1156 root 1.12 glBegin (GL_QUADS);
1157 root 1.37 glTexCoord2f (0, 0); glVertex2f (x , y );
1158     glTexCoord2f (0, t); glVertex2f (x , y + h);
1159     glTexCoord2f (s, t); glVertex2f (x + w, y + h);
1160     glTexCoord2f (s, 0); glVertex2f (x + w, y );
1161 root 1.12 glEnd ();
1162 root 1.76
1163     if (ix)
1164 root 1.86 {
1165     glDisable (GL_ALPHA_TEST);
1166     glDisable (GL_BLEND);
1167     }
1168 root 1.11 }
1169 root 1.28
1170 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Map
1171 root 1.28
1172 root 1.133 CFPlus::Map
1173 root 1.164 new (SV *class)
1174 root 1.28 CODE:
1175     New (0, RETVAL, 1, struct map);
1176 root 1.42 RETVAL->x = 0;
1177     RETVAL->y = 0;
1178 root 1.164 RETVAL->w = 0;
1179     RETVAL->h = 0;
1180 root 1.42 RETVAL->ox = 0;
1181     RETVAL->oy = 0;
1182 root 1.30 RETVAL->faces = 8192;
1183     Newz (0, RETVAL->face, RETVAL->faces, mapface);
1184 root 1.42 RETVAL->texs = 8192;
1185     Newz (0, RETVAL->tex, RETVAL->texs, maptex);
1186 root 1.28 RETVAL->rows = 0;
1187     RETVAL->row = 0;
1188     OUTPUT:
1189     RETVAL
1190    
1191     void
1192 root 1.133 DESTROY (CFPlus::Map self)
1193 root 1.28 CODE:
1194     {
1195 root 1.30 map_clear (self);
1196 root 1.28 Safefree (self->face);
1197 root 1.111 Safefree (self->tex);
1198 root 1.29 Safefree (self);
1199     }
1200    
1201     void
1202 root 1.164 resize (CFPlus::Map self, int map_width, int map_height)
1203     CODE:
1204     self->w = map_width;
1205     self->h = map_height;
1206    
1207     void
1208 root 1.133 clear (CFPlus::Map self)
1209 root 1.30 CODE:
1210     map_clear (self);
1211    
1212     void
1213 root 1.133 set_face (CFPlus::Map self, int face, int texid)
1214 root 1.29 CODE:
1215     {
1216 root 1.42 while (self->faces <= face)
1217 root 1.28 {
1218 root 1.30 Append (mapface, self->face, self->faces, self->faces);
1219 root 1.29 self->faces *= 2;
1220     }
1221 root 1.28
1222 root 1.42 self->face [face] = texid;
1223     }
1224    
1225     void
1226 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)
1227 root 1.42 CODE:
1228     {
1229     while (self->texs <= texid)
1230     {
1231     Append (maptex, self->tex, self->texs, self->texs);
1232     self->texs *= 2;
1233     }
1234    
1235 root 1.48 {
1236     maptex *tex = self->tex + texid;
1237 root 1.39
1238 root 1.48 tex->name = name;
1239     tex->w = w;
1240     tex->h = h;
1241     tex->s = s;
1242     tex->t = t;
1243     tex->r = r;
1244     tex->g = g;
1245     tex->b = b;
1246     tex->a = a;
1247     }
1248 root 1.95
1249     // somewhat hackish, but for textures that require it, it really
1250     // improves the look, and most others don't suffer.
1251     glBindTexture (GL_TEXTURE_2D, name);
1252 root 1.99 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1253     //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1254     // use uglier nearest interpolation because linear suffers
1255     // from transparent color bleeding and ugly wrapping effects.
1256     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1257 root 1.29 }
1258    
1259 root 1.42 int
1260 root 1.133 ox (CFPlus::Map self)
1261 root 1.42 ALIAS:
1262     oy = 1
1263 root 1.101 x = 2
1264     y = 3
1265 root 1.102 w = 4
1266     h = 5
1267 root 1.42 CODE:
1268     switch (ix)
1269     {
1270     case 0: RETVAL = self->ox; break;
1271     case 1: RETVAL = self->oy; break;
1272 root 1.101 case 2: RETVAL = self->x; break;
1273     case 3: RETVAL = self->y; break;
1274 root 1.102 case 4: RETVAL = self->w; break;
1275     case 5: RETVAL = self->h; break;
1276 root 1.42 }
1277     OUTPUT:
1278     RETVAL
1279    
1280 root 1.29 void
1281 root 1.133 scroll (CFPlus::Map self, int dx, int dy)
1282 root 1.43 CODE:
1283     {
1284 root 1.44 if (dx > 0)
1285 root 1.154 map_blank (self, self->x, self->y, dx, self->h);
1286 root 1.44 else if (dx < 0)
1287 root 1.154 map_blank (self, self->x + self->w + dx + 1, self->y, -dx, self->h);
1288 root 1.44
1289     if (dy > 0)
1290 root 1.154 map_blank (self, self->x, self->y, self->w, dy);
1291 root 1.44 else if (dy < 0)
1292 root 1.154 map_blank (self, self->x, self->y + self->h + dy + 1, self->w, -dy);
1293 root 1.43
1294 root 1.44 self->ox += dx; self->x += dx;
1295     self->oy += dy; self->y += dy;
1296 root 1.43
1297     while (self->y < 0)
1298     {
1299     Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
1300    
1301     self->rows += MAP_EXTEND_Y;
1302     self->y += MAP_EXTEND_Y;
1303     }
1304 root 1.44 }
1305 root 1.43
1306 root 1.44 void
1307 root 1.141 map1a_update (CFPlus::Map self, SV *data_, int extmap)
1308 root 1.44 CODE:
1309     {
1310 root 1.30 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1311     uint8_t *data_end = (uint8_t *)SvEND (data_);
1312 root 1.48 mapcell *cell;
1313     int x, y, flags;
1314 root 1.43
1315 root 1.150 while (data < data_end - 1)
1316 root 1.29 {
1317 root 1.48 flags = (data [0] << 8) + data [1]; data += 2;
1318 root 1.30
1319 root 1.120 x = self->x + ((flags >> 10) & 63);
1320     y = self->y + ((flags >> 4) & 63);
1321 root 1.29
1322 root 1.48 cell = map_get_cell (self, x, y);
1323 root 1.29
1324     if (flags & 15)
1325     {
1326 root 1.142 if (!cell->darkness)
1327 root 1.29 {
1328 root 1.154 memset (cell, 0, sizeof (*cell));
1329 root 1.142 cell->darkness = 256;
1330 root 1.29 }
1331 root 1.45
1332 root 1.142 //TODO: don't trust server data to be in-range(!)
1333    
1334 root 1.141 if (flags & 8)
1335     {
1336     if (extmap)
1337     {
1338     uint8_t ext, cmd;
1339    
1340     do
1341     {
1342     ext = *data++;
1343 root 1.144 cmd = ext & 0x3f;
1344 root 1.141
1345 root 1.147 if (cmd < 4)
1346 root 1.142 cell->darkness = 255 - ext * 64 + 1;
1347 root 1.147 else if (cmd == 5) // health
1348     {
1349     cell->stat_width = 1;
1350     cell->stat_hp = *data++;
1351     }
1352     else if (cmd == 6) // monster width
1353     cell->stat_width = *data++ + 1;
1354 root 1.153 else if (cmd == 0x47) // monster width
1355     {
1356     if (*data == 4)
1357     ; // decode player tag
1358    
1359     data += *data + 1;
1360     }
1361     else if (cmd == 8) // cell flags
1362     cell->flags = *data++;
1363 root 1.144 else if (ext & 0x40) // unknown, multibyte => skip
1364     data += *data + 1;
1365 root 1.147 else
1366     data++;
1367 root 1.141 }
1368 root 1.147 while (ext & 0x80);
1369 root 1.141 }
1370     else
1371 root 1.142 cell->darkness = *data++ + 1;
1372 root 1.141 }
1373 root 1.29
1374     if (flags & 4)
1375     {
1376 root 1.42 cell->face [0] = self->face [(data [0] << 8) + data [1]]; data += 2;
1377 root 1.29 }
1378    
1379     if (flags & 2)
1380     {
1381 root 1.42 cell->face [1] = self->face [(data [0] << 8) + data [1]]; data += 2;
1382 root 1.29 }
1383    
1384     if (flags & 1)
1385     {
1386 root 1.42 cell->face [2] = self->face [(data [0] << 8) + data [1]]; data += 2;
1387 root 1.29 }
1388     }
1389     else
1390 root 1.155 cell->darkness = 0;
1391 root 1.29 }
1392 root 1.28 }
1393    
1394 root 1.40 SV *
1395 root 1.133 mapmap (CFPlus::Map self, int x0, int y0, int w, int h)
1396 root 1.40 CODE:
1397     {
1398 root 1.55 int x1, x;
1399     int y1, y;
1400 root 1.40 int z;
1401     SV *map_sv = newSV (w * h * sizeof (uint32_t));
1402     uint32_t *map = (uint32_t *)SvPVX (map_sv);
1403    
1404     SvPOK_only (map_sv);
1405     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
1406    
1407 root 1.55 x0 += self->x; x1 = x0 + w;
1408     y0 += self->y; y1 = y0 + h;
1409 root 1.40
1410     for (y = y0; y < y1; y++)
1411     {
1412     maprow *row = 0 <= y && y < self->rows
1413     ? self->row + y
1414     : 0;
1415    
1416     for (x = x0; x < x1; x++)
1417     {
1418     int r = 32, g = 32, b = 32, a = 192;
1419    
1420     if (row && row->c0 <= x && x < row->c1)
1421     {
1422     mapcell *cell = row->col + (x - row->c0);
1423    
1424     for (z = 0; z <= 0; z++)
1425     {
1426 root 1.42 mapface face = cell->face [z];
1427 root 1.40
1428     if (face)
1429     {
1430 root 1.42 maptex tex = self->tex [face];
1431 root 1.40 int a0 = 255 - tex.a;
1432     int a1 = tex.a;
1433    
1434     r = (r * a0 + tex.r * a1) / 255;
1435     g = (g * a0 + tex.g * a1) / 255;
1436     b = (b * a0 + tex.b * a1) / 255;
1437     a = (a * a0 + tex.a * a1) / 255;
1438     }
1439     }
1440     }
1441    
1442     *map++ = (r )
1443     | (g << 8)
1444     | (b << 16)
1445     | (a << 24);
1446     }
1447     }
1448    
1449     RETVAL = map_sv;
1450     }
1451     OUTPUT:
1452     RETVAL
1453    
1454 root 1.30 void
1455 root 1.164 draw (CFPlus::Map self, int mx, int my, int sw, int sh)
1456 root 1.116 CODE:
1457 root 1.30 {
1458 root 1.48 int x, y, z;
1459     int last_name;
1460     mapface face;
1461    
1462 root 1.30 glColor4ub (255, 255, 255, 255);
1463    
1464 root 1.117 glEnable (GL_BLEND);
1465 root 1.30 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1466     glEnable (GL_TEXTURE_2D);
1467     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1468    
1469 root 1.48 glBegin (GL_QUADS);
1470 root 1.30
1471 root 1.48 last_name = 0;
1472 root 1.30
1473 root 1.164 mx += self->x;
1474     my += self->y;
1475    
1476 root 1.30 for (z = 0; z < 3; z++)
1477     for (y = 0; y < sh; y++)
1478 root 1.164 if (0 <= y + my && y + my < self->rows)
1479 root 1.30 {
1480 root 1.164 maprow *row = self->row + (y + my);
1481 root 1.30
1482     for (x = 0; x < sw; x++)
1483 root 1.164 if (row->c0 <= x + mx && x + mx < row->c1)
1484 root 1.30 {
1485 root 1.164 mapcell *cell = row->col + (x + mx - row->c0);
1486 root 1.32
1487 root 1.48 face = cell->face [z];
1488 root 1.30
1489 root 1.145 if (face && face < self->texs)
1490 root 1.30 {
1491 root 1.42 maptex tex = self->tex [face];
1492 root 1.30 int px = (x + 1) * 32 - tex.w;
1493     int py = (y + 1) * 32 - tex.h;
1494    
1495     if (last_name != tex.name)
1496     {
1497     glEnd ();
1498 root 1.153 glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1499 root 1.30 glBegin (GL_QUADS);
1500     }
1501    
1502     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1503     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1504     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1505     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1506     }
1507 root 1.153
1508     if (cell->flags && z == 2)
1509     {
1510     if (cell->flags & 1)
1511     {
1512     maptex tex = self->tex [1];
1513     int px = (x + 1) * 32 - tex.w + 2;
1514     int py = (y + 1) * 32 - tex.h - 6;
1515    
1516     glEnd ();
1517     glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1518     glBegin (GL_QUADS);
1519    
1520     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1521     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1522     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1523     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1524     }
1525     }
1526 root 1.30 }
1527     }
1528    
1529     glEnd ();
1530 root 1.32
1531 root 1.34 glDisable (GL_TEXTURE_2D);
1532 root 1.152 glDisable (GL_BLEND);
1533 root 1.143
1534 root 1.145 // top layer: overlays such as the health bar
1535 root 1.143 for (y = 0; y < sh; y++)
1536 root 1.164 if (0 <= y + my && y + my < self->rows)
1537 root 1.143 {
1538 root 1.164 maprow *row = self->row + (y + my);
1539 root 1.143
1540     for (x = 0; x < sw; x++)
1541 root 1.164 if (row->c0 <= x + mx && x + mx < row->c1)
1542 root 1.143 {
1543 root 1.164 mapcell *cell = row->col + (x + mx - row->c0);
1544 root 1.143
1545     int px = x * 32;
1546     int py = y * 32;
1547    
1548     if (cell->stat_hp)
1549     {
1550 root 1.147 int width = cell->stat_width * 32;
1551     int thick = sh / 28 + 1 + cell->stat_width;
1552 root 1.143
1553 root 1.152 glColor3ub (0, 0, 0);
1554 root 1.151 glRectf (px + 1, py - thick - 2,
1555     px + width - 1, py);
1556 root 1.147
1557 root 1.152 glColor3ub (cell->stat_hp, 255 - cell->stat_hp, 0);
1558 root 1.147 glRectf (px + 2,
1559 root 1.151 py - thick - 1,
1560     px + width - 2 - cell->stat_hp * (width - 4) / 255, py - 1);
1561 root 1.143 }
1562     }
1563     }
1564 root 1.116 }
1565    
1566     void
1567 root 1.133 draw_magicmap (CFPlus::Map self, int dx, int dy, int w, int h, unsigned char *data)
1568 root 1.117 CODE:
1569     {
1570     static float color[16][3] = {
1571 root 1.123 { 0.00F, 0.00F, 0.00F },
1572     { 1.00F, 1.00F, 1.00F },
1573     { 0.00F, 0.00F, 0.55F },
1574     { 1.00F, 0.00F, 0.00F },
1575    
1576     { 1.00F, 0.54F, 0.00F },
1577     { 0.11F, 0.56F, 1.00F },
1578     { 0.93F, 0.46F, 0.00F },
1579     { 0.18F, 0.54F, 0.34F },
1580    
1581     { 0.56F, 0.73F, 0.56F },
1582     { 0.80F, 0.80F, 0.80F },
1583     { 0.55F, 0.41F, 0.13F },
1584     { 0.99F, 0.77F, 0.26F },
1585    
1586     { 0.74F, 0.65F, 0.41F },
1587    
1588     { 0.00F, 1.00F, 1.00F },
1589     { 1.00F, 0.00F, 1.00F },
1590     { 1.00F, 1.00F, 0.00F },
1591 root 1.117 };
1592    
1593     int x, y;
1594    
1595     glEnable (GL_TEXTURE_2D);
1596     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1597     glEnable (GL_BLEND);
1598     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1599     glBegin (GL_QUADS);
1600    
1601     for (y = 0; y < h; y++)
1602     for (x = 0; x < w; x++)
1603     {
1604     unsigned char m = data [x + y * w];
1605    
1606 root 1.118 if (m)
1607     {
1608     float *c = color [m & 15];
1609    
1610     float tx1 = m & 0x40 ? 0.5 : 0.;
1611     float tx2 = tx1 + 0.5;
1612    
1613     glColor4f (c[0], c[1], c[2], 0.75);
1614     glTexCoord2f (tx1, 0.); glVertex2i (x , y );
1615     glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
1616     glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
1617     glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
1618     }
1619 root 1.117 }
1620    
1621     glEnd ();
1622     glDisable (GL_BLEND);
1623     glDisable (GL_TEXTURE_2D);
1624     }
1625    
1626     void
1627 root 1.164 fow_texture (CFPlus::Map self, int mx, int my, int sw, int sh)
1628 root 1.116 PPCODE:
1629     {
1630     int x, y;
1631     int sw4 = (sw + 3) & ~3;
1632     SV *darkness_sv = sv_2mortal (newSV (sw4 * sh));
1633     uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv);
1634    
1635     memset (darkness, 255, sw4 * sh);
1636     SvPOK_only (darkness_sv);
1637     SvCUR_set (darkness_sv, sw4 * sh);
1638    
1639 root 1.164 mx += self->x;
1640     my += self->y;
1641 root 1.116
1642     for (y = 0; y < sh; y++)
1643 root 1.164 if (0 <= y + my && y + my < self->rows)
1644 root 1.116 {
1645 root 1.164 maprow *row = self->row + (y + my);
1646 root 1.116
1647     for (x = 0; x < sw; x++)
1648 root 1.164 if (row->c0 <= x + mx && x + mx < row->c1)
1649 root 1.116 {
1650 root 1.164 mapcell *cell = row->col + (x + mx - row->c0);
1651 root 1.116
1652 root 1.142 darkness[y * sw4 + x] = cell->darkness
1653 root 1.143 ? 255 - (cell->darkness - 1)
1654 root 1.142 : 255 - FOW_DARKNESS;
1655 root 1.116 }
1656     }
1657 root 1.34
1658 root 1.32 EXTEND (SP, 3);
1659     PUSHs (sv_2mortal (newSViv (sw4)));
1660     PUSHs (sv_2mortal (newSViv (sh)));
1661     PUSHs (darkness_sv);
1662 root 1.30 }
1663    
1664 root 1.42 SV *
1665 root 1.133 get_rect (CFPlus::Map self, int x0, int y0, int w, int h)
1666 root 1.42 CODE:
1667     {
1668     int x, y, x1, y1;
1669     SV *data_sv = newSV (w * h * 7 + 5);
1670     uint8_t *data = (uint8_t *)SvPVX (data_sv);
1671    
1672     *data++ = 0; /* version 0 format */
1673     *data++ = w >> 8; *data++ = w;
1674     *data++ = h >> 8; *data++ = h;
1675    
1676     // we need to do this 'cause we don't keep an absolute coord system for rows
1677 root 1.55 // TODO: treat rows as we treat columns
1678 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1679     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1680    
1681     x0 += self->x - self->ox;
1682     y0 += self->y - self->oy;
1683    
1684     x1 = x0 + w;
1685     y1 = y0 + h;
1686    
1687     for (y = y0; y < y1; y++)
1688     {
1689     maprow *row = 0 <= y && y < self->rows
1690     ? self->row + y
1691     : 0;
1692    
1693     for (x = x0; x < x1; x++)
1694     {
1695     if (row && row->c0 <= x && x < row->c1)
1696     {
1697     mapcell *cell = row->col + (x - row->c0);
1698     uint8_t flags = 0;
1699    
1700     if (cell->face [0]) flags |= 1;
1701     if (cell->face [1]) flags |= 2;
1702     if (cell->face [2]) flags |= 4;
1703    
1704     *data++ = flags;
1705    
1706     if (flags & 1)
1707     {
1708     *data++ = cell->face [0] >> 8;
1709     *data++ = cell->face [0];
1710     }
1711    
1712     if (flags & 2)
1713     {
1714     *data++ = cell->face [1] >> 8;
1715     *data++ = cell->face [1];
1716     }
1717    
1718     if (flags & 4)
1719     {
1720     *data++ = cell->face [2] >> 8;
1721     *data++ = cell->face [2];
1722     }
1723     }
1724     else
1725     *data++ = 0;
1726     }
1727     }
1728    
1729     SvPOK_only (data_sv);
1730     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
1731     RETVAL = data_sv;
1732     }
1733     OUTPUT:
1734     RETVAL
1735    
1736     void
1737 root 1.133 set_rect (CFPlus::Map self, int x0, int y0, uint8_t *data)
1738 root 1.42 PPCODE:
1739     {
1740     int x, y, z;
1741 root 1.48 int w, h;
1742 root 1.42 int x1, y1;
1743    
1744     if (*data++ != 0)
1745     return; /* version mismatch */
1746    
1747 root 1.48 w = *data++ << 8; w |= *data++;
1748     h = *data++ << 8; h |= *data++;
1749 root 1.42
1750     // we need to do this 'cause we don't keep an absolute coord system for rows
1751 root 1.55 // TODO: treat rows as we treat columns
1752 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1753     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1754    
1755     x0 += self->x - self->ox;
1756     y0 += self->y - self->oy;
1757    
1758     x1 = x0 + w;
1759     y1 = y0 + h;
1760    
1761     for (y = y0; y < y1; y++)
1762     {
1763     maprow *row = map_get_row (self, y);
1764    
1765     for (x = x0; x < x1; x++)
1766     {
1767     uint8_t flags = *data++;
1768    
1769     if (flags)
1770     {
1771     mapface face[3] = { 0, 0, 0 };
1772    
1773     mapcell *cell = row_get_cell (row, x);
1774    
1775     if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; }
1776     if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; }
1777     if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; }
1778    
1779 root 1.143 if (cell->darkness == 0)
1780 root 1.42 {
1781 root 1.142 cell->darkness = 0;
1782 root 1.42
1783     for (z = 0; z <= 2; z++)
1784     {
1785     cell->face[z] = face[z];
1786    
1787     if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name))
1788     XPUSHs (sv_2mortal (newSViv (face[z])));
1789     }
1790     }
1791     }
1792     }
1793     }
1794     }
1795    
1796 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixChunk
1797 root 1.52
1798 root 1.133 CFPlus::MixChunk
1799 root 1.52 new_from_file (SV *class, char *path)
1800     CODE:
1801     RETVAL = Mix_LoadWAV (path);
1802     OUTPUT:
1803     RETVAL
1804    
1805     void
1806 root 1.133 DESTROY (CFPlus::MixChunk self)
1807 root 1.52 CODE:
1808     Mix_FreeChunk (self);
1809    
1810     int
1811 root 1.133 volume (CFPlus::MixChunk self, int volume = -1)
1812 root 1.52 CODE:
1813     RETVAL = Mix_VolumeChunk (self, volume);
1814     OUTPUT:
1815     RETVAL
1816    
1817     int
1818 root 1.133 play (CFPlus::MixChunk self, int channel = -1, int loops = 0, int ticks = -1)
1819 root 1.52 CODE:
1820     RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
1821     OUTPUT:
1822     RETVAL
1823    
1824 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixMusic
1825 root 1.52
1826     int
1827     volume (int volume = -1)
1828     CODE:
1829     RETVAL = Mix_VolumeMusic (volume);
1830     OUTPUT:
1831     RETVAL
1832    
1833 root 1.133 CFPlus::MixMusic
1834 root 1.52 new_from_file (SV *class, char *path)
1835     CODE:
1836     RETVAL = Mix_LoadMUS (path);
1837     OUTPUT:
1838     RETVAL
1839    
1840     void
1841 root 1.133 DESTROY (CFPlus::MixMusic self)
1842 root 1.52 CODE:
1843     Mix_FreeMusic (self);
1844    
1845     int
1846 root 1.133 play (CFPlus::MixMusic self, int loops = -1)
1847 root 1.52 CODE:
1848     RETVAL = Mix_PlayMusic (self, loops);
1849     OUTPUT:
1850     RETVAL
1851    
1852 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::OpenGL
1853 root 1.54
1854     BOOT:
1855     {
1856 root 1.133 HV *stash = gv_stashpv ("CFPlus::OpenGL", 1);
1857 root 1.54 static const struct {
1858     const char *name;
1859     IV iv;
1860     } *civ, const_iv[] = {
1861     # define const_iv(name) { # name, (IV)name }
1862     const_iv (GL_COLOR_MATERIAL),
1863     const_iv (GL_SMOOTH),
1864     const_iv (GL_FLAT),
1865 root 1.69 const_iv (GL_DITHER),
1866 root 1.54 const_iv (GL_BLEND),
1867 root 1.89 const_iv (GL_CULL_FACE),
1868 root 1.69 const_iv (GL_SCISSOR_TEST),
1869 root 1.89 const_iv (GL_DEPTH_TEST),
1870     const_iv (GL_ALPHA_TEST),
1871     const_iv (GL_NORMALIZE),
1872     const_iv (GL_RESCALE_NORMAL),
1873 root 1.119 const_iv (GL_FRONT),
1874     const_iv (GL_BACK),
1875 root 1.54 const_iv (GL_AND),
1876 root 1.67 const_iv (GL_ONE),
1877     const_iv (GL_ZERO),
1878 root 1.54 const_iv (GL_SRC_ALPHA),
1879 root 1.104 const_iv (GL_DST_ALPHA),
1880 root 1.54 const_iv (GL_ONE_MINUS_SRC_ALPHA),
1881 root 1.67 const_iv (GL_ONE_MINUS_DST_ALPHA),
1882 root 1.104 const_iv (GL_SRC_ALPHA_SATURATE),
1883 root 1.54 const_iv (GL_RGB),
1884     const_iv (GL_RGBA),
1885 root 1.115 const_iv (GL_RGBA4),
1886     const_iv (GL_RGBA8),
1887     const_iv (GL_RGB5_A1),
1888 root 1.54 const_iv (GL_UNSIGNED_BYTE),
1889 root 1.89 const_iv (GL_UNSIGNED_SHORT),
1890     const_iv (GL_UNSIGNED_INT),
1891 root 1.54 const_iv (GL_ALPHA),
1892 root 1.86 const_iv (GL_INTENSITY),
1893 root 1.76 const_iv (GL_LUMINANCE),
1894 root 1.86 const_iv (GL_LUMINANCE_ALPHA),
1895 root 1.54 const_iv (GL_FLOAT),
1896     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1897     const_iv (GL_COMPILE),
1898     const_iv (GL_TEXTURE_1D),
1899     const_iv (GL_TEXTURE_2D),
1900     const_iv (GL_TEXTURE_ENV),
1901     const_iv (GL_TEXTURE_MAG_FILTER),
1902     const_iv (GL_TEXTURE_MIN_FILTER),
1903     const_iv (GL_TEXTURE_ENV_MODE),
1904     const_iv (GL_TEXTURE_WRAP_S),
1905     const_iv (GL_TEXTURE_WRAP_T),
1906 root 1.98 const_iv (GL_REPEAT),
1907 root 1.54 const_iv (GL_CLAMP),
1908 root 1.98 const_iv (GL_CLAMP_TO_EDGE),
1909 root 1.54 const_iv (GL_NEAREST),
1910     const_iv (GL_LINEAR),
1911 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
1912     const_iv (GL_LINEAR_MIPMAP_NEAREST),
1913     const_iv (GL_NEAREST_MIPMAP_LINEAR),
1914     const_iv (GL_LINEAR_MIPMAP_LINEAR),
1915     const_iv (GL_GENERATE_MIPMAP),
1916 root 1.54 const_iv (GL_MODULATE),
1917 root 1.69 const_iv (GL_DECAL),
1918 root 1.54 const_iv (GL_REPLACE),
1919 root 1.89 const_iv (GL_DEPTH_BUFFER_BIT),
1920 root 1.54 const_iv (GL_COLOR_BUFFER_BIT),
1921     const_iv (GL_PROJECTION),
1922     const_iv (GL_MODELVIEW),
1923     const_iv (GL_COLOR_LOGIC_OP),
1924 root 1.69 const_iv (GL_SEPARABLE_2D),
1925 root 1.54 const_iv (GL_CONVOLUTION_2D),
1926     const_iv (GL_CONVOLUTION_BORDER_MODE),
1927     const_iv (GL_CONSTANT_BORDER),
1928     const_iv (GL_LINES),
1929 root 1.138 const_iv (GL_LINE_STRIP),
1930 root 1.89 const_iv (GL_LINE_LOOP),
1931 root 1.54 const_iv (GL_QUADS),
1932 root 1.89 const_iv (GL_QUAD_STRIP),
1933     const_iv (GL_TRIANGLES),
1934     const_iv (GL_TRIANGLE_STRIP),
1935     const_iv (GL_TRIANGLE_FAN),
1936 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1937     const_iv (GL_FASTEST),
1938 root 1.89 const_iv (GL_V2F),
1939     const_iv (GL_V3F),
1940     const_iv (GL_T2F_V3F),
1941     const_iv (GL_T2F_N3F_V3F),
1942 root 1.54 # undef const_iv
1943     };
1944    
1945     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1946     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1947     }
1948    
1949 root 1.97 char *
1950     gl_vendor ()
1951     CODE:
1952     RETVAL = (char *)glGetString (GL_VENDOR);
1953     OUTPUT:
1954     RETVAL
1955    
1956     char *
1957     gl_version ()
1958     CODE:
1959     RETVAL = (char *)glGetString (GL_VERSION);
1960     OUTPUT:
1961     RETVAL
1962    
1963     char *
1964     gl_extensions ()
1965     CODE:
1966     RETVAL = (char *)glGetString (GL_EXTENSIONS);
1967     OUTPUT:
1968     RETVAL
1969    
1970 root 1.54 int glGetError ()
1971    
1972 root 1.114 void glFinish ()
1973    
1974 root 1.54 void glClear (int mask)
1975    
1976     void glClearColor (float r, float g, float b, float a = 1.0)
1977     PROTOTYPE: @
1978    
1979     void glEnable (int cap)
1980    
1981     void glDisable (int cap)
1982    
1983     void glShadeModel (int mode)
1984    
1985     void glHint (int target, int mode)
1986    
1987     void glBlendFunc (int sfactor, int dfactor)
1988    
1989 root 1.103 void glBlendFuncSeparate (int sa, int da, int saa, int daa)
1990     CODE:
1991     gl_BlendFuncSeparate (sa, da, saa, daa);
1992    
1993 root 1.89 void glDepthMask (int flag)
1994    
1995 root 1.54 void glLogicOp (int opcode)
1996    
1997 root 1.68 void glColorMask (int red, int green, int blue, int alpha)
1998    
1999 root 1.54 void glMatrixMode (int mode)
2000    
2001     void glPushMatrix ()
2002    
2003     void glPopMatrix ()
2004    
2005     void glLoadIdentity ()
2006    
2007 root 1.119 void glDrawBuffer (int buffer)
2008    
2009     void glReadBuffer (int buffer)
2010    
2011 root 1.90 # near_ and far_ are due to microsofts buggy "c" compiler
2012     void glFrustum (double left, double right, double bottom, double top, double near_, double far_)
2013    
2014     # near_ and far_ are due to microsofts buggy "c" compiler
2015 root 1.64 void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
2016 root 1.54
2017     void glViewport (int x, int y, int width, int height)
2018    
2019 root 1.69 void glScissor (int x, int y, int width, int height)
2020    
2021 root 1.54 void glTranslate (float x, float y, float z = 0.)
2022     CODE:
2023     glTranslatef (x, y, z);
2024    
2025 root 1.62 void glScale (float x, float y, float z = 1.)
2026 root 1.54 CODE:
2027     glScalef (x, y, z);
2028    
2029     void glRotate (float angle, float x, float y, float z)
2030     CODE:
2031     glRotatef (angle, x, y, z);
2032    
2033     void glBegin (int mode)
2034    
2035     void glEnd ()
2036    
2037     void glColor (float r, float g, float b, float a = 1.0)
2038     PROTOTYPE: @
2039 root 1.103 ALIAS:
2040     glColor_premultiply = 1
2041 root 1.54 CODE:
2042 root 1.103 if (ix)
2043     {
2044     r *= a;
2045     g *= a;
2046     b *= a;
2047     }
2048 root 1.90 // microsoft visual "c" rounds instead of truncating...
2049 root 1.130 glColor4f (r, g, b, a);
2050 root 1.54
2051 root 1.89 void glInterleavedArrays (int format, int stride, char *data)
2052    
2053     void glDrawElements (int mode, int count, int type, char *indices)
2054    
2055     # 1.2 void glDrawRangeElements (int mode, int start, int end
2056    
2057 root 1.91 void glRasterPos (float x, float y, float z = 0.)
2058     CODE:
2059     glRasterPos3f (0, 0, z);
2060     glBitmap (0, 0, 0, 0, x, y, 0);
2061    
2062 root 1.54 void glVertex (float x, float y, float z = 0.)
2063     CODE:
2064     glVertex3f (x, y, z);
2065    
2066     void glTexCoord (float s, float t)
2067     CODE:
2068     glTexCoord2f (s, t);
2069    
2070     void glTexEnv (int target, int pname, float param)
2071     CODE:
2072     glTexEnvf (target, pname, param);
2073    
2074     void glTexParameter (int target, int pname, float param)
2075     CODE:
2076     glTexParameterf (target, pname, param);
2077    
2078     void glBindTexture (int target, int name)
2079    
2080     void glConvolutionParameter (int target, int pname, float params)
2081     CODE:
2082 root 1.103 if (gl.ConvolutionParameterf)
2083     gl.ConvolutionParameterf (target, pname, params);
2084 root 1.54
2085     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
2086 root 1.64 CODE:
2087 root 1.103 if (gl.ConvolutionFilter2D)
2088     gl.ConvolutionFilter2D (target, internalformat, width, height, format, type, data);
2089 root 1.54
2090 root 1.69 void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
2091     CODE:
2092 root 1.103 if (gl.SeparableFilter2D)
2093     gl.SeparableFilter2D (target, internalformat, width, height, format, type, row, column);
2094 root 1.69
2095 root 1.54 void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
2096    
2097     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
2098    
2099 root 1.91 void glDrawPixels (int width, int height, int format, int type, char *pixels)
2100 root 1.68
2101     void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
2102    
2103 root 1.54 int glGenTexture ()
2104     CODE:
2105     {
2106     GLuint name;
2107     glGenTextures (1, &name);
2108     RETVAL = name;
2109     }
2110     OUTPUT:
2111     RETVAL
2112    
2113     void glDeleteTexture (int name)
2114     CODE:
2115     {
2116     GLuint name_ = name;
2117     glDeleteTextures (1, &name_);
2118     }
2119    
2120     int glGenList ()
2121     CODE:
2122     RETVAL = glGenLists (1);
2123     OUTPUT:
2124     RETVAL
2125    
2126     void glDeleteList (int list)
2127     CODE:
2128     glDeleteLists (list, 1);
2129    
2130     void glNewList (int list, int mode = GL_COMPILE)
2131    
2132     void glEndList ()
2133    
2134     void glCallList (int list)
2135