ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.150
Committed: Sat Aug 19 17:24:39 2006 UTC (17 years, 8 months ago) by root
Branch: MAIN
Changes since 1.149: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

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