ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.155
Committed: Thu Sep 21 00:16:42 2006 UTC (17 years, 7 months ago) by root
Branch: MAIN
Changes since 1.154: +1 -6 lines
Log Message:
fix map cleared-too-much bug

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.155 cell->darkness = 0;
1358 root 1.29 }
1359 root 1.28 }
1360    
1361 root 1.40 SV *
1362 root 1.133 mapmap (CFPlus::Map self, int x0, int y0, int w, int h)
1363 root 1.40 CODE:
1364     {
1365 root 1.55 int x1, x;
1366     int y1, y;
1367 root 1.40 int z;
1368     SV *map_sv = newSV (w * h * sizeof (uint32_t));
1369     uint32_t *map = (uint32_t *)SvPVX (map_sv);
1370    
1371     SvPOK_only (map_sv);
1372     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
1373    
1374 root 1.55 x0 += self->x; x1 = x0 + w;
1375     y0 += self->y; y1 = y0 + h;
1376 root 1.40
1377     for (y = y0; y < y1; y++)
1378     {
1379     maprow *row = 0 <= y && y < self->rows
1380     ? self->row + y
1381     : 0;
1382    
1383     for (x = x0; x < x1; x++)
1384     {
1385     int r = 32, g = 32, b = 32, a = 192;
1386    
1387     if (row && row->c0 <= x && x < row->c1)
1388     {
1389     mapcell *cell = row->col + (x - row->c0);
1390    
1391     for (z = 0; z <= 0; z++)
1392     {
1393 root 1.42 mapface face = cell->face [z];
1394 root 1.40
1395     if (face)
1396     {
1397 root 1.42 maptex tex = self->tex [face];
1398 root 1.40 int a0 = 255 - tex.a;
1399     int a1 = tex.a;
1400    
1401     r = (r * a0 + tex.r * a1) / 255;
1402     g = (g * a0 + tex.g * a1) / 255;
1403     b = (b * a0 + tex.b * a1) / 255;
1404     a = (a * a0 + tex.a * a1) / 255;
1405     }
1406     }
1407     }
1408    
1409     *map++ = (r )
1410     | (g << 8)
1411     | (b << 16)
1412     | (a << 24);
1413     }
1414     }
1415    
1416     RETVAL = map_sv;
1417     }
1418     OUTPUT:
1419     RETVAL
1420    
1421 root 1.30 void
1422 root 1.133 draw (CFPlus::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1423 root 1.116 CODE:
1424 root 1.30 {
1425 root 1.48 int vx, vy;
1426     int x, y, z;
1427     int last_name;
1428     mapface face;
1429    
1430 root 1.120 vx = self->x + self->w / 2 - sw / 2 - shift_x;
1431     vy = self->y + self->h / 2 - sh / 2 - shift_y;
1432 root 1.38
1433 root 1.42 /*
1434     int vx = self->vx = self->w >= sw
1435     ? self->x + (self->w - sw) / 2
1436     : MIN (self->x, MAX (self->x + self->w - sw + 1, self->vx));
1437    
1438     int vy = self->vy = self->h >= sh
1439     ? self->y + (self->h - sh) / 2
1440     : MIN (self->y, MAX (self->y + self->h - sh + 1, self->vy));
1441     */
1442 root 1.30
1443     glColor4ub (255, 255, 255, 255);
1444    
1445 root 1.117 glEnable (GL_BLEND);
1446 root 1.30 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1447     glEnable (GL_TEXTURE_2D);
1448     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1449    
1450 root 1.48 glBegin (GL_QUADS);
1451 root 1.30
1452 root 1.48 last_name = 0;
1453 root 1.30
1454     for (z = 0; z < 3; z++)
1455     for (y = 0; y < sh; y++)
1456     if (0 <= y + vy && y + vy < self->rows)
1457     {
1458     maprow *row = self->row + (y + vy);
1459    
1460     for (x = 0; x < sw; x++)
1461     if (row->c0 <= x + vx && x + vx < row->c1)
1462     {
1463     mapcell *cell = row->col + (x + vx - row->c0);
1464 root 1.32
1465 root 1.48 face = cell->face [z];
1466 root 1.30
1467 root 1.145 if (face && face < self->texs)
1468 root 1.30 {
1469 root 1.42 maptex tex = self->tex [face];
1470 root 1.30 int px = (x + 1) * 32 - tex.w;
1471     int py = (y + 1) * 32 - tex.h;
1472    
1473     if (last_name != tex.name)
1474     {
1475     glEnd ();
1476 root 1.153 glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1477 root 1.30 glBegin (GL_QUADS);
1478     }
1479    
1480     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1481     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1482     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1483     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1484     }
1485 root 1.153
1486     if (cell->flags && z == 2)
1487     {
1488     if (cell->flags & 1)
1489     {
1490     maptex tex = self->tex [1];
1491     int px = (x + 1) * 32 - tex.w + 2;
1492     int py = (y + 1) * 32 - tex.h - 6;
1493    
1494     glEnd ();
1495     glBindTexture (GL_TEXTURE_2D, last_name = tex.name);
1496     glBegin (GL_QUADS);
1497    
1498     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1499     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1500     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1501     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1502     }
1503     }
1504 root 1.30 }
1505     }
1506    
1507     glEnd ();
1508 root 1.32
1509 root 1.34 glDisable (GL_TEXTURE_2D);
1510 root 1.152 glDisable (GL_BLEND);
1511 root 1.143
1512 root 1.145 // top layer: overlays such as the health bar
1513 root 1.143 for (y = 0; y < sh; y++)
1514     if (0 <= y + vy && y + vy < self->rows)
1515     {
1516     maprow *row = self->row + (y + vy);
1517    
1518     for (x = 0; x < sw; x++)
1519     if (row->c0 <= x + vx && x + vx < row->c1)
1520     {
1521     mapcell *cell = row->col + (x + vx - row->c0);
1522    
1523     int px = x * 32;
1524     int py = y * 32;
1525    
1526     if (cell->stat_hp)
1527     {
1528 root 1.147 int width = cell->stat_width * 32;
1529     int thick = sh / 28 + 1 + cell->stat_width;
1530 root 1.143
1531 root 1.152 glColor3ub (0, 0, 0);
1532 root 1.151 glRectf (px + 1, py - thick - 2,
1533     px + width - 1, py);
1534 root 1.147
1535 root 1.152 glColor3ub (cell->stat_hp, 255 - cell->stat_hp, 0);
1536 root 1.147 glRectf (px + 2,
1537 root 1.151 py - thick - 1,
1538     px + width - 2 - cell->stat_hp * (width - 4) / 255, py - 1);
1539 root 1.143 }
1540     }
1541     }
1542 root 1.116 }
1543    
1544     void
1545 root 1.133 draw_magicmap (CFPlus::Map self, int dx, int dy, int w, int h, unsigned char *data)
1546 root 1.117 CODE:
1547     {
1548     static float color[16][3] = {
1549 root 1.123 { 0.00F, 0.00F, 0.00F },
1550     { 1.00F, 1.00F, 1.00F },
1551     { 0.00F, 0.00F, 0.55F },
1552     { 1.00F, 0.00F, 0.00F },
1553    
1554     { 1.00F, 0.54F, 0.00F },
1555     { 0.11F, 0.56F, 1.00F },
1556     { 0.93F, 0.46F, 0.00F },
1557     { 0.18F, 0.54F, 0.34F },
1558    
1559     { 0.56F, 0.73F, 0.56F },
1560     { 0.80F, 0.80F, 0.80F },
1561     { 0.55F, 0.41F, 0.13F },
1562     { 0.99F, 0.77F, 0.26F },
1563    
1564     { 0.74F, 0.65F, 0.41F },
1565    
1566     { 0.00F, 1.00F, 1.00F },
1567     { 1.00F, 0.00F, 1.00F },
1568     { 1.00F, 1.00F, 0.00F },
1569 root 1.117 };
1570    
1571     int x, y;
1572    
1573     glEnable (GL_TEXTURE_2D);
1574     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1575     glEnable (GL_BLEND);
1576     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1577     glBegin (GL_QUADS);
1578    
1579     for (y = 0; y < h; y++)
1580     for (x = 0; x < w; x++)
1581     {
1582     unsigned char m = data [x + y * w];
1583    
1584 root 1.118 if (m)
1585     {
1586     float *c = color [m & 15];
1587    
1588     float tx1 = m & 0x40 ? 0.5 : 0.;
1589     float tx2 = tx1 + 0.5;
1590    
1591     glColor4f (c[0], c[1], c[2], 0.75);
1592     glTexCoord2f (tx1, 0.); glVertex2i (x , y );
1593     glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
1594     glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
1595     glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
1596     }
1597 root 1.117 }
1598    
1599     glEnd ();
1600     glDisable (GL_BLEND);
1601     glDisable (GL_TEXTURE_2D);
1602     }
1603    
1604     void
1605 root 1.133 fow_texture (CFPlus::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1606 root 1.116 PPCODE:
1607     {
1608     int vx, vy;
1609     int x, y;
1610     int sw4 = (sw + 3) & ~3;
1611     SV *darkness_sv = sv_2mortal (newSV (sw4 * sh));
1612     uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv);
1613    
1614     memset (darkness, 255, sw4 * sh);
1615     SvPOK_only (darkness_sv);
1616     SvCUR_set (darkness_sv, sw4 * sh);
1617    
1618     vx = self->x + (self->w - sw + 1) / 2 - shift_x;
1619     vy = self->y + (self->h - sh + 1) / 2 - shift_y;
1620    
1621     for (y = 0; y < sh; y++)
1622     if (0 <= y + vy && y + vy < self->rows)
1623     {
1624     maprow *row = self->row + (y + vy);
1625    
1626     for (x = 0; x < sw; x++)
1627     if (row->c0 <= x + vx && x + vx < row->c1)
1628     {
1629     mapcell *cell = row->col + (x + vx - row->c0);
1630    
1631 root 1.142 darkness[y * sw4 + x] = cell->darkness
1632 root 1.143 ? 255 - (cell->darkness - 1)
1633 root 1.142 : 255 - FOW_DARKNESS;
1634 root 1.116 }
1635     }
1636 root 1.34
1637 root 1.32 EXTEND (SP, 3);
1638     PUSHs (sv_2mortal (newSViv (sw4)));
1639     PUSHs (sv_2mortal (newSViv (sh)));
1640     PUSHs (darkness_sv);
1641 root 1.30 }
1642    
1643 root 1.42 SV *
1644 root 1.133 get_rect (CFPlus::Map self, int x0, int y0, int w, int h)
1645 root 1.42 CODE:
1646     {
1647     int x, y, x1, y1;
1648     SV *data_sv = newSV (w * h * 7 + 5);
1649     uint8_t *data = (uint8_t *)SvPVX (data_sv);
1650    
1651     *data++ = 0; /* version 0 format */
1652     *data++ = w >> 8; *data++ = w;
1653     *data++ = h >> 8; *data++ = h;
1654    
1655     // we need to do this 'cause we don't keep an absolute coord system for rows
1656 root 1.55 // TODO: treat rows as we treat columns
1657 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1658     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1659    
1660     x0 += self->x - self->ox;
1661     y0 += self->y - self->oy;
1662    
1663     x1 = x0 + w;
1664     y1 = y0 + h;
1665    
1666     for (y = y0; y < y1; y++)
1667     {
1668     maprow *row = 0 <= y && y < self->rows
1669     ? self->row + y
1670     : 0;
1671    
1672     for (x = x0; x < x1; x++)
1673     {
1674     if (row && row->c0 <= x && x < row->c1)
1675     {
1676     mapcell *cell = row->col + (x - row->c0);
1677     uint8_t flags = 0;
1678    
1679     if (cell->face [0]) flags |= 1;
1680     if (cell->face [1]) flags |= 2;
1681     if (cell->face [2]) flags |= 4;
1682    
1683     *data++ = flags;
1684    
1685     if (flags & 1)
1686     {
1687     *data++ = cell->face [0] >> 8;
1688     *data++ = cell->face [0];
1689     }
1690    
1691     if (flags & 2)
1692     {
1693     *data++ = cell->face [1] >> 8;
1694     *data++ = cell->face [1];
1695     }
1696    
1697     if (flags & 4)
1698     {
1699     *data++ = cell->face [2] >> 8;
1700     *data++ = cell->face [2];
1701     }
1702     }
1703     else
1704     *data++ = 0;
1705     }
1706     }
1707    
1708     SvPOK_only (data_sv);
1709     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
1710     RETVAL = data_sv;
1711     }
1712     OUTPUT:
1713     RETVAL
1714    
1715     void
1716 root 1.133 set_rect (CFPlus::Map self, int x0, int y0, uint8_t *data)
1717 root 1.42 PPCODE:
1718     {
1719     int x, y, z;
1720 root 1.48 int w, h;
1721 root 1.42 int x1, y1;
1722    
1723     if (*data++ != 0)
1724     return; /* version mismatch */
1725    
1726 root 1.48 w = *data++ << 8; w |= *data++;
1727     h = *data++ << 8; h |= *data++;
1728 root 1.42
1729     // we need to do this 'cause we don't keep an absolute coord system for rows
1730 root 1.55 // TODO: treat rows as we treat columns
1731 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1732     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1733    
1734     x0 += self->x - self->ox;
1735     y0 += self->y - self->oy;
1736    
1737     x1 = x0 + w;
1738     y1 = y0 + h;
1739    
1740     for (y = y0; y < y1; y++)
1741     {
1742     maprow *row = map_get_row (self, y);
1743    
1744     for (x = x0; x < x1; x++)
1745     {
1746     uint8_t flags = *data++;
1747    
1748     if (flags)
1749     {
1750     mapface face[3] = { 0, 0, 0 };
1751    
1752     mapcell *cell = row_get_cell (row, x);
1753    
1754     if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; }
1755     if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; }
1756     if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; }
1757    
1758 root 1.143 if (cell->darkness == 0)
1759 root 1.42 {
1760 root 1.142 cell->darkness = 0;
1761 root 1.42
1762     for (z = 0; z <= 2; z++)
1763     {
1764     cell->face[z] = face[z];
1765    
1766     if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name))
1767     XPUSHs (sv_2mortal (newSViv (face[z])));
1768     }
1769     }
1770     }
1771     }
1772     }
1773     }
1774    
1775 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixChunk
1776 root 1.52
1777 root 1.133 CFPlus::MixChunk
1778 root 1.52 new_from_file (SV *class, char *path)
1779     CODE:
1780     RETVAL = Mix_LoadWAV (path);
1781     OUTPUT:
1782     RETVAL
1783    
1784     void
1785 root 1.133 DESTROY (CFPlus::MixChunk self)
1786 root 1.52 CODE:
1787     Mix_FreeChunk (self);
1788    
1789     int
1790 root 1.133 volume (CFPlus::MixChunk self, int volume = -1)
1791 root 1.52 CODE:
1792     RETVAL = Mix_VolumeChunk (self, volume);
1793     OUTPUT:
1794     RETVAL
1795    
1796     int
1797 root 1.133 play (CFPlus::MixChunk self, int channel = -1, int loops = 0, int ticks = -1)
1798 root 1.52 CODE:
1799     RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
1800     OUTPUT:
1801     RETVAL
1802    
1803 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::MixMusic
1804 root 1.52
1805     int
1806     volume (int volume = -1)
1807     CODE:
1808     RETVAL = Mix_VolumeMusic (volume);
1809     OUTPUT:
1810     RETVAL
1811    
1812 root 1.133 CFPlus::MixMusic
1813 root 1.52 new_from_file (SV *class, char *path)
1814     CODE:
1815     RETVAL = Mix_LoadMUS (path);
1816     OUTPUT:
1817     RETVAL
1818    
1819     void
1820 root 1.133 DESTROY (CFPlus::MixMusic self)
1821 root 1.52 CODE:
1822     Mix_FreeMusic (self);
1823    
1824     int
1825 root 1.133 play (CFPlus::MixMusic self, int loops = -1)
1826 root 1.52 CODE:
1827     RETVAL = Mix_PlayMusic (self, loops);
1828     OUTPUT:
1829     RETVAL
1830    
1831 root 1.133 MODULE = CFPlus PACKAGE = CFPlus::OpenGL
1832 root 1.54
1833     BOOT:
1834     {
1835 root 1.133 HV *stash = gv_stashpv ("CFPlus::OpenGL", 1);
1836 root 1.54 static const struct {
1837     const char *name;
1838     IV iv;
1839     } *civ, const_iv[] = {
1840     # define const_iv(name) { # name, (IV)name }
1841     const_iv (GL_COLOR_MATERIAL),
1842     const_iv (GL_SMOOTH),
1843     const_iv (GL_FLAT),
1844 root 1.69 const_iv (GL_DITHER),
1845 root 1.54 const_iv (GL_BLEND),
1846 root 1.89 const_iv (GL_CULL_FACE),
1847 root 1.69 const_iv (GL_SCISSOR_TEST),
1848 root 1.89 const_iv (GL_DEPTH_TEST),
1849     const_iv (GL_ALPHA_TEST),
1850     const_iv (GL_NORMALIZE),
1851     const_iv (GL_RESCALE_NORMAL),
1852 root 1.119 const_iv (GL_FRONT),
1853     const_iv (GL_BACK),
1854 root 1.54 const_iv (GL_AND),
1855 root 1.67 const_iv (GL_ONE),
1856     const_iv (GL_ZERO),
1857 root 1.54 const_iv (GL_SRC_ALPHA),
1858 root 1.104 const_iv (GL_DST_ALPHA),
1859 root 1.54 const_iv (GL_ONE_MINUS_SRC_ALPHA),
1860 root 1.67 const_iv (GL_ONE_MINUS_DST_ALPHA),
1861 root 1.104 const_iv (GL_SRC_ALPHA_SATURATE),
1862 root 1.54 const_iv (GL_RGB),
1863     const_iv (GL_RGBA),
1864 root 1.115 const_iv (GL_RGBA4),
1865     const_iv (GL_RGBA8),
1866     const_iv (GL_RGB5_A1),
1867 root 1.54 const_iv (GL_UNSIGNED_BYTE),
1868 root 1.89 const_iv (GL_UNSIGNED_SHORT),
1869     const_iv (GL_UNSIGNED_INT),
1870 root 1.54 const_iv (GL_ALPHA),
1871 root 1.86 const_iv (GL_INTENSITY),
1872 root 1.76 const_iv (GL_LUMINANCE),
1873 root 1.86 const_iv (GL_LUMINANCE_ALPHA),
1874 root 1.54 const_iv (GL_FLOAT),
1875     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1876     const_iv (GL_COMPILE),
1877     const_iv (GL_TEXTURE_1D),
1878     const_iv (GL_TEXTURE_2D),
1879     const_iv (GL_TEXTURE_ENV),
1880     const_iv (GL_TEXTURE_MAG_FILTER),
1881     const_iv (GL_TEXTURE_MIN_FILTER),
1882     const_iv (GL_TEXTURE_ENV_MODE),
1883     const_iv (GL_TEXTURE_WRAP_S),
1884     const_iv (GL_TEXTURE_WRAP_T),
1885 root 1.98 const_iv (GL_REPEAT),
1886 root 1.54 const_iv (GL_CLAMP),
1887 root 1.98 const_iv (GL_CLAMP_TO_EDGE),
1888 root 1.54 const_iv (GL_NEAREST),
1889     const_iv (GL_LINEAR),
1890 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
1891     const_iv (GL_LINEAR_MIPMAP_NEAREST),
1892     const_iv (GL_NEAREST_MIPMAP_LINEAR),
1893     const_iv (GL_LINEAR_MIPMAP_LINEAR),
1894     const_iv (GL_GENERATE_MIPMAP),
1895 root 1.54 const_iv (GL_MODULATE),
1896 root 1.69 const_iv (GL_DECAL),
1897 root 1.54 const_iv (GL_REPLACE),
1898 root 1.89 const_iv (GL_DEPTH_BUFFER_BIT),
1899 root 1.54 const_iv (GL_COLOR_BUFFER_BIT),
1900     const_iv (GL_PROJECTION),
1901     const_iv (GL_MODELVIEW),
1902     const_iv (GL_COLOR_LOGIC_OP),
1903 root 1.69 const_iv (GL_SEPARABLE_2D),
1904 root 1.54 const_iv (GL_CONVOLUTION_2D),
1905     const_iv (GL_CONVOLUTION_BORDER_MODE),
1906     const_iv (GL_CONSTANT_BORDER),
1907     const_iv (GL_LINES),
1908 root 1.138 const_iv (GL_LINE_STRIP),
1909 root 1.89 const_iv (GL_LINE_LOOP),
1910 root 1.54 const_iv (GL_QUADS),
1911 root 1.89 const_iv (GL_QUAD_STRIP),
1912     const_iv (GL_TRIANGLES),
1913     const_iv (GL_TRIANGLE_STRIP),
1914     const_iv (GL_TRIANGLE_FAN),
1915 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1916     const_iv (GL_FASTEST),
1917 root 1.89 const_iv (GL_V2F),
1918     const_iv (GL_V3F),
1919     const_iv (GL_T2F_V3F),
1920     const_iv (GL_T2F_N3F_V3F),
1921 root 1.54 # undef const_iv
1922     };
1923    
1924     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1925     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1926     }
1927    
1928 root 1.97 char *
1929     gl_vendor ()
1930     CODE:
1931     RETVAL = (char *)glGetString (GL_VENDOR);
1932     OUTPUT:
1933     RETVAL
1934    
1935     char *
1936     gl_version ()
1937     CODE:
1938     RETVAL = (char *)glGetString (GL_VERSION);
1939     OUTPUT:
1940     RETVAL
1941    
1942     char *
1943     gl_extensions ()
1944     CODE:
1945     RETVAL = (char *)glGetString (GL_EXTENSIONS);
1946     OUTPUT:
1947     RETVAL
1948    
1949 root 1.54 int glGetError ()
1950    
1951 root 1.114 void glFinish ()
1952    
1953 root 1.54 void glClear (int mask)
1954    
1955     void glClearColor (float r, float g, float b, float a = 1.0)
1956     PROTOTYPE: @
1957    
1958     void glEnable (int cap)
1959    
1960     void glDisable (int cap)
1961    
1962     void glShadeModel (int mode)
1963    
1964     void glHint (int target, int mode)
1965    
1966     void glBlendFunc (int sfactor, int dfactor)
1967    
1968 root 1.103 void glBlendFuncSeparate (int sa, int da, int saa, int daa)
1969     CODE:
1970     gl_BlendFuncSeparate (sa, da, saa, daa);
1971    
1972 root 1.89 void glDepthMask (int flag)
1973    
1974 root 1.54 void glLogicOp (int opcode)
1975    
1976 root 1.68 void glColorMask (int red, int green, int blue, int alpha)
1977    
1978 root 1.54 void glMatrixMode (int mode)
1979    
1980     void glPushMatrix ()
1981    
1982     void glPopMatrix ()
1983    
1984     void glLoadIdentity ()
1985    
1986 root 1.119 void glDrawBuffer (int buffer)
1987    
1988     void glReadBuffer (int buffer)
1989    
1990 root 1.90 # near_ and far_ are due to microsofts buggy "c" compiler
1991     void glFrustum (double left, double right, double bottom, double top, double near_, double far_)
1992    
1993     # near_ and far_ are due to microsofts buggy "c" compiler
1994 root 1.64 void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
1995 root 1.54
1996     void glViewport (int x, int y, int width, int height)
1997    
1998 root 1.69 void glScissor (int x, int y, int width, int height)
1999    
2000 root 1.54 void glTranslate (float x, float y, float z = 0.)
2001     CODE:
2002     glTranslatef (x, y, z);
2003    
2004 root 1.62 void glScale (float x, float y, float z = 1.)
2005 root 1.54 CODE:
2006     glScalef (x, y, z);
2007    
2008     void glRotate (float angle, float x, float y, float z)
2009     CODE:
2010     glRotatef (angle, x, y, z);
2011    
2012     void glBegin (int mode)
2013    
2014     void glEnd ()
2015    
2016     void glColor (float r, float g, float b, float a = 1.0)
2017     PROTOTYPE: @
2018 root 1.103 ALIAS:
2019     glColor_premultiply = 1
2020 root 1.54 CODE:
2021 root 1.103 if (ix)
2022     {
2023     r *= a;
2024     g *= a;
2025     b *= a;
2026     }
2027 root 1.90 // microsoft visual "c" rounds instead of truncating...
2028 root 1.130 glColor4f (r, g, b, a);
2029 root 1.54
2030 root 1.89 void glInterleavedArrays (int format, int stride, char *data)
2031    
2032     void glDrawElements (int mode, int count, int type, char *indices)
2033    
2034     # 1.2 void glDrawRangeElements (int mode, int start, int end
2035    
2036 root 1.91 void glRasterPos (float x, float y, float z = 0.)
2037     CODE:
2038     glRasterPos3f (0, 0, z);
2039     glBitmap (0, 0, 0, 0, x, y, 0);
2040    
2041 root 1.54 void glVertex (float x, float y, float z = 0.)
2042     CODE:
2043     glVertex3f (x, y, z);
2044    
2045     void glTexCoord (float s, float t)
2046     CODE:
2047     glTexCoord2f (s, t);
2048    
2049     void glTexEnv (int target, int pname, float param)
2050     CODE:
2051     glTexEnvf (target, pname, param);
2052    
2053     void glTexParameter (int target, int pname, float param)
2054     CODE:
2055     glTexParameterf (target, pname, param);
2056    
2057     void glBindTexture (int target, int name)
2058    
2059     void glConvolutionParameter (int target, int pname, float params)
2060     CODE:
2061 root 1.103 if (gl.ConvolutionParameterf)
2062     gl.ConvolutionParameterf (target, pname, params);
2063 root 1.54
2064     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
2065 root 1.64 CODE:
2066 root 1.103 if (gl.ConvolutionFilter2D)
2067     gl.ConvolutionFilter2D (target, internalformat, width, height, format, type, data);
2068 root 1.54
2069 root 1.69 void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
2070     CODE:
2071 root 1.103 if (gl.SeparableFilter2D)
2072     gl.SeparableFilter2D (target, internalformat, width, height, format, type, row, column);
2073 root 1.69
2074 root 1.54 void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
2075    
2076     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
2077    
2078 root 1.91 void glDrawPixels (int width, int height, int format, int type, char *pixels)
2079 root 1.68
2080     void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
2081    
2082 root 1.54 int glGenTexture ()
2083     CODE:
2084     {
2085     GLuint name;
2086     glGenTextures (1, &name);
2087     RETVAL = name;
2088     }
2089     OUTPUT:
2090     RETVAL
2091    
2092     void glDeleteTexture (int name)
2093     CODE:
2094     {
2095     GLuint name_ = name;
2096     glDeleteTextures (1, &name_);
2097     }
2098    
2099     int glGenList ()
2100     CODE:
2101     RETVAL = glGenLists (1);
2102     OUTPUT:
2103     RETVAL
2104    
2105     void glDeleteList (int list)
2106     CODE:
2107     glDeleteLists (list, 1);
2108    
2109     void glNewList (int list, int mode = GL_COMPILE)
2110    
2111     void glEndList ()
2112    
2113     void glCallList (int list)
2114