ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.162
Committed: Fri Oct 13 19:23:08 2006 UTC (17 years, 7 months ago) by root
Branch: MAIN
Changes since 1.161: +2 -8 lines
Log Message:
vc60

File Contents

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