//----------------------------------------------------------------------------- // Capture_Screen(void) // Capture current screen to a file //----------------------------------------------------------------------------- static void Capture_Screen(void) { //PALETTE pal; BITMAP * bmp; BITMAP * source; char s1[FILENAME_LEN]; int x_start, x_len; int y_start, y_len; // Get a filename Capture_FileName_Get(s1); if (Capture.id_number >= CAPTURE_ID_MAX) { Msg(MSGT_USER, Msg_Get(MSG_Capture_Error_File)); return; } if ((Meka_State == MEKA_STATE_FULLSCREEN) || (!g_Configuration.capture_include_gui)) { // Fullscreen source = screenbuffer; x_start = cur_drv->x_start; y_start = cur_drv->y_show_start; x_len = cur_drv->x_res; y_len = cur_drv->y_res; // Crop left column if (g_Configuration.capture_crop_scrolling_column) { if ((cur_drv->id == DRV_SMS) && (tsms.VDP_VideoMode > 4) && (Mask_Left_8)) { x_start += 8; x_len -= 8; } } // Automatic crop on tile boundaries (for map making) // In total, remove 8 pixels from each axis if (g_Configuration.capture_crop_align_8x8) { const int scroll_x = cur_machine.VDP.scroll_x_latched; const int scroll_y = cur_machine.VDP.scroll_y_latched; x_start += scroll_x & 7; y_start += 8 - (scroll_y & 7); x_len -= 8; y_len -= 8; } } else if (Meka_State == MEKA_STATE_GUI) { // GUI mode x_start = 0; y_start = 0; x_len = g_Configuration.video_mode_gui_res_x; y_len = g_Configuration.video_mode_gui_res_y; source = gui_buffer; } else { // Unknown Mode assert(0); return; } acquire_bitmap(source); bmp = create_sub_bitmap(source, x_start, y_start, x_len, y_len); if (bmp == NULL) { Msg(MSGT_USER, Msg_Get(MSG_Capture_Error)); return; } release_bitmap(source); //get_palette(pal); if (save_bitmap(s1, bmp, NULL) != 0) { Msg(MSGT_USER, Msg_Get(MSG_Capture_Error)); destroy_bitmap(bmp); return; } destroy_bitmap(bmp); // Verbose killpath(s1); Msg(MSGT_USER, Msg_Get(MSG_Capture_Done), s1); }
void triple_buffer(BITMAP **page) { int i = 0, w, repeat, active_page = 0; int time_diff, bar_number, *used_voices = NULL, hw_voices; int text_bar_height, half_bar_size; unsigned int radius; coord_t dot[2], dot_old[2], cal[2], cal_tmp[2]; wiimote *wiimote; char *fonts[NUM_MAX_FONTS] = FONTS; FONT *font_msg, *font_notes; BITMAP *background; bars *bar; /* dot_old data initialization. dot_old's X coord is not used */ dot_old[0].y = SCREEN_H; dot_old[1].y = SCREEN_H; /* Wiimote initialization*/ wiimote = *wiiuse_init(1); /* Load fonts, size of font is related to SCREEN_W */ do { font_msg = load_font(fonts[i], NULL, NULL); __ASSERT(font_msg, ERROR_CANT_LOAD_FONT(fonts[i])); w = text_length(font_msg, WIIMOTE_CONNECTION_MSG); } while (w >= SCREEN_W && ++i < (NUM_MAX_FONTS-1)); /* Notes' font is smaller than messages' font */ font_notes = load_font(fonts[i], NULL, NULL); __ASSERT(font_notes, ERROR_CANT_LOAD_FONT(fonts[i])); /* Initialize and calculate bars size, point radius, text bar height, and calculate half bar size for text output under bars */ bar = bar_create(NUM_BARS); radius = RADIUS(bar); text_bar_height = TEXT_BAR_HEIGHT; half_bar_size = HALF_BAR_SIZE(bar); /* Control the max number of available hardware voices. Though ALSA driver voices are up to 64, max hardware voices generally are 8-16. Checking the allocated voices after the driver allocation seems to be the only way */ hw_voices = get_mixer_voices(); if (hw_voices < NUM_BARS) used_voices = reallocate_voices(bar, hw_voices); /* Install timer, 10 ticks a second */ LOCK_VARIABLE(timer); LOCK_FUNCTION(inc_timer); install_int_ex(inc_timer, BPS_TO_TIMER(10)); /* Load background from file */ background = load_tga("images/back.tga", NULL); __ASSERT(background, ERROR_CANT_LOAD_IMAGE("back.tga")); /* Enables vertical syncronization*/ vsync(); i = 0; /* First frame, this lasts until wiimote is connected, the user is prompted to activate the wiimote by pressing 1 & 2 keys on the wiimote */ while(i == 0 && !keypressed()) { active_page = start_credits3buf(page, active_page); clear_keybuf(); title3buf(page, active_page, font_msg); clear_keybuf(); repeat = 0; while(repeat++ < 8 && i == 0 && !keypressed()) { stretch_blit(background, page[active_page], 0, 0, background->w, background->h, 0, 0, SCREEN_W, SCREEN_H); // background if(repeat%2 == 1) textout_centre_ex(page[active_page], font_msg, WIIMOTE_CONNECTION_MSG, SCREEN_W/2, SCREEN_H/2, makecol(0, 0, 0), -1); // text prompt release_bitmap(page[active_page]); /* make sure the last flip request has actually happened */ do { } while (poll_scroll()); /* post a request to display the page we just drew */ request_video_bitmap(page[active_page]); /* update counters to point to the next page */ switch (active_page) { case 0: active_page = 1; break; case 1: active_page = 2; break; case 2: active_page = 0; break; } /* Search for a wiimote */ i = wiiuse_find(&wiimote, 1, 1); } } /* Try to connect to the wiimote */ __ASSERT(wiiuse_connect(&wiimote, 1) > 0, ERROR_CANT_OPEN_WIIMOTE); /* Activate the first led on the wiimote */ wiiuse_set_leds(wiimote, WIIMOTE_LED_1); /* Activate the ir module on the wiimote */ wiiuse_set_ir(wiimote, TRUE); wiiuse_motion_sensing(wiimote, FALSE); wiiuse_set_ir_sensitivity(wiimote, 1); wiiuse_set_flags(wiimote, WIIUSE_CONTINUOUS, 0); cal[0].x = 0; cal[0].y = 0; cal[1].x = 1023; cal[1].y = 767; /* CALIBRATION LOOP */ for(repeat=0;repeat<2;repeat++) { clear_keybuf(); while(!keypressed()) { if (wiiuse_poll(&wiimote, 1)) // if there are datas pending from/to wiimote or ESC is pressed if (key[KEY_ESC] || wiimote->event == WIIUSE_DISCONNECT || wiimote->event == WIIUSE_UNEXPECTED_DISCONNECT || IS_PRESSED(wiimote, WIIMOTE_BUTTON_HOME)) { // if ESC is pressed, if wiimote update fails, or if HOME key on wiimote is pressed wiiuse_disconnect(wiimote); destroy_bitmap(background); destroy_font(font_msg); destroy_font(font_notes); for (i=0;i<NUM_BARS;i++) { deallocate_voice(bar[i].voice); destroy_sample(bar[i].sound); } free(bar); // YO!! :-) free(used_voices); return; } /* background */ stretch_blit(background, page[active_page], 0, 0, background->w, background->h, 0, 0, SCREEN_W, SCREEN_H); if (wiimote->ir.dot[0].visible) { // if ir source is visible /* Read coords from the wiimote's ir*/ dot[0] = transpose(wiimote->ir.dot[0], cal, 0); } switch(repeat) { case 0: textout_centre_ex(page[active_page], font_msg, WIIMOTE_CAL_ASX, SCREEN_W/2, SCREEN_H/2, makecol(0, 0, 0), -1); // text prompt rect(page[active_page], dot[0].x, dot[0].y, SCREEN_W+1, SCREEN_H+1, makecol(0, 0, 0)); break; case 1: textout_centre_ex(page[active_page], font_msg, WIIMOTE_CAL_BDX, SCREEN_W/2, SCREEN_H/2, makecol(0, 0, 0), -1); // text prompt rect(page[active_page], dot[1].x, dot[1].y, SCREEN_W+1, SCREEN_H+1, makecol(0, 0, 0)); rect(page[active_page], -1, -1, dot[0].x, dot[0].y, makecol(0, 0, 0)); break; } circlefill(page[active_page], dot[0].x, dot[0].y, radius, makecol(0, 0, 0)); release_bitmap(page[active_page]); /* make sure the last flip request has actually happened */ do { } while (poll_scroll()); /* post a request to display the page we just drew */ request_video_bitmap(page[active_page]); /* update counters to point to the next page */ switch (active_page) { case 0: active_page = 1; break; case 1: active_page = 2; break; case 2: active_page = 0; break; } } cal_tmp[repeat].x = wiimote->ir.dot[0].x; cal_tmp[repeat].y = wiimote->ir.dot[0].y; dot[1] = dot[0]; } __ASSERT((cal_tmp[0].x < cal_tmp[1].x && cal_tmp[0].y > cal_tmp[1].y), ERROR_WHILE_CALIBRATING); cal[0].x = cal_tmp[0].x; cal[0].y = 767-cal_tmp[0].y; cal[1].x = cal_tmp[1].x; cal[1].y = 767-cal_tmp[1].y; /* MAIN LOOP */ while (TRUE) { /* Draw a frame */ if (wiiuse_poll(&wiimote, 1) || key[KEY_ESC]) // if there are datas pending from/to wiimote or ESC is pressed if (key[KEY_ESC] || wiimote->event == WIIUSE_DISCONNECT || wiimote->event == WIIUSE_UNEXPECTED_DISCONNECT || IS_PRESSED(wiimote, WIIMOTE_BUTTON_HOME)) { // if ESC is pressed, if wiimote update fails, or if HOME key on wiimote is pressed wiiuse_disconnect(wiimote); destroy_bitmap(background); destroy_font(font_msg); destroy_font(font_notes); for (i=0;i<NUM_BARS;i++) { deallocate_voice(bar[i].voice); destroy_sample(bar[i].sound); } free(bar); // YO!! :-) free(used_voices); return; } /* background */ stretch_blit(background, page[active_page], 0, 0, background->w, background->h, 0, 0, SCREEN_W, SCREEN_H); /* Xylophone's bars and notes names */ for(i=0;i<NUM_BARS;i++) { if (bar[i].t_start != -1 && (time_diff = timer-bar[i].t_start) > TICKS_TO_BLACK) // if color animation ends bar[i].t_start = -1; if (bar[i].t_start == -1) // if no color animation bar[i].color = 0; else bar[i].color = COLORVAL(time_diff); // if color animation is running /* Draw bar */ rectfill(page[active_page], bar[i].min.x, bar[i].min.y, bar[i].max.x, bar[i].max.y, makecol(bar[i].color, bar[i].color, bar[i].color)); /* Print bar's associated note */ textout_centre_ex(page[active_page], font_notes, bar[i].note, (bar[i].min.x + half_bar_size), text_bar_height, makecol(0, 0, 0), -1); } // da normalizzare e da contenere nello schermo, ir for(i=0;i<MAX_IR_DOTS;i++) { if (wiimote->ir.dot[i].visible) { // if ir source is visible /* Read coords from the wiimote's ir*/ dot[i] = transpose(wiimote->ir.dot[i], cal, radius); /* If the ir source is under the bars and in previous frame it was above the bars, then play the sound and start the animation */ if (dot[i].y > bar[0].min.y-radius) { if(dot_old[i].y <= bar[0].min.y-radius) { /* This calculates on which bar the ir source actually is */ bar_number = is_onbar(bar, dot[i].x, NUM_BARS); /* play bar_number's sound with specified volume */ play_bar_voice(bar, bar_number, volume(dot[i].y-dot_old[i].y), used_voices, hw_voices); } /* The dot have not to go under the bars or out of the screen */ circlefill(page[active_page], dot[i].x, bar[0].min.y-radius, radius, makecol(0, 0, 0)); } else circlefill(page[active_page], dot[i].x, dot[i].y, radius, makecol(0, 0, 0)); dot_old[i].y = dot[i].y; } else dot_old[i].y = SCREEN_H; } release_bitmap(page[active_page]); /* make sure the last flip request has actually happened */ do { } while (poll_scroll()); /* post a request to display the page we just drew */ request_video_bitmap(page[active_page]); /* update counters to point to the next page */ switch (active_page) { case 0: active_page = 1; break; case 1: active_page = 2; break; case 2: active_page = 0; break; } } }
/* create_sub_bitmap: * Creates a sub bitmap, ie. a bitmap sharing drawing memory with a * pre-existing bitmap, but possibly with different clipping settings. * Usually will be smaller, and positioned at some arbitrary point. * * Mark Wodrich is the owner of the brain responsible this hugely useful * and beautiful function. */ BITMAP *create_sub_bitmap(BITMAP *parent, int x, int y, int width, int height) { BITMAP *bitmap; int nr_pointers; int i; ASSERT(parent); ASSERT((x >= 0) && (y >= 0) && (x < parent->w) && (y < parent->h)); ASSERT((width > 0) && (height > 0)); ASSERT(system_driver); if (x+width > parent->w) width = parent->w-x; if (y+height > parent->h) height = parent->h-y; if (parent->vtable->create_sub_bitmap) return parent->vtable->create_sub_bitmap(parent, x, y, width, height); if (system_driver->create_sub_bitmap) return system_driver->create_sub_bitmap(parent, x, y, width, height); /* get memory for structure and line pointers */ /* (see create_bitmap for the reason we need at least two) */ nr_pointers = MAX(2, height); bitmap = _AL_MALLOC(sizeof(BITMAP) + (sizeof(char *) * nr_pointers)); if (!bitmap) return NULL; acquire_bitmap(parent); bitmap->w = bitmap->cr = width; bitmap->h = bitmap->cb = height; bitmap->clip = TRUE; bitmap->cl = bitmap->ct = 0; bitmap->vtable = parent->vtable; bitmap->write_bank = parent->write_bank; bitmap->read_bank = parent->read_bank; bitmap->dat = NULL; bitmap->extra = NULL; bitmap->x_ofs = x + parent->x_ofs; bitmap->y_ofs = y + parent->y_ofs; bitmap->seg = parent->seg; /* All bitmaps are created with zero ID's. When a sub-bitmap is created, * a unique ID is needed to identify the relationship when blitting from * one to the other. This is obtained from the global variable * _sub_bitmap_id_count, which provides a sequence of integers (yes I * know it will wrap eventually, but not for a long time :-) If the * parent already has an ID the sub-bitmap adopts it, otherwise a new * ID is given to both the parent and the child. */ if (!(parent->id & BMP_ID_MASK)) { parent->id |= _sub_bitmap_id_count; _sub_bitmap_id_count = (_sub_bitmap_id_count+1) & BMP_ID_MASK; } bitmap->id = parent->id | BMP_ID_SUB; bitmap->id &= ~BMP_ID_LOCKED; if (is_planar_bitmap(bitmap)) x /= 4; x *= BYTES_PER_PIXEL(bitmap_color_depth(bitmap)); /* setup line pointers: each line points to a line in the parent bitmap */ for (i=0; i<height; i++) bitmap->line[i] = parent->line[y+i] + x; if (bitmap->vtable->set_clip) bitmap->vtable->set_clip(bitmap); if (parent->vtable->created_sub_bitmap) parent->vtable->created_sub_bitmap(bitmap, parent); if (system_driver->created_sub_bitmap) system_driver->created_sub_bitmap(bitmap, parent); if (parent->id & BMP_ID_VIDEO) _register_switch_bitmap(bitmap, parent); release_bitmap(parent); return bitmap; }
/* show_mouse: * Tells Allegro to display a mouse pointer. This only works when the timer * module is active. The mouse pointer will be drawn onto the bitmap bmp, * which should normally be the hardware screen. To turn off the mouse * pointer, which you must do before you draw anything onto the screen, call * show_mouse(NULL). If you forget to turn off the mouse pointer when * drawing something, the SVGA bank switching code will become confused and * will produce garbage all over the screen. */ void show_mouse(BITMAP *bmp) { if (!mouse_driver) return; remove_int(mouse_move); /* Remove the mouse cursor */ if (_mouse_screen) { acquire_bitmap(_mouse_screen); if (gfx_capabilities & GFX_HW_CURSOR) { gfx_driver->hide_mouse(); gfx_capabilities &= ~(GFX_HW_CURSOR|GFX_SYSTEM_CURSOR); hw_cursor_dirty = TRUE; } else draw_mouse(TRUE, FALSE); release_bitmap(_mouse_screen); } _mouse_screen = bmp; if (bmp && (current_cursor != MOUSE_CURSOR_NONE)) { acquire_bitmap(_mouse_screen); /* Default system cursor? */ if ((current_cursor != MOUSE_CURSOR_ALLEGRO) && allow_system_cursor) { if (mouse_driver && mouse_driver->select_system_cursor) { use_system_cursor = mouse_driver->select_system_cursor(current_cursor); if (use_system_cursor) { gfx_capabilities |= GFX_HW_CURSOR|GFX_SYSTEM_CURSOR; hw_cursor_dirty = FALSE; got_hw_cursor = TRUE; } } } else { use_system_cursor = FALSE; } /* Custom hardware cursor? */ if (hw_cursor_dirty) { got_hw_cursor = FALSE; if ((gfx_driver) && (gfx_driver->set_mouse_sprite) && (!_dispsw_status)) if (gfx_driver->set_mouse_sprite(mouse_sprite, mouse_x_focus, mouse_y_focus) == 0) got_hw_cursor = TRUE; hw_cursor_dirty = FALSE; } /* Try to display hardware (custom or system) cursor */ if ((got_hw_cursor) && (is_same_bitmap(bmp, screen))) if (gfx_driver->show_mouse(bmp, mx=mouse_x, my=mouse_y) == 0) gfx_capabilities |= GFX_HW_CURSOR; /* Draw cursor manually if we can't do that */ if (!(gfx_capabilities & GFX_HW_CURSOR)) { draw_mouse(FALSE, TRUE); use_system_cursor = FALSE; } release_bitmap(_mouse_screen); install_int(mouse_move, 10); } else { if (mouse_driver->timer_poll) install_int(mouse_move, 10); } }
/* spline: * Draws a bezier spline onto the specified bitmap in the specified color. */ void _soft_spline(BITMAP *bmp, AL_CONST int points[8], int color) { #define MAX_POINTS 64 int xpts[MAX_POINTS], ypts[MAX_POINTS]; int i; int num_points; int c; int old_drawing_mode, old_drawing_x_anchor, old_drawing_y_anchor; BITMAP *old_drawing_pattern; ASSERT(bmp); /* Calculate the number of points to draw. We want to draw as few as possible without loosing image quality. This algorithm is rather random; I have no motivation for it at all except that it seems to work quite well. The length of the spline is approximated by the sum of distances from first to second to third to last point. The number of points to draw is then the square root of this distance. I first tried to make the number of points proportional to this distance without taking the square root of it, but then short splines kind of had too few points and long splines had too many. Since sqrt() increases more for small input than for large, it seems in a way logical to use it, but I don't precisely have any mathematical proof for it. So if someone has a better idea of how this could be done, don't hesitate to let us know... */ #undef DIST #define DIST(x, y) (sqrt((x) * (x) + (y) * (y))) num_points = (int)(sqrt(DIST(points[2]-points[0], points[3]-points[1]) + DIST(points[4]-points[2], points[5]-points[3]) + DIST(points[6]-points[4], points[7]-points[5])) * 1.2); if (num_points > MAX_POINTS) num_points = MAX_POINTS; calc_spline(points, num_points, xpts, ypts); acquire_bitmap(bmp); if ((_drawing_mode == DRAW_MODE_XOR) || (_drawing_mode == DRAW_MODE_TRANS)) { /* Must compensate for the end pixel being drawn twice, hence the mess. */ old_drawing_mode = _drawing_mode; old_drawing_pattern = _drawing_pattern; old_drawing_x_anchor = _drawing_x_anchor; old_drawing_y_anchor = _drawing_y_anchor; for (i=1; i<num_points-1; i++) { c = getpixel(bmp, xpts[i], ypts[i]); line(bmp, xpts[i-1], ypts[i-1], xpts[i], ypts[i], color); solid_mode(); putpixel(bmp, xpts[i], ypts[i], c); drawing_mode(old_drawing_mode, old_drawing_pattern, old_drawing_x_anchor, old_drawing_y_anchor); } line(bmp, xpts[i-1], ypts[i-1], xpts[i], ypts[i], color); } else { for (i=1; i<num_points; i++) line(bmp, xpts[i-1], ypts[i-1], xpts[i], ypts[i], color); } release_bitmap(bmp); }
void Alleg4Surface::unlock() { ASSERT(m_lock > 0); if (--m_lock == 0) release_bitmap(m_bmp); }
int main(void) { BITMAP *scroller; RGB black = { 0, 0, 0, 0 }; int x = 0; int next_x; int h = 100; if (allegro_init() != 0) return 1; install_keyboard(); if (set_gfx_mode(GFX_AUTODETECT, 320, 240, 640, 240) != 0) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Unable to set a 320x240 mode with 640x240 " "virtual dimensions\n"); return 1; } /* the scrolling area is twice the width of the screen (640x240) */ scroller = create_sub_bitmap(screen, 0, 0, SCREEN_W*2, SCREEN_H); set_palette(desktop_palette); set_color(0, &black); rectfill(scroller, 0, 0, SCREEN_W, 100, 6); rectfill(scroller, 0, 100, SCREEN_W, SCREEN_H, 2); do { /* advance the scroller, wrapping every 320 pixels */ next_x = x + 1; if (next_x >= 320) next_x = 0; /* draw another column of the landscape */ acquire_bitmap(scroller); vline(scroller, next_x+SCREEN_W-1, 0, h, 6); vline(scroller, next_x+SCREEN_W-1, h+1, SCREEN_H, 2); release_bitmap(scroller); /* scroll the screen */ scroll_screen(next_x, 0); /* duplicate the landscape column so we can wrap the scroller */ if (next_x > 0) { acquire_bitmap(scroller); vline(scroller, x, 0, h, 6); vline(scroller, x, h+1, SCREEN_H, 2); release_bitmap(scroller); } /* randomly alter the landscape position */ if (AL_RAND()&1) { if (h > 5) h--; } else { if (h < 195) h++; } x = next_x; rest(0); } while (!keypressed()); destroy_bitmap(scroller); clear_keybuf(); return 0; }