ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.154
Committed: Tue Sep 19 22:23:30 2006 UTC (17 years, 7 months ago) by root
Branch: MAIN
CVS Tags: rel-0_52
Changes since 1.153: +10 -7 lines
Log Message:
fix map blanking and a few minor items

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