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