コード例 #1
0
ファイル: wjoydx.c プロジェクト: zeromus/ZeldaClassic
/* joystick_dinput_exit: [primary thread]
 *  Shuts down the DirectInput joystick devices.
 */
static void joystick_dinput_exit(void)
{
   int i, j;

   /* unacquire the devices */
   wnd_call_proc(joystick_dinput_unacquire);

   /* destroy the devices */
   for (i=0; i<dinput_joy_num; i++) {
      IDirectInputDevice2_Release(dinput_joystick[i].device);

      for (j=0; j<dinput_joystick[i].num_axes; j++) {
         if (dinput_joystick[i].axis_name[j])
            _AL_FREE(dinput_joystick[i].axis_name[j]);
      }

      if (dinput_joystick[i].caps & JOYCAPS_HASPOV)
         _AL_FREE(dinput_joystick[i].hat_name);

      for (j=0; j<dinput_joystick[i].num_buttons; j++)
         _AL_FREE(dinput_joystick[i].button_name[j]);
   }

   /* destroy the DirectInput interface */
   IDirectInput_Release(joystick_dinput);

   win_remove_all_joysticks();
   dinput_joy_num = 0;
}
コード例 #2
0
ファイル: xdga2.c プロジェクト: AntonLanghoff/whitecatlib
/* _xdga2_fetch_mode_list:
 *  Creates list of available DGA2 video modes.
 */
static GFX_MODE_LIST *_xdga2_private_fetch_mode_list(void)
{
   XDGAMode *mode;
   int bpp, num_modes, stored_modes, i, j, already_there;
   GFX_MODE_LIST *mode_list;
   GFX_MODE *tmp;

   mode = XDGAQueryModes(_xwin.display, _xwin.screen, &num_modes);
   if (!mode)
      return NULL;

   mode_list = _AL_MALLOC(sizeof(GFX_MODE_LIST));
   if (!mode_list)
      goto error;
   mode_list->mode = NULL;

   stored_modes = 0;
   for (i=0; i<num_modes; i++) {
      bpp = (mode[i].depth == 24) ? mode[i].bitsPerPixel : mode[i].depth;
      already_there = FALSE;
      for (j=0; j<stored_modes; j++) {
         if ((mode_list->mode[j].width == mode[i].viewportWidth) &&
             (mode_list->mode[j].height == mode[i].viewportHeight) &&
             (mode_list->mode[j].bpp == bpp)) {
            already_there = TRUE;
            break;
         }
      }
      if (!already_there) {
	 tmp = _AL_REALLOC(mode_list->mode, sizeof(GFX_MODE) * (stored_modes + 1));
	 if (!tmp)
            goto error;
         mode_list->mode = tmp;
         mode_list->mode[stored_modes].width = mode[i].viewportWidth;
         mode_list->mode[stored_modes].height = mode[i].viewportHeight;
         mode_list->mode[stored_modes].bpp = bpp;
	 stored_modes++;
      }
   }

   tmp = _AL_REALLOC(mode_list->mode, sizeof(GFX_MODE) * (stored_modes + 1));
   if (!tmp)
      goto error;
   mode_list->mode = tmp;
   mode_list->mode[stored_modes].width = 0;
   mode_list->mode[stored_modes].height = 0;
   mode_list->mode[stored_modes].bpp = 0;
   mode_list->num_modes = stored_modes;

   XFree(mode);
   return mode_list;

   error:
   if (mode_list) {
      _AL_FREE(mode_list->mode);
      _AL_FREE(mode_list);
   }
   XFree(mode);
   return NULL;
}
コード例 #3
0
ファイル: wddbmp.c プロジェクト: Skiles/aseprite
/* gfx_directx_destroy_system_bitmap:
 */
void gfx_directx_destroy_system_bitmap(BITMAP *bmp)
{
   /* Special case: use normal destroy_bitmap() for subbitmaps of system
    * bitmaps. Checked here rather than in destroy_bitmap() because that
    * function should not make assumptions about the relation between system
    * bitmaps and subbitmaps thereof. This duplicates code though and a
    * different solution would be better.
    */
   if (is_sub_bitmap(bmp)) {
      if (system_driver->destroy_bitmap) {
        if (system_driver->destroy_bitmap(bmp))
           return;
      }

      if (bmp->dat)
        _AL_FREE(bmp->dat);

      _AL_FREE(bmp);

      return;
   }

   /* destroy the surface */
   gfx_directx_destroy_surface(DDRAW_SURFACE_OF(bmp));

   _AL_FREE(bmp);
}
コード例 #4
0
ファイル: wddbmp.c プロジェクト: Skiles/aseprite
/* gfx_directx_destroy_video_bitmap:
 */
void gfx_directx_destroy_video_bitmap(BITMAP *bmp)
{
   DDRAW_SURFACE *surf, *tail_page;

   surf = DDRAW_SURFACE_OF(bmp);

   if ((surf == flipping_page[0]) || (surf == flipping_page[1]) || (surf == flipping_page[2])) {
      /* handle surfaces belonging to the flipping chain */
      if (--n_flipping_pages > 0) {
         tail_page = flipping_page[n_flipping_pages];

         /* If the surface attached to the bitmap is not the tail page
          * that is to be destroyed, attach it to the bitmap whose
          * attached surface is the tail page.
          */
         if (surf != tail_page) {
            surf->parent_bmp = tail_page->parent_bmp;
            surf->parent_bmp->extra = surf;
         }

         /* remove the tail page from the flipping chain */
         recreate_flipping_chain(n_flipping_pages);
         _AL_FREE(tail_page);
      }
      flipping_page[n_flipping_pages] = NULL;
   }
   else {
      /* destroy the surface */
      gfx_directx_destroy_surface(surf);
   }

   _AL_FREE(bmp);
}
コード例 #5
0
ファイル: wmcursor.c プロジェクト: sesc4mt/mvcdecoder
/* stretch_blit_to_hdc:
 *  Blits an Allegro BITMAP to a Windows DC. Has a syntax similar to
 *  stretch_blit().
 */
static void local_stretch_blit_to_hdc(ALLEGRO_BITMAP *bitmap, HDC dc,
   int src_x, int src_y, int src_w, int src_h,
   int dest_x, int dest_y, int dest_w, int dest_h)
{
   const int bitmap_h = al_get_bitmap_height(bitmap);
   const int bottom_up_src_y = bitmap_h - src_y - src_h;
   BYTE *pixels;
   BITMAPINFO *bi;

   bi = get_bitmap_info(bitmap);
   pixels = get_dib_from_bitmap_32(bitmap);

   /* Windows treats all source bitmaps as bottom-up when using StretchDIBits
    * unless the source (x,y) is (0,0).  To work around this buggy behavior, we
    * can use negative heights to reverse the direction of the blits.
    *
    * See <http://wiki.allegro.cc/StretchDIBits> for a detailed explanation.
    */
   if (bottom_up_src_y == 0 && src_x == 0 && src_h != bitmap_h) {
      StretchDIBits(dc, dest_x, dest_h+dest_y-1, dest_w, -dest_h,
	 src_x, bitmap_h - src_y + 1, src_w, -src_h, pixels, bi,
	 DIB_RGB_COLORS, SRCCOPY);
   }
   else {
      StretchDIBits(dc, dest_x, dest_y, dest_w, dest_h,
	 src_x, bottom_up_src_y, src_w, src_h, pixels, bi,
	 DIB_RGB_COLORS, SRCCOPY);
   }

   _AL_FREE(pixels);
   _AL_FREE(bi);
}
コード例 #6
0
ファイル: graphics.c プロジェクト: Skiles/aseprite
/* destroy_gfx_mode_list:
 *  Removes the mode list created by get_gfx_mode_list() from memory.
 */
void destroy_gfx_mode_list(GFX_MODE_LIST *gfx_mode_list)
{
   if (gfx_mode_list) {
      if (gfx_mode_list->mode)
         _AL_FREE(gfx_mode_list->mode);

      _AL_FREE(gfx_mode_list);
   }
}
コード例 #7
0
ファイル: ljoy.c プロジェクト: AntonLanghoff/whitecatlib
static void joy_exit(void)
{
   int i, j;
   for (i = 0; i < num_joysticks; i++) {
      close(joy_fd[i]);
      for (j = 0; j < joy[i].num_sticks; j++)
	 _AL_FREE((void *)joy[i].stick[j].name);
      for (j = 0; j < joy[i].num_buttons; j++)
	 _AL_FREE((void *)joy[i].button[j].name);
   }
}
コード例 #8
0
ファイル: readfont.c プロジェクト: dodamn/pkg-allegro4.2
   /* font_filetype_destructor:
    *  Since we only want to destroy the whole list when we *actually*
    *  quit, not just when allegro_exit() is called, we need to use a
    *  destructor to accomplish this.
    */
   static void font_filetype_destructor(void)
   {
      FONT_TYPE_INFO *iter = font_type_list, *next;

      while (iter) {
         next = iter->next;
         _AL_FREE(iter->ext);
         _AL_FREE(iter);
         iter = next;
      }
   
      font_type_list = NULL;

      _remove_exit_func(register_font_file_type_exit);
   }
コード例 #9
0
ファイル: ljoynu.c プロジェクト: sesc4mt/mvcdecoder
/* ljoy_release_joystick: [primary thread]
 *
 *  Close the device for a joystick then free the joystick structure.
 */
static void ljoy_release_joystick(ALLEGRO_JOYSTICK *joy_)
{
   ALLEGRO_JOYSTICK_LINUX *joy = (ALLEGRO_JOYSTICK_LINUX *) joy_;
   int i;
   
   _al_unix_stop_watching_fd(joy->fd);

   _al_event_source_free(&joy->parent.es);
   close(joy->fd);
   for (i = 0; i < joy->parent.info.num_sticks; i++)
      _AL_FREE((void *)joy->parent.info.stick[i].name);
   for (i = 0; i < joy->parent.info.num_buttons; i++)
      _AL_FREE((void *)joy->parent.info.button[i].name);
   _AL_FREE(joy);
}
コード例 #10
0
ファイル: readbmp.c プロジェクト: 1007650105/aseprite
   /* bitmap_filetype_destructor:
    *  Since we only want to destroy the whole list when we *actually*
    *  quit, not just when allegro_exit() is called, we need to use a
    *  destructor to accomplish this.
    */
   static void bitmap_filetype_destructor(void)
   {
      BITMAP_TYPE_INFO *iter = bitmap_type_list, *next;

      while (iter) {
         next = iter->next;
         _AL_FREE(iter->ext);
         _AL_FREE(iter);
         iter = next;
      }

      bitmap_type_list = NULL;

      _remove_exit_func(register_bitmap_file_type_exit);
   }
コード例 #11
0
ファイル: path.c プロジェクト: sesc4mt/mvcdecoder
/* Function: al_destroy_path
 */
void al_destroy_path(ALLEGRO_PATH *path)
{
   unsigned i;

   if (!path) {
      return;
   }

   if (path->drive) {
      al_ustr_free(path->drive);
      path->drive = NULL;
   }

   if (path->filename) {
      al_ustr_free(path->filename);
      path->filename = NULL;
   }

   for (i = 0; i < _al_vector_size(&path->segments); i++) {
      al_ustr_free(get_segment(path, i));
   }
   _al_vector_free(&path->segments);

   if (path->basename) {
      al_ustr_free(path->basename);
      path->basename = NULL;
   }

   if (path->full_string) {
      al_ustr_free(path->full_string);
      path->full_string = NULL;
   }

   _AL_FREE(path);
}
コード例 #12
0
ファイル: dispsw.c プロジェクト: AntonLanghoff/whitecatlib
/* _unregister_switch_bitmap:
 *  Removes a bitmap from the list of things that need to be saved.
 */
void _unregister_switch_bitmap(BITMAP *bmp)
{
   BITMAP_INFORMATION *info, **head;

   if (system_driver->display_switch_lock)
      system_driver->display_switch_lock(TRUE, FALSE);

   info = find_switch_bitmap(&info_list, bmp, &head);
   if (!info)
      goto getout;

   /* all the sub-bitmaps should be destroyed before we get to here */
   ASSERT(!info->child);

   /* it's not cool to destroy things that have important state */
   ASSERT(!info->other);

   *head = info->sibling;
   _AL_FREE(info);

   getout:

   if (system_driver->display_switch_lock)
      system_driver->display_switch_lock(FALSE, FALSE);
}
コード例 #13
0
ファイル: modex.c プロジェクト: Yurand/tw-light
/* modex_exit:
 *  Frees the magic bank switch buffer.
 */
static void modex_exit(BITMAP *b)
{
   #ifdef ALLEGRO_DOS

      /* free conventional memory buffer */
      if (_x_magic_buffer_addr) {
	 __dpmi_free_dos_memory(magic_sel);
	 magic_sel = 0;
	 _x_magic_buffer_addr = 0;
      }

   #else

      /* free normal memory buffer */
      if (_x_magic_buffer_addr) {
	 _AL_FREE((void *)_x_magic_buffer_addr);
	 _x_magic_buffer_addr = 0;
      }

   #endif
   _unset_vga_mode();

   /* see modexsms.c */
   _split_modex_screen_ptr = NULL;
}
コード例 #14
0
ファイル: fli.c プロジェクト: zeromus/ZeldaClassic
/* close_fli:
 *  Shuts down the FLI player at the end of the file.
 */
void close_fli(void)
{
   remove_int(fli_timer_callback);

   if (fli_file) {
      pack_fclose(fli_file);
      fli_file = NULL;
   }

   if (fli_filename) {
      _AL_FREE(fli_filename);
      fli_filename = NULL;
   }

   if (fli_bitmap) {
      destroy_bitmap(fli_bitmap);
      fli_bitmap = NULL;
   }

   fli_mem_data = NULL;
   fli_mem_pos = 0;

   reset_fli_variables();

   fli_status = FLI_NOT_OPEN;
}
コード例 #15
0
ファイル: graphics.c プロジェクト: Skiles/aseprite
/* add_vram_block:
 *  Creates a video memory bitmap out of the specified region
 *  of the larger screen surface, returning a pointer to it.
 */
static BITMAP *add_vram_block(int x, int y, int w, int h)
{
   VRAM_BITMAP *b, *new_b;
   VRAM_BITMAP **last_p;

   new_b = _AL_MALLOC(sizeof(VRAM_BITMAP));
   if (!new_b)
      return NULL;

   new_b->x = x;
   new_b->y = y;
   new_b->w = w;
   new_b->h = h;

   new_b->bmp = create_sub_bitmap(screen, x, y, w, h);
   if (!new_b->bmp) {
      _AL_FREE(new_b);
      return NULL;
   }

   /* find sorted y-position */
   last_p = &vram_bitmap_list;
   for (b = vram_bitmap_list; b && (b->y < new_b->y); b = b->next_y)
      last_p = &b->next_y;

   /* insert */
   *last_p = new_b;
   new_b->next_y = b;

   return new_b->bmp;
}
コード例 #16
0
ファイル: wgdi.c プロジェクト: dodamn/pkg-allegro4.2
/* gfx_gdi_exit:
 */
static void gfx_gdi_exit(struct BITMAP *bmp)
{
   _enter_critical();

   _enter_gfx_critical();

   if (bmp) {
      save_window_pos();
      clear_bitmap(bmp);
   }

   /* stop timer */
   remove_int(render_proc);
   CloseHandle(vsync_event);

   /* disconnect from the system driver */
   win_gfx_driver = NULL;

   /* destroy dirty lines array */   
   _AL_FREE(gdi_dirty_lines);
   gdi_dirty_lines = NULL;   

   /* destroy screen surface */
   _AL_FREE(screen_surf);
   gdi_screen = NULL;

   /* destroy mouse bitmaps */
   if (wgdi_mouse_sprite) {
      destroy_bitmap(wgdi_mouse_sprite);
      wgdi_mouse_sprite = NULL;

      destroy_bitmap(mouse_frontbuffer);
      mouse_frontbuffer = NULL;

      destroy_bitmap(mouse_backbuffer);
      mouse_backbuffer = NULL;
   }

   _exit_gfx_critical();

   /* before restoring video mode, hide window */
   set_display_switch_mode(SWITCH_PAUSE);
   system_driver->restore_console_state();
   restore_window_style();

   _exit_critical();
}
コード例 #17
0
ファイル: ogg.c プロジェクト: sesc4mt/mvcdecoder
/* To be called when stream is destroyed */
static void ogg_stream_close(ALLEGRO_AUDIO_STREAM *stream)
{
   AL_OV_DATA *extra = (AL_OV_DATA *) stream->extra;
   ALLEGRO_EVENT quit_event;


   quit_event.type = _KCM_STREAM_FEEDER_QUIT_EVENT_TYPE;
   al_emit_user_event(al_get_audio_stream_event_source(stream), &quit_event, NULL);
   al_join_thread(stream->feed_thread, NULL);
   al_destroy_thread(stream->feed_thread);

   ov_clear(extra->vf);
   _AL_FREE(extra->vf);
   _AL_FREE(extra);
   stream->extra = NULL;
   stream->feed_thread = NULL;
}
コード例 #18
0
ファイル: uthreads.c プロジェクト: 1007650105/aseprite
/* _unix_destroy_mutex:
 *  Destroys a mutex.
 */
void _unix_destroy_mutex(void *handle)
{
   struct my_mutex *mx = (struct my_mutex *)handle;

   pthread_mutex_destroy(&mx->actual_mutex);

   _AL_FREE(mx);
}
コード例 #19
0
ファイル: wfile.c プロジェクト: Skiles/aseprite
/* al_findclose:
 *  Cleans up after a directory search.
 */
void al_findclose(struct al_ffblk *info)
{
   struct FF_DATA *ff_data = (struct FF_DATA *) info->ff_data;

   if (ff_data) {
      _findclose(ff_data->handle);
      _AL_FREE(ff_data);
      info->ff_data = NULL;
   }
}
コード例 #20
0
ファイル: wsystem.c プロジェクト: dodamn/pkg-allegro4.2
/* sys_directx_get_executable_name:
 *  Returns full path to the current executable.
 */
static void sys_directx_get_executable_name(char *output, int size)
{
    char *temp = _AL_MALLOC_ATOMIC(size);

    if (GetModuleFileName(allegro_inst, temp, size))
        do_uconvert(temp, U_ASCII, output, U_CURRENT, size);
    else
        usetc(output, 0);

    _AL_FREE(temp);
}
コード例 #21
0
ファイル: libc.c プロジェクト: sesc4mt/mvcdecoder
/* _al_sane_realloc:
 *  _AL_REALLOC() substitution with guaranteed behaviour.
 */
void *_al_sane_realloc(void *ptr, size_t size)
{
   void *tmp_ptr;

   tmp_ptr = NULL;

   if (ptr && size) {
      tmp_ptr = _AL_REALLOC(ptr, size);
      if (!tmp_ptr && ptr) _AL_FREE(ptr);
   }
   else if (!size) {
      tmp_ptr = NULL;
      if (ptr) _AL_FREE(ptr);
   }
   else if (!ptr) {
      tmp_ptr = _AL_MALLOC(size);
   }
   
   return tmp_ptr;
}
コード例 #22
0
ファイル: wiz_display_fb.c プロジェクト: sesc4mt/mvcdecoder
static void gp2xwiz_destroy_display_fb(ALLEGRO_DISPLAY *d)
{
   ALLEGRO_SYSTEM_GP2XWIZ *s = (void *)al_get_system_driver();
   ALLEGRO_DISPLAY_GP2XWIZ_FB *wiz_disp = (void *)d;

   _al_vector_find_and_delete(&s->system.displays, &d);

   /* All bitmaps are memory bitmaps, no need to do anything */

   _al_vector_free(&d->bitmaps);
   _al_event_source_free(&d->es);

   wiz_disp->backbuffer->memory = wiz_disp->screen_mem;
   al_destroy_bitmap(wiz_disp->backbuffer);
   
   _AL_FREE(d->vertex_cache);
   _AL_FREE(d);

   set_gfx_mode = false;
}
コード例 #23
0
ファイル: vector.c プロジェクト: sesc4mt/mvcdecoder
/* Internal function: _al_vector_free
 * 
 *  Free the space used by the vector.  You really must do this at some
 *  stage.  It is not enough to delete all the items in the vector (which you
 *  should usually do also).
 */
void _al_vector_free(_AL_VECTOR *vec)
{
   ASSERT(vec);

   if (vec->_items != NULL) {
      _AL_FREE(vec->_items);
      vec->_items = NULL;
   }
   vec->_size = 0;
   vec->_unused = 0;
}
コード例 #24
0
ファイル: djirq.c プロジェクト: AntonLanghoff/whitecatlib
/* _dos_irq_exit:
 *  Routine for freeing the interrupt handler stacks.
 */
void _dos_irq_exit(void)
{
   int c;

   for (c=0; c<IRQ_STACKS; c++) {
      if (_irq_stack[c]) {
	 _irq_stack[c] -= STACK_SIZE - 32;
	 _AL_FREE(_irq_stack[c]);
	 _irq_stack[c] = NULL;
      }
   }
}
コード例 #25
0
ファイル: dialog.c プロジェクト: sesc4mt/mvcdecoder
/* Function: al_destroy_native_dialog
 */
void al_destroy_native_dialog(ALLEGRO_NATIVE_DIALOG *fd)
{
   if (!fd)
      return;

   if (fd->paths) {
      size_t i;
      for (i = 0; i < fd->count; i++) {
         al_destroy_path(fd->paths[i]);
      }
   }
   _AL_FREE(fd->paths);
   if (fd->initial_path)
      al_destroy_path(fd->initial_path);
   al_ustr_free(fd->title);
   al_ustr_free(fd->heading);
   al_ustr_free(fd->patterns);
   al_ustr_free(fd->text);
   al_ustr_free(fd->buttons);
   al_destroy_cond(fd->cond);
   _AL_FREE(fd);
}
コード例 #26
0
ファイル: wmcursor.c プロジェクト: sesc4mt/mvcdecoder
void _al_win_destroy_mouse_cursor(ALLEGRO_DISPLAY *display, ALLEGRO_MOUSE_CURSOR *cursor)
{
   ALLEGRO_DISPLAY_WIN *win_display = (ALLEGRO_DISPLAY_WIN *) display;
   ALLEGRO_MOUSE_CURSOR_WIN *win_cursor = (ALLEGRO_MOUSE_CURSOR_WIN *) cursor;

   ASSERT(win_cursor);

   if (win_cursor->hcursor == win_display->mouse_selected_hcursor) {
      _al_win_set_system_mouse_cursor(display, ALLEGRO_SYSTEM_MOUSE_CURSOR_ARROW);
   }

   DestroyIcon(win_cursor->hcursor);
   _AL_FREE(win_cursor);
}
コード例 #27
0
ファイル: readbmp.c プロジェクト: 1007650105/aseprite
/* register_bitmap_file_type_exit:
 *  Free list of registered bitmap file types.
 */
static void register_bitmap_file_type_exit(void)
{
   BITMAP_TYPE_INFO *iter = bitmap_type_list, *next;

   while (iter) {
      next = iter->next;
      _AL_FREE(iter->ext);
      _AL_FREE(iter);
      iter = next;
   }

   bitmap_type_list = NULL;

   /* If we are using a destructor, then we only want to prune the list
    * down to valid modules. So we clean up as usual, but then reinstall
    * the internal modules.
    */
   #ifdef ALLEGRO_USE_CONSTRUCTOR
      _register_bitmap_file_type_init();
   #endif

   _remove_exit_func(register_bitmap_file_type_exit);
}
コード例 #28
0
ファイル: ufile.c プロジェクト: dodamn/pkg-allegro4.2
/* al_findclose:
 *  Cleans up after a directory search.
 */
void al_findclose(struct al_ffblk *info)
{
   struct FF_DATA *ff_data = (struct FF_DATA *) info->ff_data;

   if (ff_data) {
      if (ff_data->dir) {
         closedir(ff_data->dir);
      }
      _AL_FREE(ff_data);
      info->ff_data = NULL;

      /* to avoid leaking memory */
      ff_match(NULL, NULL);
   }
}
コード例 #29
0
ファイル: wmidi.c プロジェクト: dodamn/pkg-allegro4.2
/* _free_win_midi_driver_list:
 *  Helper function for freeing the dynamically generated driver list.
 */
void _free_win_midi_driver_list(void)
{
   int i = 0;

   if (driver_list) {
      while (driver_list[i].driver) {
         if (driver_list[i].id != MIDI_DIGMID)
            _AL_FREE(driver_list[i].driver);
         i++;
      }

      _destroy_driver_list(driver_list);
      driver_list = NULL;
   }
}
コード例 #30
0
ファイル: wsystem.c プロジェクト: dodamn/pkg-allegro4.2
/* sys_directx_message:
 *  Displays a message.
 */
static void sys_directx_message(AL_CONST char *msg)
{
    char *tmp1 = _AL_MALLOC_ATOMIC(ALLEGRO_MESSAGE_SIZE);
    char tmp2[WND_TITLE_SIZE*2];
    HWND allegro_wnd = win_get_window();

    while ((ugetc(msg) == '\r') || (ugetc(msg) == '\n'))
        msg += uwidth(msg);

    MessageBoxW(allegro_wnd,
                (unsigned short *)uconvert(msg, U_CURRENT, tmp1, U_UNICODE, ALLEGRO_MESSAGE_SIZE),
                (unsigned short *)uconvert(wnd_title, U_ASCII, tmp2, U_UNICODE, sizeof(tmp2)),
                MB_OK);

    _AL_FREE(tmp1);
}