ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.157
Committed: Sun Oct 1 14:48:50 2006 UTC (17 years, 7 months ago) by root
Branch: MAIN
Changes since 1.156: +31 -0 lines
Log Message:
support for grabbing win32 proxy

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     INTERNET_PROXY_INFO proxyinfo;
662     char buffer[2048];
663     DWORD buflen;
664    
665     EXTEND (SP, 3);
666    
667     buflen = sizeof (buffer);
668     if (InternetQueryOption (0, INTERNET_OPTION_PROXY, (void *)buffer, &buflen))
669     if (((INTERNET_PROXY_INFO *)buffer)->dwAccessType == INTERNET_OPEN_TYPE_PROXY)
670     {
671     PUSHs (newSVpv (((INTERNET_PROXY_INFO *)buffer)->lpszProxy, 0));
672    
673     buflen = sizeof (buffer);
674     if (InternetQueryOption (0, INTERNET_OPTION_PROXY_USERNAME, (void *)buffer, &buflen))
675     {
676     PUSHs (newSVpv (buffer, 0));
677    
678     buflen = sizeof (buffer);
679     if (InternetQueryOption (0, INTERNET_OPTION_PROXY_PASSWORD, (void *)buffer, &buflen))
680     PUSHs (newSVpv (buffer, 0));
681     }
682     }
683     #endif
684     }
685    
686     void
687 root 1.13 add_font (char *file)
688     CODE:
689 root 1.129 FcConfigAppFontAddFile (0, (const FcChar8 *)file);
690 root 1.13
691     void
692 root 1.23 load_image_inline (SV *image_)
693     ALIAS:
694     load_image_file = 1
695     PPCODE:
696     {
697     STRLEN image_len;
698     char *image = (char *)SvPVbyte (image_, image_len);
699     SDL_Surface *surface, *surface2;
700     SDL_PixelFormat fmt;
701     SDL_RWops *rw = ix
702     ? SDL_RWFromFile (image, "r")
703     : SDL_RWFromConstMem (image, image_len);
704    
705     if (!rw)
706 root 1.41 croak ("load_image: %s", SDL_GetError ());
707 root 1.23
708     surface = IMG_Load_RW (rw, 1);
709     if (!surface)
710 root 1.41 croak ("load_image: %s", SDL_GetError ());
711 root 1.23
712     fmt.palette = NULL;
713     fmt.BitsPerPixel = 32;
714     fmt.BytesPerPixel = 4;
715 root 1.49 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
716 root 1.23 fmt.Rmask = 0x000000ff;
717     fmt.Gmask = 0x0000ff00;
718     fmt.Bmask = 0x00ff0000;
719     fmt.Amask = 0xff000000;
720 root 1.49 #else
721     fmt.Rmask = 0xff000000;
722     fmt.Gmask = 0x00ff0000;
723     fmt.Bmask = 0x0000ff00;
724     fmt.Amask = 0x000000ff;
725     #endif
726 root 1.23 fmt.Rloss = 0;
727     fmt.Gloss = 0;
728     fmt.Bloss = 0;
729     fmt.Aloss = 0;
730     fmt.Rshift = 0;
731     fmt.Gshift = 8;
732     fmt.Bshift = 16;
733     fmt.Ashift = 24;
734     fmt.colorkey = 0;
735     fmt.alpha = 0;
736    
737     surface2 = SDL_ConvertSurface (surface, &fmt, SDL_SWSURFACE);
738    
739 root 1.39 assert (surface2->pitch == surface2->w * 4);
740    
741 root 1.129 SDL_LockSurface (surface2);
742     EXTEND (SP, 6);
743 root 1.23 PUSHs (sv_2mortal (newSViv (surface2->w)));
744     PUSHs (sv_2mortal (newSViv (surface2->h)));
745     PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch)));
746 root 1.116 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
747 root 1.23 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
748 root 1.49 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
749 root 1.129 SDL_UnlockSurface (surface2);
750 root 1.23
751     SDL_FreeSurface (surface);
752     SDL_FreeSurface (surface2);
753     }
754    
755 root 1.25 void
756 root 1.39 average (int x, int y, uint32_t *data)
757     PPCODE:
758     {
759     uint32_t r = 0, g = 0, b = 0, a = 0;
760    
761     x = y = x * y;
762    
763     while (x--)
764     {
765     uint32_t p = *data++;
766    
767     r += (p ) & 255;
768     g += (p >> 8) & 255;
769     b += (p >> 16) & 255;
770     a += (p >> 24) & 255;
771     }
772    
773     EXTEND (SP, 4);
774 root 1.40 PUSHs (sv_2mortal (newSViv (r / y)));
775     PUSHs (sv_2mortal (newSViv (g / y)));
776     PUSHs (sv_2mortal (newSViv (b / y)));
777     PUSHs (sv_2mortal (newSViv (a / y)));
778 root 1.39 }
779    
780     void
781 root 1.66 error (char *message)
782     CODE:
783 root 1.86 fprintf (stderr, "ERROR: %s\n", message);
784 root 1.66 #ifdef _WIN32
785 root 1.86 MessageBox (0, message, "Crossfire+ Error", MB_OK | MB_ICONERROR);
786 root 1.66 #endif
787    
788     void
789 root 1.25 fatal (char *message)
790     CODE:
791 root 1.86 fprintf (stderr, "FATAL: %s\n", message);
792 root 1.50 #ifdef _WIN32
793 root 1.86 MessageBox (0, message, "Crossfire+ Fatal Error", MB_OK | MB_ICONERROR);
794 root 1.25 #endif
795 root 1.112 _exit (1);
796 root 1.111
797     void
798     _exit (int retval)
799     CODE:
800 root 1.112 _exit (retval);
801 root 1.25
802 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Font
803 root 1.61
804 root 1.133 CFPlus::Font
805 root 1.70 new_from_file (SV *class, char *path, int id = 0)
806 root 1.61 CODE:
807     {
808     int count;
809 root 1.70 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count);
810 root 1.61 RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
811     FcPatternDestroy (pattern);
812     }
813     OUTPUT:
814     RETVAL
815    
816     void
817 root 1.133 DESTROY (CFPlus::Font self)
818 root 1.61 CODE:
819     pango_font_description_free (self);
820    
821     void
822 root 1.133 make_default (CFPlus::Font self)
823 root 1.61 CODE:
824     default_font = self;
825    
826 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Layout
827 root 1.14
828 root 1.124 void
829 root 1.129 reset_glyph_cache ()
830 root 1.124 CODE:
831     tc_clear ();
832    
833 root 1.133 CFPlus::Layout
834 root 1.128 new (SV *class)
835 root 1.14 CODE:
836     New (0, RETVAL, 1, struct cf_layout);
837 root 1.76
838 root 1.124 RETVAL->pl = pango_layout_new (opengl_context);
839 root 1.76 RETVAL->r = 1.;
840     RETVAL->g = 1.;
841     RETVAL->b = 1.;
842     RETVAL->a = 1.;
843     RETVAL->base_height = MIN_FONT_HEIGHT;
844     RETVAL->font = 0;
845    
846 root 1.14 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
847 root 1.76 layout_update_font (RETVAL);
848 root 1.14 OUTPUT:
849     RETVAL
850    
851     void
852 root 1.133 DESTROY (CFPlus::Layout self)
853 root 1.14 CODE:
854     g_object_unref (self->pl);
855     Safefree (self);
856 root 1.13
857 root 1.8 void
858 root 1.133 set_text (CFPlus::Layout self, SV *text_)
859 root 1.35 CODE:
860     {
861     STRLEN textlen;
862     char *text = SvPVutf8 (text_, textlen);
863    
864     pango_layout_set_text (self->pl, text, textlen);
865     }
866    
867     void
868 root 1.133 set_markup (CFPlus::Layout self, SV *text_)
869 root 1.14 CODE:
870 root 1.5 {
871     STRLEN textlen;
872     char *text = SvPVutf8 (text_, textlen);
873 root 1.14
874     pango_layout_set_markup (self->pl, text, textlen);
875     }
876    
877 root 1.121 void
878 root 1.133 set_shapes (CFPlus::Layout self, ...)
879 root 1.121 CODE:
880     {
881     PangoAttrList *attrs = 0;
882     const char *text = pango_layout_get_text (self->pl);
883     const char *pos = text;
884 root 1.122 int arg = 4;
885 root 1.121
886     while (arg < items && (pos = strstr (pos, OBJ_STR)))
887     {
888 root 1.122 PangoRectangle inkrect, rect;
889 root 1.121 PangoAttribute *attr;
890    
891 root 1.122 int x = SvIV (ST (arg - 3));
892     int y = SvIV (ST (arg - 2));
893 root 1.121 int w = SvIV (ST (arg - 1));
894 root 1.122 int h = SvIV (ST (arg ));
895 root 1.121
896 root 1.122 inkrect.x = 0;
897     inkrect.y = 0;
898     inkrect.width = 0;
899     inkrect.height = 0;
900    
901     rect.x = x * PANGO_SCALE;
902     rect.y = y * PANGO_SCALE;
903     rect.width = w * PANGO_SCALE;
904 root 1.121 rect.height = h * PANGO_SCALE;
905    
906     if (!attrs)
907     attrs = pango_layout_get_attributes (self->pl);
908    
909 root 1.122 attr = pango_attr_shape_new (&inkrect, &rect);
910 root 1.121 attr->start_index = pos - text;
911     attr->end_index = attr->start_index + sizeof (OBJ_STR) - 1;
912     pango_attr_list_insert (attrs, attr);
913    
914 root 1.122 arg += 4;
915 root 1.121 pos += sizeof (OBJ_STR) - 1;
916     }
917    
918     if (attrs)
919     pango_layout_set_attributes (self->pl, attrs);
920     }
921    
922     void
923 root 1.133 get_shapes (CFPlus::Layout self)
924 root 1.121 PPCODE:
925     {
926     PangoLayoutIter *iter = pango_layout_get_iter (self->pl);
927    
928     do
929     {
930     PangoLayoutRun *run = pango_layout_iter_get_run (iter);
931    
932     if (run && shape_attr_p (run))
933     {
934     PangoRectangle extents;
935     pango_layout_iter_get_run_extents (iter, 0, &extents);
936    
937 root 1.129 EXTEND (SP, 2);
938 root 1.121 PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.x))));
939     PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.y))));
940     }
941     }
942     while (pango_layout_iter_next_run (iter));
943    
944     pango_layout_iter_free (iter);
945     }
946    
947     int
948 root 1.133 has_wrapped (CFPlus::Layout self)
949 root 1.121 CODE:
950     {
951     int lines = 1;
952     const char *text = pango_layout_get_text (self->pl);
953    
954     while (*text)
955     lines += *text++ == '\n';
956    
957     RETVAL = lines < pango_layout_get_line_count (self->pl);
958     }
959     OUTPUT:
960     RETVAL
961    
962 root 1.46 SV *
963 root 1.133 get_text (CFPlus::Layout self)
964 root 1.46 CODE:
965 root 1.47 RETVAL = newSVpv (pango_layout_get_text (self->pl), 0);
966 root 1.107 sv_utf8_decode (RETVAL);
967 root 1.46 OUTPUT:
968     RETVAL
969    
970 root 1.14 void
971 root 1.133 set_foreground (CFPlus::Layout self, float r, float g, float b, float a = 1.)
972 root 1.76 CODE:
973     self->r = r;
974     self->g = g;
975     self->b = b;
976     self->a = a;
977    
978     void
979 root 1.133 set_font (CFPlus::Layout self, CFPlus::Font font = 0)
980 root 1.61 CODE:
981     if (self->font != font)
982     {
983     self->font = font;
984     layout_update_font (self);
985     }
986    
987     void
988 root 1.133 set_height (CFPlus::Layout self, int base_height)
989 root 1.16 CODE:
990 root 1.61 if (self->base_height != base_height)
991     {
992     self->base_height = base_height;
993     layout_update_font (self);
994     }
995 root 1.16
996     void
997 root 1.133 set_width (CFPlus::Layout self, int max_width = -1)
998 root 1.14 CODE:
999     pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE);
1000    
1001     void
1002 root 1.133 set_indent (CFPlus::Layout self, int indent)
1003 root 1.84 CODE:
1004     pango_layout_set_indent (self->pl, indent * PANGO_SCALE);
1005    
1006     void
1007 root 1.133 set_spacing (CFPlus::Layout self, int spacing)
1008 root 1.84 CODE:
1009     pango_layout_set_spacing (self->pl, spacing * PANGO_SCALE);
1010    
1011     void
1012 root 1.133 set_ellipsise (CFPlus::Layout self, int ellipsise)
1013 root 1.84 CODE:
1014     pango_layout_set_ellipsize (self->pl,
1015     ellipsise == 1 ? PANGO_ELLIPSIZE_START
1016     : ellipsise == 2 ? PANGO_ELLIPSIZE_MIDDLE
1017     : ellipsise == 3 ? PANGO_ELLIPSIZE_END
1018     : PANGO_ELLIPSIZE_NONE
1019     );
1020    
1021     void
1022 root 1.133 set_single_paragraph_mode (CFPlus::Layout self, int spm)
1023 root 1.84 CODE:
1024     pango_layout_set_single_paragraph_mode (self->pl, !!spm);
1025    
1026     void
1027 root 1.133 size (CFPlus::Layout self)
1028 root 1.14 PPCODE:
1029     {
1030     int w, h;
1031    
1032     layout_get_pixel_size (self, &w, &h);
1033    
1034     EXTEND (SP, 2);
1035     PUSHs (sv_2mortal (newSViv (w)));
1036     PUSHs (sv_2mortal (newSViv (h)));
1037     }
1038    
1039 root 1.17 int
1040 root 1.133 descent (CFPlus::Layout self)
1041 root 1.122 CODE:
1042     {
1043     PangoRectangle rect;
1044     PangoLayoutLine *line = pango_layout_get_line (self->pl, 0);
1045     pango_layout_line_get_pixel_extents (line, 0, &rect);
1046     RETVAL = PANGO_DESCENT (rect);
1047     }
1048     OUTPUT:
1049     RETVAL
1050    
1051     int
1052 root 1.133 xy_to_index (CFPlus::Layout self, int x, int y)
1053 root 1.17 CODE:
1054     {
1055     int index, trailing;
1056     pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing);
1057     RETVAL = index;
1058     }
1059     OUTPUT:
1060     RETVAL
1061    
1062     void
1063 root 1.133 cursor_pos (CFPlus::Layout self, int index)
1064 root 1.17 PPCODE:
1065     {
1066     PangoRectangle strong_pos;
1067     pango_layout_get_cursor_pos (self->pl, index, &strong_pos, 0);
1068 root 1.30
1069 root 1.17 EXTEND (SP, 3);
1070     PUSHs (sv_2mortal (newSViv (strong_pos.x / PANGO_SCALE)));
1071     PUSHs (sv_2mortal (newSViv (strong_pos.y / PANGO_SCALE)));
1072     PUSHs (sv_2mortal (newSViv (strong_pos.height / PANGO_SCALE)));
1073     }
1074    
1075 root 1.14 void
1076 root 1.135 render (CFPlus::Layout self, float x, float y, int flags = 0)
1077 root 1.14 PPCODE:
1078 root 1.124 pango_opengl_render_layout_subpixel (
1079     self->pl,
1080     x * PANGO_SCALE, y * PANGO_SCALE,
1081 root 1.135 self->r, self->g, self->b, self->a,
1082     flags
1083 root 1.124 );
1084 root 1.11
1085 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Texture
1086 root 1.11
1087     void
1088 root 1.113 pad2pot (SV *data_, SV *w_, SV *h_)
1089     CODE:
1090     {
1091     int ow = SvIV (w_);
1092     int oh = SvIV (h_);
1093    
1094     if (ow && oh)
1095     {
1096     int nw = minpot (ow);
1097     int nh = minpot (oh);
1098    
1099     if (nw != ow || nh != oh)
1100     {
1101     if (SvOK (data_))
1102     {
1103     STRLEN datalen;
1104     char *data = SvPVbyte (data_, datalen);
1105     int bpp = datalen / (ow * oh);
1106     SV *result_ = sv_2mortal (newSV (nw * nh * bpp));
1107    
1108     SvPOK_only (result_);
1109     SvCUR_set (result_, nw * nh * bpp);
1110    
1111     memset (SvPVX (result_), 0, nw * nh * bpp);
1112     while (oh--)
1113     memcpy (SvPVX (result_) + oh * nw * bpp, data + oh * ow * bpp, ow * bpp);
1114    
1115     sv_setsv (data_, result_);
1116     }
1117    
1118     sv_setiv (w_, nw);
1119     sv_setiv (h_, nh);
1120     }
1121     }
1122     }
1123    
1124     void
1125 root 1.114 draw_quad (SV *self, float x, float y, float w = 0., float h = 0.)
1126 root 1.12 PROTOTYPE: $$$;$$
1127 root 1.76 ALIAS:
1128     draw_quad_alpha = 1
1129     draw_quad_alpha_premultiplied = 2
1130 root 1.11 CODE:
1131     {
1132 root 1.12 HV *hv = (HV *)SvRV (self);
1133 root 1.37 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
1134     float t = SvNV (*hv_fetch (hv, "t", 1, 1));
1135 root 1.12 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
1136    
1137     if (items < 5)
1138     {
1139 root 1.18 w = SvNV (*hv_fetch (hv, "w", 1, 1));
1140     h = SvNV (*hv_fetch (hv, "h", 1, 1));
1141 root 1.12 }
1142    
1143 root 1.76 if (ix)
1144     {
1145     glEnable (GL_BLEND);
1146 root 1.103
1147     if (ix == 2)
1148     glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1149     else
1150     gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1151 root 1.104 GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1152 root 1.103
1153 root 1.86 glEnable (GL_ALPHA_TEST);
1154     glAlphaFunc (GL_GREATER, 0.01f);
1155 root 1.76 }
1156    
1157 root 1.12 glBindTexture (GL_TEXTURE_2D, name);
1158 root 1.76
1159 root 1.12 glBegin (GL_QUADS);
1160 root 1.37 glTexCoord2f (0, 0); glVertex2f (x , y );
1161     glTexCoord2f (0, t); glVertex2f (x , y + h);
1162     glTexCoord2f (s, t); glVertex2f (x + w, y + h);
1163     glTexCoord2f (s, 0); glVertex2f (x + w, y );
1164 root 1.12 glEnd ();
1165 root 1.76
1166     if (ix)
1167 root 1.86 {
1168     glDisable (GL_ALPHA_TEST);
1169     glDisable (GL_BLEND);
1170     }
1171 root 1.11 }
1172 root 1.28
1173 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::Map
1174 root 1.28
1175 root 1.133 CFPlus::Map
1176 root 1.28 new (SV *class, int map_width, int map_height)
1177     CODE:
1178     New (0, RETVAL, 1, struct map);
1179 root 1.42 RETVAL->x = 0;
1180     RETVAL->y = 0;
1181     RETVAL->w = map_width;
1182     RETVAL->h = map_height;
1183     RETVAL->ox = 0;
1184     RETVAL->oy = 0;
1185 root 1.30 RETVAL->faces = 8192;
1186     Newz (0, RETVAL->face, RETVAL->faces, mapface);
1187 root 1.42 RETVAL->texs = 8192;
1188     Newz (0, RETVAL->tex, RETVAL->texs, maptex);
1189 root 1.28 RETVAL->rows = 0;
1190     RETVAL->row = 0;
1191     OUTPUT:
1192     RETVAL
1193    
1194     void
1195 root 1.133 DESTROY (CFPlus::Map self)
1196 root 1.28 CODE:
1197     {
1198 root 1.30 map_clear (self);
1199 root 1.28 Safefree (self->face);
1200 root 1.111 Safefree (self->tex);
1201 root 1.29 Safefree (self);
1202     }
1203    
1204     void
1205 root 1.133 clear (CFPlus::Map self)
1206 root 1.30 CODE:
1207     map_clear (self);
1208    
1209     void
1210 root 1.133 set_face (CFPlus::Map self, int face, int texid)
1211 root 1.29 CODE:
1212     {
1213 root 1.42 while (self->faces <= face)
1214 root 1.28 {
1215 root 1.30 Append (mapface, self->face, self->faces, self->faces);
1216 root 1.29 self->faces *= 2;
1217     }
1218 root 1.28
1219 root 1.42 self->face [face] = texid;
1220     }
1221    
1222     void
1223 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)
1224 root 1.42 CODE:
1225     {
1226     while (self->texs <= texid)
1227     {
1228     Append (maptex, self->tex, self->texs, self->texs);
1229     self->texs *= 2;
1230     }
1231    
1232 root 1.48 {
1233     maptex *tex = self->tex + texid;
1234 root 1.39
1235 root 1.48 tex->name = name;
1236     tex->w = w;
1237     tex->h = h;
1238     tex->s = s;
1239     tex->t = t;
1240     tex->r = r;
1241     tex->g = g;
1242     tex->b = b;
1243     tex->a = a;
1244     }
1245 root 1.95
1246     // somewhat hackish, but for textures that require it, it really
1247     // improves the look, and most others don't suffer.
1248     glBindTexture (GL_TEXTURE_2D, name);
1249 root 1.99 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1250     //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1251     // use uglier nearest interpolation because linear suffers
1252     // from transparent color bleeding and ugly wrapping effects.
1253     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1254 root 1.29 }
1255    
1256 root 1.42 int
1257 root 1.133 ox (CFPlus::Map self)
1258 root 1.42 ALIAS:
1259     oy = 1
1260 root 1.101 x = 2
1261     y = 3
1262 root 1.102 w = 4
1263     h = 5
1264 root 1.42 CODE:
1265     switch (ix)
1266     {
1267     case 0: RETVAL = self->ox; break;
1268     case 1: RETVAL = self->oy; break;
1269 root 1.101 case 2: RETVAL = self->x; break;
1270     case 3: RETVAL = self->y; break;
1271 root 1.102 case 4: RETVAL = self->w; break;
1272     case 5: RETVAL = self->h; break;
1273 root 1.42 }
1274     OUTPUT:
1275     RETVAL
1276    
1277 root 1.29 void
1278 root 1.133 scroll (CFPlus::Map self, int dx, int dy)
1279 root 1.43 CODE:
1280     {
1281 root 1.44 if (dx > 0)
1282 root 1.154 map_blank (self, self->x, self->y, dx, self->h);
1283 root 1.44 else if (dx < 0)
1284 root 1.154 map_blank (self, self->x + self->w + dx + 1, self->y, -dx, self->h);
1285 root 1.44
1286     if (dy > 0)
1287 root 1.154 map_blank (self, self->x, self->y, self->w, dy);
1288 root 1.44 else if (dy < 0)
1289 root 1.154 map_blank (self, self->x, self->y + self->h + dy + 1, self->w, -dy);
1290 root 1.43
1291 root 1.44 self->ox += dx; self->x += dx;
1292     self->oy += dy; self->y += dy;
1293 root 1.43
1294     while (self->y < 0)
1295     {
1296     Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
1297    
1298     self->rows += MAP_EXTEND_Y;
1299     self->y += MAP_EXTEND_Y;
1300     }
1301 root 1.44 }
1302 root 1.43
1303 root 1.44 void
1304 root 1.141 map1a_update (CFPlus::Map self, SV *data_, int extmap)
1305 root 1.44 CODE:
1306     {
1307 root 1.30 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1308     uint8_t *data_end = (uint8_t *)SvEND (data_);
1309 root 1.48 mapcell *cell;
1310     int x, y, flags;
1311 root 1.43
1312 root 1.150 while (data < data_end - 1)
1313 root 1.29 {
1314 root 1.48 flags = (data [0] << 8) + data [1]; data += 2;
1315 root 1.30
1316 root 1.120 x = self->x + ((flags >> 10) & 63);
1317     y = self->y + ((flags >> 4) & 63);
1318 root 1.29
1319 root 1.48 cell = map_get_cell (self, x, y);
1320 root 1.29
1321     if (flags & 15)
1322     {
1323 root 1.142 if (!cell->darkness)
1324 root 1.29 {
1325 root 1.154 memset (cell, 0, sizeof (*cell));
1326 root 1.142 cell->darkness = 256;
1327 root 1.29 }
1328 root 1.45
1329 root 1.142 //TODO: don't trust server data to be in-range(!)
1330    
1331 root 1.141 if (flags & 8)
1332     {
1333     if (extmap)
1334     {
1335     uint8_t ext, cmd;
1336    
1337     do
1338     {
1339     ext = *data++;
1340 root 1.144 cmd = ext & 0x3f;
1341 root 1.141
1342 root 1.147 if (cmd < 4)
1343 root 1.142 cell->darkness = 255 - ext * 64 + 1;
1344 root 1.147 else if (cmd == 5) // health
1345     {
1346     cell->stat_width = 1;
1347     cell->stat_hp = *data++;
1348     }
1349     else if (cmd == 6) // monster width
1350     cell->stat_width = *data++ + 1;
1351 root 1.153 else if (cmd == 0x47) // monster width
1352     {
1353     if (*data == 4)
1354     ; // decode player tag
1355    
1356     data += *data + 1;
1357     }
1358     else if (cmd == 8) // cell flags
1359     cell->flags = *data++;
1360 root 1.144 else if (ext & 0x40) // unknown, multibyte => skip
1361     data += *data + 1;
1362 root 1.147 else
1363     data++;
1364 root 1.141 }
1365 root 1.147 while (ext & 0x80);
1366 root 1.141 }
1367     else
1368 root 1.142 cell->darkness = *data++ + 1;
1369 root 1.141 }
1370 root 1.29
1371     if (flags & 4)
1372     {
1373 root 1.42 cell->face [0] = self->face [(data [0] << 8) + data [1]]; data += 2;
1374 root 1.29 }
1375    
1376     if (flags & 2)
1377     {
1378 root 1.42 cell->face [1] = self->face [(data [0] << 8) + data [1]]; data += 2;
1379 root 1.29 }
1380    
1381     if (flags & 1)
1382     {
1383 root 1.42 cell->face [2] = self->face [(data [0] << 8) + data [1]]; data += 2;
1384 root 1.29 }
1385     }
1386     else
1387 root 1.155 cell->darkness = 0;
1388 root 1.29 }
1389 root 1.28 }
1390    
1391 root 1.40 SV *
1392 root 1.133 mapmap (CFPlus::Map self, int x0, int y0, int w, int h)
1393 root 1.40 CODE:
1394     {
1395 root 1.55 int x1, x;
1396     int y1, y;
1397 root 1.40 int z;
1398     SV *map_sv = newSV (w * h * sizeof (uint32_t));
1399     uint32_t *map = (uint32_t *)SvPVX (map_sv);
1400    
1401     SvPOK_only (map_sv);
1402     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
1403    
1404 root 1.55 x0 += self->x; x1 = x0 + w;
1405     y0 += self->y; y1 = y0 + h;
1406 root 1.40
1407     for (y = y0; y < y1; y++)
1408     {
1409     maprow *row = 0 <= y && y < self->rows
1410     ? self->row + y
1411     : 0;
1412    
1413     for (x = x0; x < x1; x++)
1414     {
1415     int r = 32, g = 32, b = 32, a = 192;
1416    
1417     if (row && row->c0 <= x && x < row->c1)
1418     {
1419     mapcell *cell = row->col + (x - row->c0);
1420    
1421     for (z = 0; z <= 0; z++)
1422     {
1423 root 1.42 mapface face = cell->face [z];
1424 root 1.40
1425     if (face)
1426     {
1427 root 1.42 maptex tex = self->tex [face];
1428 root 1.40 int a0 = 255 - tex.a;
1429     int a1 = tex.a;
1430    
1431     r = (r * a0 + tex.r * a1) / 255;
1432     g = (g * a0 + tex.g * a1) / 255;
1433     b = (b * a0 + tex.b * a1) / 255;
1434     a = (a * a0 + tex.a * a1) / 255;
1435     }
1436     }
1437     }
1438    
1439     *map++ = (r )
1440     | (g << 8)
1441     | (b << 16)
1442     | (a << 24);
1443     }
1444     }
1445    
1446     RETVAL = map_sv;
1447     }
1448     OUTPUT:
1449     RETVAL
1450    
1451 root 1.30 void
1452 root 1.133 draw (CFPlus::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1453 root 1.116 CODE:
1454 root 1.30 {
1455 root 1.48 int vx, vy;
1456     int x, y, z;
1457     int last_name;
1458     mapface face;
1459    
1460 root 1.120 vx = self->x + self->w / 2 - sw / 2 - shift_x;
1461     vy = self->y + self->h / 2 - sh / 2 - shift_y;
1462 root 1.38
1463 root 1.42 /*
1464     int vx = self->vx = self->w >= sw
1465     ? self->x + (self->w - sw) / 2
1466     : MIN (self->x, MAX (self->x + self->w - sw + 1, self->vx));
1467    
1468     int vy = self->vy = self->h >= sh
1469     ? self->y + (self->h - sh) / 2
1470     : MIN (self->y, MAX (self->y + self->h - sh + 1, self->vy));
1471     */
1472 root 1.30
1473     glColor4ub (255, 255, 255, 255);
1474    
1475 root 1.117 glEnable (GL_BLEND);
1476 root 1.30 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1477     glEnable (GL_TEXTURE_2D);
1478     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1479    
1480 root 1.48 glBegin (GL_QUADS);
1481 root 1.30
1482 root 1.48 last_name = 0;
1483 root 1.30
1484     for (z = 0; z < 3; z++)
1485     for (y = 0; y < sh; y++)
1486     if (0 <= y + vy && y + vy < self->rows)
1487     {
1488     maprow *row = self->row + (y + vy);
1489    
1490     for (x = 0; x < sw; x++)
1491     if (row->c0 <= x + vx && x + vx < row->c1)
1492     {
1493     mapcell *cell = row->col + (x + vx - row->c0);
1494 root 1.32
1495 root 1.48 face = cell->face [z];
1496 root 1.30
1497 root 1.145 if (face && face < self->texs)
1498 root 1.30 {
1499 root 1.42 maptex tex = self->tex [face];
1500 root 1.30 int px = (x + 1) * 32 - tex.w;
1501     int py = (y + 1) * 32 - tex.h;
1502    
1503     if (last_name != tex.name)
1504     {
1505     glEnd ();
1506 root 1.153 glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1507 root 1.30 glBegin (GL_QUADS);
1508     }
1509    
1510     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1511     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1512     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1513     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1514     }
1515 root 1.153
1516     if (cell->flags && z == 2)
1517     {
1518     if (cell->flags & 1)
1519     {
1520     maptex tex = self->tex [1];
1521     int px = (x + 1) * 32 - tex.w + 2;
1522     int py = (y + 1) * 32 - tex.h - 6;
1523    
1524     glEnd ();
1525     glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1526     glBegin (GL_QUADS);
1527    
1528     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1529     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1530     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1531     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1532     }
1533     }
1534 root 1.30 }
1535     }
1536    
1537     glEnd ();
1538 root 1.32
1539 root 1.34 glDisable (GL_TEXTURE_2D);
1540 root 1.152 glDisable (GL_BLEND);
1541 root 1.143
1542 root 1.145 // top layer: overlays such as the health bar
1543 root 1.143 for (y = 0; y < sh; y++)
1544     if (0 <= y + vy && y + vy < self->rows)
1545     {
1546     maprow *row = self->row + (y + vy);
1547    
1548     for (x = 0; x < sw; x++)
1549     if (row->c0 <= x + vx && x + vx < row->c1)
1550     {
1551     mapcell *cell = row->col + (x + vx - row->c0);
1552    
1553     int px = x * 32;
1554     int py = y * 32;
1555    
1556     if (cell->stat_hp)
1557     {
1558 root 1.147 int width = cell->stat_width * 32;
1559     int thick = sh / 28 + 1 + cell->stat_width;
1560 root 1.143
1561 root 1.152 glColor3ub (0, 0, 0);
1562 root 1.151 glRectf (px + 1, py - thick - 2,
1563     px + width - 1, py);
1564 root 1.147
1565 root 1.152 glColor3ub (cell->stat_hp, 255 - cell->stat_hp, 0);
1566 root 1.147 glRectf (px + 2,
1567 root 1.151 py - thick - 1,
1568     px + width - 2 - cell->stat_hp * (width - 4) / 255, py - 1);
1569 root 1.143 }
1570     }
1571     }
1572 root 1.116 }
1573    
1574     void
1575 root 1.133 draw_magicmap (CFPlus::Map self, int dx, int dy, int w, int h, unsigned char *data)
1576 root 1.117 CODE:
1577     {
1578     static float color[16][3] = {
1579 root 1.123 { 0.00F, 0.00F, 0.00F },
1580     { 1.00F, 1.00F, 1.00F },
1581     { 0.00F, 0.00F, 0.55F },
1582     { 1.00F, 0.00F, 0.00F },
1583    
1584     { 1.00F, 0.54F, 0.00F },
1585     { 0.11F, 0.56F, 1.00F },
1586     { 0.93F, 0.46F, 0.00F },
1587     { 0.18F, 0.54F, 0.34F },
1588    
1589     { 0.56F, 0.73F, 0.56F },
1590     { 0.80F, 0.80F, 0.80F },
1591     { 0.55F, 0.41F, 0.13F },
1592     { 0.99F, 0.77F, 0.26F },
1593    
1594     { 0.74F, 0.65F, 0.41F },
1595    
1596     { 0.00F, 1.00F, 1.00F },
1597     { 1.00F, 0.00F, 1.00F },
1598     { 1.00F, 1.00F, 0.00F },
1599 root 1.117 };
1600    
1601     int x, y;
1602    
1603     glEnable (GL_TEXTURE_2D);
1604     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1605     glEnable (GL_BLEND);
1606     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1607     glBegin (GL_QUADS);
1608    
1609     for (y = 0; y < h; y++)
1610     for (x = 0; x < w; x++)
1611     {
1612     unsigned char m = data [x + y * w];
1613    
1614 root 1.118 if (m)
1615     {
1616     float *c = color [m & 15];
1617    
1618     float tx1 = m & 0x40 ? 0.5 : 0.;
1619     float tx2 = tx1 + 0.5;
1620    
1621     glColor4f (c[0], c[1], c[2], 0.75);
1622     glTexCoord2f (tx1, 0.); glVertex2i (x , y );
1623     glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
1624     glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
1625     glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
1626     }
1627 root 1.117 }
1628    
1629     glEnd ();
1630     glDisable (GL_BLEND);
1631     glDisable (GL_TEXTURE_2D);
1632     }
1633    
1634     void
1635 root 1.133 fow_texture (CFPlus::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1636 root 1.116 PPCODE:
1637     {
1638     int vx, vy;
1639     int x, y;
1640     int sw4 = (sw + 3) & ~3;
1641     SV *darkness_sv = sv_2mortal (newSV (sw4 * sh));
1642     uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv);
1643    
1644     memset (darkness, 255, sw4 * sh);
1645     SvPOK_only (darkness_sv);
1646     SvCUR_set (darkness_sv, sw4 * sh);
1647    
1648     vx = self->x + (self->w - sw + 1) / 2 - shift_x;
1649     vy = self->y + (self->h - sh + 1) / 2 - shift_y;
1650    
1651     for (y = 0; y < sh; y++)
1652     if (0 <= y + vy && y + vy < self->rows)
1653     {
1654     maprow *row = self->row + (y + vy);
1655    
1656     for (x = 0; x < sw; x++)
1657     if (row->c0 <= x + vx && x + vx < row->c1)
1658     {
1659     mapcell *cell = row->col + (x + vx - row->c0);
1660    
1661 root 1.142 darkness[y * sw4 + x] = cell->darkness
1662 root 1.143 ? 255 - (cell->darkness - 1)
1663 root 1.142 : 255 - FOW_DARKNESS;
1664 root 1.116 }
1665     }
1666 root 1.34
1667 root 1.32 EXTEND (SP, 3);
1668     PUSHs (sv_2mortal (newSViv (sw4)));
1669     PUSHs (sv_2mortal (newSViv (sh)));
1670     PUSHs (darkness_sv);
1671 root 1.30 }
1672    
1673 root 1.42 SV *
1674 root 1.133 get_rect (CFPlus::Map self, int x0, int y0, int w, int h)
1675 root 1.42 CODE:
1676     {
1677     int x, y, x1, y1;
1678     SV *data_sv = newSV (w * h * 7 + 5);
1679     uint8_t *data = (uint8_t *)SvPVX (data_sv);
1680    
1681     *data++ = 0; /* version 0 format */
1682     *data++ = w >> 8; *data++ = w;
1683     *data++ = h >> 8; *data++ = h;
1684    
1685     // we need to do this 'cause we don't keep an absolute coord system for rows
1686 root 1.55 // TODO: treat rows as we treat columns
1687 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1688     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1689    
1690     x0 += self->x - self->ox;
1691     y0 += self->y - self->oy;
1692    
1693     x1 = x0 + w;
1694     y1 = y0 + h;
1695    
1696     for (y = y0; y < y1; y++)
1697     {
1698     maprow *row = 0 <= y && y < self->rows
1699     ? self->row + y
1700     : 0;
1701    
1702     for (x = x0; x < x1; x++)
1703     {
1704     if (row && row->c0 <= x && x < row->c1)
1705     {
1706     mapcell *cell = row->col + (x - row->c0);
1707     uint8_t flags = 0;
1708    
1709     if (cell->face [0]) flags |= 1;
1710     if (cell->face [1]) flags |= 2;
1711     if (cell->face [2]) flags |= 4;
1712    
1713     *data++ = flags;
1714    
1715     if (flags & 1)
1716     {
1717     *data++ = cell->face [0] >> 8;
1718     *data++ = cell->face [0];
1719     }
1720    
1721     if (flags & 2)
1722     {
1723     *data++ = cell->face [1] >> 8;
1724     *data++ = cell->face [1];
1725     }
1726    
1727     if (flags & 4)
1728     {
1729     *data++ = cell->face [2] >> 8;
1730     *data++ = cell->face [2];
1731     }
1732     }
1733     else
1734     *data++ = 0;
1735     }
1736     }
1737    
1738     SvPOK_only (data_sv);
1739     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
1740     RETVAL = data_sv;
1741     }
1742     OUTPUT:
1743     RETVAL
1744    
1745     void
1746 root 1.133 set_rect (CFPlus::Map self, int x0, int y0, uint8_t *data)
1747 root 1.42 PPCODE:
1748     {
1749     int x, y, z;
1750 root 1.48 int w, h;
1751 root 1.42 int x1, y1;
1752    
1753     if (*data++ != 0)
1754     return; /* version mismatch */
1755    
1756 root 1.48 w = *data++ << 8; w |= *data++;
1757     h = *data++ << 8; h |= *data++;
1758 root 1.42
1759     // we need to do this 'cause we don't keep an absolute coord system for rows
1760 root 1.55 // TODO: treat rows as we treat columns
1761 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1762     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1763    
1764     x0 += self->x - self->ox;
1765     y0 += self->y - self->oy;
1766    
1767     x1 = x0 + w;
1768     y1 = y0 + h;
1769    
1770     for (y = y0; y < y1; y++)
1771     {
1772     maprow *row = map_get_row (self, y);
1773    
1774     for (x = x0; x < x1; x++)
1775     {
1776     uint8_t flags = *data++;
1777    
1778     if (flags)
1779     {
1780     mapface face[3] = { 0, 0, 0 };
1781    
1782     mapcell *cell = row_get_cell (row, x);
1783    
1784     if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; }
1785     if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; }
1786     if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; }
1787    
1788 root 1.143 if (cell->darkness == 0)
1789 root 1.42 {
1790 root 1.142 cell->darkness = 0;
1791 root 1.42
1792     for (z = 0; z <= 2; z++)
1793     {
1794     cell->face[z] = face[z];
1795    
1796     if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name))
1797     XPUSHs (sv_2mortal (newSViv (face[z])));
1798     }
1799     }
1800     }
1801     }
1802     }
1803     }
1804    
1805 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixChunk
1806 root 1.52
1807 root 1.133 CFPlus::MixChunk
1808 root 1.52 new_from_file (SV *class, char *path)
1809     CODE:
1810     RETVAL = Mix_LoadWAV (path);
1811     OUTPUT:
1812     RETVAL
1813    
1814     void
1815 root 1.133 DESTROY (CFPlus::MixChunk self)
1816 root 1.52 CODE:
1817     Mix_FreeChunk (self);
1818    
1819     int
1820 root 1.133 volume (CFPlus::MixChunk self, int volume = -1)
1821 root 1.52 CODE:
1822     RETVAL = Mix_VolumeChunk (self, volume);
1823     OUTPUT:
1824     RETVAL
1825    
1826     int
1827 root 1.133 play (CFPlus::MixChunk self, int channel = -1, int loops = 0, int ticks = -1)
1828 root 1.52 CODE:
1829     RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
1830     OUTPUT:
1831     RETVAL
1832    
1833 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixMusic
1834 root 1.52
1835     int
1836     volume (int volume = -1)
1837     CODE:
1838     RETVAL = Mix_VolumeMusic (volume);
1839     OUTPUT:
1840     RETVAL
1841    
1842 root 1.133 CFPlus::MixMusic
1843 root 1.52 new_from_file (SV *class, char *path)
1844     CODE:
1845     RETVAL = Mix_LoadMUS (path);
1846     OUTPUT:
1847     RETVAL
1848    
1849     void
1850 root 1.133 DESTROY (CFPlus::MixMusic self)
1851 root 1.52 CODE:
1852     Mix_FreeMusic (self);
1853    
1854     int
1855 root 1.133 play (CFPlus::MixMusic self, int loops = -1)
1856 root 1.52 CODE:
1857     RETVAL = Mix_PlayMusic (self, loops);
1858     OUTPUT:
1859     RETVAL
1860    
1861 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::OpenGL
1862 root 1.54
1863     BOOT:
1864     {
1865 root 1.133 HV *stash = gv_stashpv ("CFPlus::OpenGL", 1);
1866 root 1.54 static const struct {
1867     const char *name;
1868     IV iv;
1869     } *civ, const_iv[] = {
1870     # define const_iv(name) { # name, (IV)name }
1871     const_iv (GL_COLOR_MATERIAL),
1872     const_iv (GL_SMOOTH),
1873     const_iv (GL_FLAT),
1874 root 1.69 const_iv (GL_DITHER),
1875 root 1.54 const_iv (GL_BLEND),
1876 root 1.89 const_iv (GL_CULL_FACE),
1877 root 1.69 const_iv (GL_SCISSOR_TEST),
1878 root 1.89 const_iv (GL_DEPTH_TEST),
1879     const_iv (GL_ALPHA_TEST),
1880     const_iv (GL_NORMALIZE),
1881     const_iv (GL_RESCALE_NORMAL),
1882 root 1.119 const_iv (GL_FRONT),
1883     const_iv (GL_BACK),
1884 root 1.54 const_iv (GL_AND),
1885 root 1.67 const_iv (GL_ONE),
1886     const_iv (GL_ZERO),
1887 root 1.54 const_iv (GL_SRC_ALPHA),
1888 root 1.104 const_iv (GL_DST_ALPHA),
1889 root 1.54 const_iv (GL_ONE_MINUS_SRC_ALPHA),
1890 root 1.67 const_iv (GL_ONE_MINUS_DST_ALPHA),
1891 root 1.104 const_iv (GL_SRC_ALPHA_SATURATE),
1892 root 1.54 const_iv (GL_RGB),
1893     const_iv (GL_RGBA),
1894 root 1.115 const_iv (GL_RGBA4),
1895     const_iv (GL_RGBA8),
1896     const_iv (GL_RGB5_A1),
1897 root 1.54 const_iv (GL_UNSIGNED_BYTE),
1898 root 1.89 const_iv (GL_UNSIGNED_SHORT),
1899     const_iv (GL_UNSIGNED_INT),
1900 root 1.54 const_iv (GL_ALPHA),
1901 root 1.86 const_iv (GL_INTENSITY),
1902 root 1.76 const_iv (GL_LUMINANCE),
1903 root 1.86 const_iv (GL_LUMINANCE_ALPHA),
1904 root 1.54 const_iv (GL_FLOAT),
1905     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1906     const_iv (GL_COMPILE),
1907     const_iv (GL_TEXTURE_1D),
1908     const_iv (GL_TEXTURE_2D),
1909     const_iv (GL_TEXTURE_ENV),
1910     const_iv (GL_TEXTURE_MAG_FILTER),
1911     const_iv (GL_TEXTURE_MIN_FILTER),
1912     const_iv (GL_TEXTURE_ENV_MODE),
1913     const_iv (GL_TEXTURE_WRAP_S),
1914     const_iv (GL_TEXTURE_WRAP_T),
1915 root 1.98 const_iv (GL_REPEAT),
1916 root 1.54 const_iv (GL_CLAMP),
1917 root 1.98 const_iv (GL_CLAMP_TO_EDGE),
1918 root 1.54 const_iv (GL_NEAREST),
1919     const_iv (GL_LINEAR),
1920 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
1921     const_iv (GL_LINEAR_MIPMAP_NEAREST),
1922     const_iv (GL_NEAREST_MIPMAP_LINEAR),
1923     const_iv (GL_LINEAR_MIPMAP_LINEAR),
1924     const_iv (GL_GENERATE_MIPMAP),
1925 root 1.54 const_iv (GL_MODULATE),
1926 root 1.69 const_iv (GL_DECAL),
1927 root 1.54 const_iv (GL_REPLACE),
1928 root 1.89 const_iv (GL_DEPTH_BUFFER_BIT),
1929 root 1.54 const_iv (GL_COLOR_BUFFER_BIT),
1930     const_iv (GL_PROJECTION),
1931     const_iv (GL_MODELVIEW),
1932     const_iv (GL_COLOR_LOGIC_OP),
1933 root 1.69 const_iv (GL_SEPARABLE_2D),
1934 root 1.54 const_iv (GL_CONVOLUTION_2D),
1935     const_iv (GL_CONVOLUTION_BORDER_MODE),
1936     const_iv (GL_CONSTANT_BORDER),
1937     const_iv (GL_LINES),
1938 root 1.138 const_iv (GL_LINE_STRIP),
1939 root 1.89 const_iv (GL_LINE_LOOP),
1940 root 1.54 const_iv (GL_QUADS),
1941 root 1.89 const_iv (GL_QUAD_STRIP),
1942     const_iv (GL_TRIANGLES),
1943     const_iv (GL_TRIANGLE_STRIP),
1944     const_iv (GL_TRIANGLE_FAN),
1945 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1946     const_iv (GL_FASTEST),
1947 root 1.89 const_iv (GL_V2F),
1948     const_iv (GL_V3F),
1949     const_iv (GL_T2F_V3F),
1950     const_iv (GL_T2F_N3F_V3F),
1951 root 1.54 # undef const_iv
1952     };
1953    
1954     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1955     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1956     }
1957    
1958 root 1.97 char *
1959     gl_vendor ()
1960     CODE:
1961     RETVAL = (char *)glGetString (GL_VENDOR);
1962     OUTPUT:
1963     RETVAL
1964    
1965     char *
1966     gl_version ()
1967     CODE:
1968     RETVAL = (char *)glGetString (GL_VERSION);
1969     OUTPUT:
1970     RETVAL
1971    
1972     char *
1973     gl_extensions ()
1974     CODE:
1975     RETVAL = (char *)glGetString (GL_EXTENSIONS);
1976     OUTPUT:
1977     RETVAL
1978    
1979 root 1.54 int glGetError ()
1980    
1981 root 1.114 void glFinish ()
1982    
1983 root 1.54 void glClear (int mask)
1984    
1985     void glClearColor (float r, float g, float b, float a = 1.0)
1986     PROTOTYPE: @
1987    
1988     void glEnable (int cap)
1989    
1990     void glDisable (int cap)
1991    
1992     void glShadeModel (int mode)
1993    
1994     void glHint (int target, int mode)
1995    
1996     void glBlendFunc (int sfactor, int dfactor)
1997    
1998 root 1.103 void glBlendFuncSeparate (int sa, int da, int saa, int daa)
1999     CODE:
2000     gl_BlendFuncSeparate (sa, da, saa, daa);
2001    
2002 root 1.89 void glDepthMask (int flag)
2003    
2004 root 1.54 void glLogicOp (int opcode)
2005    
2006 root 1.68 void glColorMask (int red, int green, int blue, int alpha)
2007    
2008 root 1.54 void glMatrixMode (int mode)
2009    
2010     void glPushMatrix ()
2011    
2012     void glPopMatrix ()
2013    
2014     void glLoadIdentity ()
2015    
2016 root 1.119 void glDrawBuffer (int buffer)
2017    
2018     void glReadBuffer (int buffer)
2019    
2020 root 1.90 # near_ and far_ are due to microsofts buggy "c" compiler
2021     void glFrustum (double left, double right, double bottom, double top, double near_, double far_)
2022    
2023     # near_ and far_ are due to microsofts buggy "c" compiler
2024 root 1.64 void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
2025 root 1.54
2026     void glViewport (int x, int y, int width, int height)
2027    
2028 root 1.69 void glScissor (int x, int y, int width, int height)
2029    
2030 root 1.54 void glTranslate (float x, float y, float z = 0.)
2031     CODE:
2032     glTranslatef (x, y, z);
2033    
2034 root 1.62 void glScale (float x, float y, float z = 1.)
2035 root 1.54 CODE:
2036     glScalef (x, y, z);
2037    
2038     void glRotate (float angle, float x, float y, float z)
2039     CODE:
2040     glRotatef (angle, x, y, z);
2041    
2042     void glBegin (int mode)
2043    
2044     void glEnd ()
2045    
2046     void glColor (float r, float g, float b, float a = 1.0)
2047     PROTOTYPE: @
2048 root 1.103 ALIAS:
2049     glColor_premultiply = 1
2050 root 1.54 CODE:
2051 root 1.103 if (ix)
2052     {
2053     r *= a;
2054     g *= a;
2055     b *= a;
2056     }
2057 root 1.90 // microsoft visual "c" rounds instead of truncating...
2058 root 1.130 glColor4f (r, g, b, a);
2059 root 1.54
2060 root 1.89 void glInterleavedArrays (int format, int stride, char *data)
2061    
2062     void glDrawElements (int mode, int count, int type, char *indices)
2063    
2064     # 1.2 void glDrawRangeElements (int mode, int start, int end
2065    
2066 root 1.91 void glRasterPos (float x, float y, float z = 0.)
2067     CODE:
2068     glRasterPos3f (0, 0, z);
2069     glBitmap (0, 0, 0, 0, x, y, 0);
2070    
2071 root 1.54 void glVertex (float x, float y, float z = 0.)
2072     CODE:
2073     glVertex3f (x, y, z);
2074    
2075     void glTexCoord (float s, float t)
2076     CODE:
2077     glTexCoord2f (s, t);
2078    
2079     void glTexEnv (int target, int pname, float param)
2080     CODE:
2081     glTexEnvf (target, pname, param);
2082    
2083     void glTexParameter (int target, int pname, float param)
2084     CODE:
2085     glTexParameterf (target, pname, param);
2086    
2087     void glBindTexture (int target, int name)
2088    
2089     void glConvolutionParameter (int target, int pname, float params)
2090     CODE:
2091 root 1.103 if (gl.ConvolutionParameterf)
2092     gl.ConvolutionParameterf (target, pname, params);
2093 root 1.54
2094     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
2095 root 1.64 CODE:
2096 root 1.103 if (gl.ConvolutionFilter2D)
2097     gl.ConvolutionFilter2D (target, internalformat, width, height, format, type, data);
2098 root 1.54
2099 root 1.69 void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
2100     CODE:
2101 root 1.103 if (gl.SeparableFilter2D)
2102     gl.SeparableFilter2D (target, internalformat, width, height, format, type, row, column);
2103 root 1.69
2104 root 1.54 void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
2105    
2106     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
2107    
2108 root 1.91 void glDrawPixels (int width, int height, int format, int type, char *pixels)
2109 root 1.68
2110     void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
2111    
2112 root 1.54 int glGenTexture ()
2113     CODE:
2114     {
2115     GLuint name;
2116     glGenTextures (1, &name);
2117     RETVAL = name;
2118     }
2119     OUTPUT:
2120     RETVAL
2121    
2122     void glDeleteTexture (int name)
2123     CODE:
2124     {
2125     GLuint name_ = name;
2126     glDeleteTextures (1, &name_);
2127     }
2128    
2129     int glGenList ()
2130     CODE:
2131     RETVAL = glGenLists (1);
2132     OUTPUT:
2133     RETVAL
2134    
2135     void glDeleteList (int list)
2136     CODE:
2137     glDeleteLists (list, 1);
2138    
2139     void glNewList (int list, int mode = GL_COMPILE)
2140    
2141     void glEndList ()
2142    
2143     void glCallList (int list)
2144