ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.161
Committed: Mon Oct 9 23:30:44 2006 UTC (17 years, 7 months ago) by root
Branch: MAIN
Changes since 1.160: +4 -2 lines
Log Message:
more win32 hacks

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