#include #ifdef ALLEGRO_WINDOWS #include #endif #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include #include /* from gd.c */ BITMAP *load_memory_gd(unsigned char *gd, int len, RGB *pal); unsigned char *save_memory_gd(BITMAP *bmp, RGB *pal, int *len); /* avoid _mangled_main problems */ int main(int argc, char *argv[]) { return 0; } END_OF_MAIN(); #define MAX_TIMERS 256 static int timer_updates[MAX_TIMERS]; static int timer_count; static void timer_callback(void *p) { timer_updates[(int)p]++; } static PALETTE current_palette; static COLOR_MAP *alpha_color_map[256]; MODULE = Allegro PACKAGE = Allegro BOOT: { int i; for(i = 0; i < 256; i++) alpha_color_map[i] = NULL; timer_count = 0; } PROTOTYPES: ENABLE # # Lines starting with #: will be included in the function's description # in Allegro.pod. # #: This is similar to the real install_allegro, with the default values #: for the errno and atexit pointers. int al_install_allegro(system) int system CODE: RETVAL = install_allegro(system, &errno, NULL); OUTPUT: RETVAL #: Identical to allegro_init. int al_allegro_init() CODE: RETVAL = allegro_init(); OUTPUT: RETVAL #: Returns allegro_error[]. char * al_get_error() CODE: RETVAL = allegro_error; OUTPUT: RETVAL #: Returns a text string (ALLEGRO_VERSION_STR). char * al_get_version() CODE: RETVAL = ALLEGRO_VERSION_STR; OUTPUT: RETVAL #: Returns the font pointer. FONT * al_get_system_font() CODE: RETVAL = font; OUTPUT: RETVAL #: Returns the screen pointer. BITMAP * al_get_screen() CODE: RETVAL = screen; OUTPUT: RETVAL #: Returns the screen width, height, virtual width, virtual height. #: #: ($w, $h, $vw, $vh) = al_get_screen_size(); void al_get_screen_size() PPCODE: EXTEND(SP, 4); PUSHs(sv_2mortal(newSViv(SCREEN_W))); PUSHs(sv_2mortal(newSViv(SCREEN_H))); PUSHs(sv_2mortal(newSViv(VIRTUAL_W))); PUSHs(sv_2mortal(newSViv(VIRTUAL_H))); #: Returns gfx_capabilites. int al_get_gfx_capabilities() CODE: RETVAL = gfx_capabilities; OUTPUT: RETVAL #: Identical to allegro_message. void al_allegro_message(text) char *text CODE: allegro_message(text); #: Returns bitmap width and height. #: #: ($w, $h) = al_get_bitmap_size($bmp); void al_get_bitmap_size(bmp) BITMAP *bmp PPCODE: EXTEND(SP, 2); PUSHs(sv_2mortal(newSViv(bmp->w))); PUSHs(sv_2mortal(newSViv(bmp->h))); #: Returns bmp->clip, bmp->cl, bmp->cr, bmp->ct, bmp->cb. #: #: ($enable, $l, $r, $t, $b) = al_get_bitmap_clip($bmp); void al_get_bitmap_clip(bmp) BITMAP *bmp PPCODE: EXTEND(SP, 5); PUSHs(sv_2mortal(newSViv(bmp->clip))); PUSHs(sv_2mortal(newSViv(bmp->cl))); PUSHs(sv_2mortal(newSViv(bmp->cr))); PUSHs(sv_2mortal(newSViv(bmp->ct))); PUSHs(sv_2mortal(newSViv(bmp->cb))); #: Returns RLE sprite width and height. #: #: ($w, $h) = al_get_rle_size($rle); void al_get_rle_size(rle) RLE_SPRITE *rle PPCODE: EXTEND(SP, 2); PUSHs(sv_2mortal(newSViv(rle->w))); PUSHs(sv_2mortal(newSViv(rle->h))); #: Returns the color depth of an RLE sprite. int al_get_rle_depth(rle) RLE_SPRITE *rle CODE: RETVAL = rle->color_depth; OUTPUT: RETVAL #: Takes points as al_polygon(bmp, color, x1, y1, x2, y2, x3, y3, x4, y4, #: ...) and calls polygon. void al_polygon(bmp, color, ...) BITMAP *bmp int color PREINIT: int points[512]; CODE: items -= 2; if(items >= 6 && items < 512) { int i; if(items % 2 != 0) items--; for(i = 0; i < items; i += 2) { points[i] = (int) SvIV(ST(2+i)); points[i+1] = (int) SvIV(ST(2+i+1)); } polygon(bmp, items/2, points, color); } #: Returns mouse_x, mouse_y, mouse_z, mouse_b. #: #: ($x, $y, $z, $b) = al_get_mouse_info(); void al_get_mouse_info() PPCODE: EXTEND(SP, 4); PUSHs(sv_2mortal(newSViv(mouse_x))); PUSHs(sv_2mortal(newSViv(mouse_y))); PUSHs(sv_2mortal(newSViv(mouse_z))); PUSHs(sv_2mortal(newSViv(mouse_b))); #: Returns the ascii and scancode values from ureadkey. #: #: ($ascii, $scan) = al_readkey(); void al_readkey() PREINIT: int ascii, scancode; PPCODE: ascii = ureadkey(&scancode); EXTEND(SP, 2); PUSHs(sv_2mortal(newSViv(ascii))); PUSHs(sv_2mortal(newSViv(scancode))); #: Calls simulate_ukeypress. void al_simulate_keypress(scancode) int scancode CODE: simulate_ukeypress(scancode_to_ascii(scancode), scancode); #: Returns a value from the key[] array. int al_get_key(k) int k CODE: RETVAL = key[k]; OUTPUT: RETVAL #: Returns key_shifts. int al_get_key_shifts() CODE: RETVAL = key_shifts; OUTPUT: RETVAL #: Returns the number of objects in a datafile. int al_get_datafile_size(dat) DATAFILE *dat PREINIT: int i = 0; CODE: while(dat[i].type != DAT_END) i++; RETVAL = i; OUTPUT: RETVAL #: Returns the datafile type. #: #: I may be either a pointer to a datafile object or a pointer to an #: array of datafile objects. #: #: I is the index into the array, or C<-1> if I is a datafile #: pointer. int al_get_datafile_type(dat, i) DATAFILE *dat int i CODE: if(i == -1) RETVAL = dat->type; else RETVAL = dat[i].type; OUTPUT: RETVAL #: Returns the data pointer. I and I are as in #: B. void * al_get_datafile_data(dat, i) DATAFILE *dat int i CODE: if(i == -1) RETVAL = dat->dat; else RETVAL = dat[i].dat; OUTPUT: RETVAL #: Returns the specified datafile property. #: #: I and I are as above. #: I is a string specifying the property. See the Allegro #: documentation for valid datafile properties. const char * al_get_datafile_property(dat, i, str) DATAFILE *dat int i const char *str PREINIT: int id; CODE: if(strlen(str) < 4) id = 0; else id = DAT_ID(str[0], str[1], str[2], str[3]); if(i == -1) RETVAL = get_datafile_property(dat, id); else RETVAL = get_datafile_property(&dat[i], id); OUTPUT: RETVAL #: Returns num_joysticks. int al_get_num_joysticks() CODE: RETVAL = num_joysticks; OUTPUT: RETVAL #: Returns joy[I].flags, joy[I].num_sticks, joy[I].num_buttons, #: or undef if I is out of range. #: #: ($flags, $sticks, $buttons) = al_get_joystick_info($i); void al_get_joystick_info(i) int i PPCODE: if(i >= 0 && i < num_joysticks) { EXTEND(SP, 3); PUSHs(sv_2mortal(newSViv(joy[i].flags))); PUSHs(sv_2mortal(newSViv(joy[i].num_sticks))); PUSHs(sv_2mortal(newSViv(joy[i].num_buttons))); } else XSRETURN_UNDEF; #: Returns joy[I].button[I].b and joy[I].button[I].name, or #: undef if I or I are out of range. #: #: ($status, $name) = al_get_joystick_button($i, $b); void al_get_joystick_button_info(i, b) int i int b PPCODE: if(i >= 0 && i < num_joysticks && b >= 0 && b < joy[i].num_buttons) { EXTEND(SP, 2); PUSHs(sv_2mortal(newSViv(joy[i].button[b].b))); PUSHs(sv_2mortal(newSVpv(joy[i].button[b].name, 0))); } else XSRETURN_UNDEF; #: Returns joy[I].stick[I].flags, joy[I].stick[I].num_axis, #: and joy[I].stick[I].name, or undef if I or I are out of #: of range. #: #: ($flags, $axes, $name) = al_get_joystick_info($i, $s); void al_get_joystick_stick_info(i, s) int i int s PPCODE: if(i >= 0 && i < num_joysticks && s >= 0 && s < joy[i].num_sticks) { EXTEND(SP, 3); PUSHs(sv_2mortal(newSViv(joy[i].stick[s].flags))); PUSHs(sv_2mortal(newSViv(joy[i].stick[s].num_axis))); PUSHs(sv_2mortal(newSVpv(joy[i].stick[s].name, 0))); } else XSRETURN_UNDEF; #: Returns analog position, digital position, and name of specified axis. #: #: Analog is joy[I].stick[I].axis[I].pos. Digital is C<-1> for #: left/up, C<1> for right/down, or C<0> for centered (based on #: joy[I].stick[I].axis[I].d1 and d2). Name is #: joy[I].stick[I].axis[I].name. #: #: ($a, $d, $name) = al_get_joystick_info($i, $s, $a); void al_get_joystick_axis_info(i, s, a) int i int s int a PREINIT: int digital; PPCODE: if(i >= 0 && i < num_joysticks && s >= 0 && s < joy[i].num_sticks && a >= 0 && a < joy[i].stick[s].num_axis) { if(joy[i].stick[s].axis[a].d1) digital = -1; else if(joy[i].stick[s].axis[a].d2) digital = 1; else digital = 0; EXTEND(SP, 3); PUSHs(sv_2mortal(newSViv(joy[i].stick[s].axis[a].pos))); PUSHs(sv_2mortal(newSViv(digital))); PUSHs(sv_2mortal(newSVpv(joy[i].stick[s].axis[a].name, 0))); } else XSRETURN_UNDEF; #: Sets freeze_mouse_flag to I. void al_set_freeze_mouse(status) int status CODE: freeze_mouse_flag = status; #: Returns midi_pos, midi_loop_start, midi_loop_end. #: #: ($pos, $start, $end) = al_get_midi_info(); void al_get_midi_info() PPCODE: EXTEND(SP, 3); PUSHs(sv_2mortal(newSViv(midi_pos))); PUSHs(sv_2mortal(newSViv(midi_loop_start))); PUSHs(sv_2mortal(newSViv(midi_loop_end))); BITMAP * _load_memory_gd(data, len, pal) unsigned char *data int len RGB *pal CODE: RETVAL = load_memory_gd(data, len, pal); OUTPUT: RETVAL unsigned char * _create_gd(bmp, pal) BITMAP *bmp RGB *pal CODE: RETVAL = save_memory_gd(bmp, pal, NULL); OUTPUT: RETVAL void _destroy_gd(data) unsigned char *data CODE: free(data); #: Mallocs a new palette and returns it. RGB * al_create_palette() CODE: RETVAL = malloc(sizeof(RGB) * 256); OUTPUT: RETVAL #: Frees a previously allocated palette. void al_destroy_palette(pal) RGB *pal CODE: if(pal) free(pal); #: Sets I's index I to the specified color. Colors are 0-255 #: instead of Allegro's 0-63. void al_set_palette_color(pal, i, r, g, b) RGB *pal int i int r int g int b CODE: pal[i].r = r / 4; pal[i].g = g / 4; pal[i].b = b / 4; #: Returns I's red, green, blue values for index I. Colors are #: 0-255 instead of Allegro's 0-63. #: #: ($r, $g, $b) = al_get_palette_color($pal, $i); void al_get_palette_color(pal, i) RGB *pal int i PPCODE: EXTEND(SP, 3); PUSHs(sv_2mortal(newSViv(pal[i].r * 4))); PUSHs(sv_2mortal(newSViv(pal[i].g * 4))); PUSHs(sv_2mortal(newSViv(pal[i].b * 4))); #: Timers: the timer functions below use Allegro's timer system, but will #: not automatically call a Perl subroutine when fired. #: #: They must be checked via B. See Allegro/Timer.pm #: for an example. #: #: Initializes a new timer. Returns an id to be used by the other timer #: routines below. int al_create_timer() CODE: if(timer_count == MAX_TIMERS - 1) RETVAL = -1; else { timer_updates[timer_count] = 0; RETVAL = timer_count; timer_count++; } OUTPUT: RETVAL #: Starts a previously initialized timer. #: #: I is the timer id and I is the time between timer updates. #: Returns true on success, false on failure. int al_start_timer(id, speed) int id double speed CODE: if(id >= 0 && id < MAX_TIMERS) { timer_updates[timer_count] = 0; if(speed < 1.0) install_param_int_ex(timer_callback, (void *)timer_count, BPS_TO_TIMER(1 / speed)); else install_param_int_ex(timer_callback, (void *)timer_count, MSEC_TO_TIMER(speed * 1000.0)); RETVAL = 1; } else RETVAL = 0; OUTPUT: RETVAL #: Stops a timer. #: #: I is the timer id. int al_stop_timer(id) int id CODE: if(id >= 0 && id < MAX_TIMERS) { remove_param_int(timer_callback, (void *)id); RETVAL = 1; } else RETVAL = 0; OUTPUT: RETVAL #: Gets the number of times the timer code needs to be run. #: #: I is the timer id. int al_get_timer_updates(id) int id CODE: if(id >= 0 && id < MAX_TIMERS) RETVAL = timer_updates[id]; else RETVAL = -1; OUTPUT: RETVAL #: Decrements the update count. This should be called after each run of #: the timer code. #: #: I is the timer id. int al_decrement_timer(id) int id CODE: if(id >= 0 && id < MAX_TIMERS) { timer_updates[id]--; RETVAL = 1; } else RETVAL = 0; OUTPUT: RETVAL #: Returns an AL_ID from the specified (four-letter) string. int al_id(id) char *id CODE: if(strlen(id) < 4) RETVAL = -1; else RETVAL = AL_ID(id[0], id[1], id[2], id[3]); OUTPUT: RETVAL #: Destroys a previously created COLOR_MAP. void al_destroy_color_map(colormap) COLOR_MAP *colormap CODE: free(colormap); #: Sets color_map. void al_set_color_map(colormap) COLOR_MAP *colormap CODE: color_map = colormap; #: Retrieves color_map. COLOR_MAP * al_get_color_map() CODE: RETVAL = color_map; OUTPUT: RETVAL #: Allocates and returns a COLOR_MAP created by create_blender_table() #: based on the current truecolor blender mode that is set. COLOR_MAP * al_create_color_map(pal) RGB *pal PREINIT: COLOR_MAP *colormap; CODE: colormap = malloc(sizeof(COLOR_MAP)); if(colormap) { create_blender_table(colormap, pal, NULL); RETVAL = colormap; } else RETVAL = NULL; OUTPUT: RETVAL INCLUDE: auto.xsh