/** * Get a textual description of a RGB format definition. * Return a string description in the format red_len/red_pos, green_len/green_pos, blue_len/blue_pos. * \return Pointer at a static buffer. */ const char* color_def_name_get(adv_color_def def_ordinal) { union adv_color_def_union def; def.ordinal = def_ordinal; switch (def.nibble.type) { case adv_color_type_palette : snprintf(color_name_buffer, sizeof(color_name_buffer), "palette %d", color_def_bytes_per_pixel_get(def_ordinal) * 8); return color_name_buffer; case adv_color_type_rgb : snprintf(color_name_buffer, sizeof(color_name_buffer), "rgb %d-%d/%d,%d/%d,%d/%d", color_def_bytes_per_pixel_get(def_ordinal) * 8, def.nibble.red_len, def.nibble.red_pos, def.nibble.green_len, def.nibble.green_pos, def.nibble.blue_len, def.nibble.blue_pos ); return color_name_buffer; case adv_color_type_yuy2 : snprintf(color_name_buffer, sizeof(color_name_buffer), "%s", "yuy2"); return color_name_buffer; case adv_color_type_text : snprintf(color_name_buffer, sizeof(color_name_buffer), "text %d", color_def_bytes_per_pixel_get(def_ordinal) * 8); return color_name_buffer; default: snprintf(color_name_buffer, sizeof(color_name_buffer), "%s", "unknown"); return color_name_buffer; } }
void advance_ui_buffer_update(struct advance_ui_context* context, void* ptr, unsigned dx, unsigned dy, unsigned dw, adv_color_def color_def, adv_color_rgb* palette_map, unsigned palette_max) { adv_bitmap* dst; struct ui_color_set* color = &context->state.color_map; ui_setup_color(context, color, color_def, palette_map, palette_max); dst = adv_bitmap_import_rgb(dx, dy, color_def_bytes_per_pixel_get(color_def), 0, 0, ptr, dw); context->state.ui_extra_flag = 0; if (context->state.ui_help_flag) { ui_help_update(context, dst, color); context->state.ui_extra_flag = 1; } if (context->state.ui_menu_flag) { ui_menu_update(context, dst, color); context->state.ui_extra_flag = 1; } if (context->state.ui_message_flag) { ui_message_update(context, dst, color); context->state.ui_extra_flag = 1; } if (context->state.ui_osd_flag) { ui_osd_update(context, dst, color); context->state.ui_extra_flag = 1; } if (context->state.ui_scroll_flag) { ui_scroll_update(context, dst, color); context->state.ui_extra_flag = 1; } adv_bitmap_free(dst); }
static void ui_messagebox_center(struct advance_ui_context* context, adv_bitmap* dst, int x, int y, const char* begin, const char* end, struct ui_color cf, struct ui_color cb, adv_pixel* map, adv_color_def def) { int border_x, border_y; int size_x, size_y; int pos_x, pos_y; adv_bitmap* flat; border_x = adv_font_sizex(context->state.ui_font); border_y = adv_font_sizey(context->state.ui_font) / 2; end = adv_font_sizex_limit(context->state.ui_font, begin, end, dst->size_x - border_x * 2); size_x = border_x * 2 + adv_font_sizex_string(context->state.ui_font, begin, end); size_y = border_y * 2 + adv_font_sizey(context->state.ui_font); pos_x = x - size_x / 2; pos_y = y - size_y / 2; if (ui_alpha(def)) flat = adv_bitmap_alloc(size_x, size_y, color_def_bytes_per_pixel_get(context->state.buffer_def)); else flat = adv_bitmap_alloc(size_x, size_y, color_def_bytes_per_pixel_get(def)); adv_bitmap_box(flat, 0, 0, size_x, size_y, 1, cf.f); adv_bitmap_clear(flat, 1, 1, size_x - 2, size_y - 2, cb.b); if (ui_alpha(def)) adv_font_put_string_map(context->state.ui_font, flat, border_x, border_y, begin, end, map); else adv_font_put_string(context->state.ui_font, flat, border_x, border_y, begin, end, cf.p, cb.p); if (ui_alpha(def)) adv_bitmap_put_alpha(dst, pos_x, pos_y, def, flat, 0, 0, flat->size_x, flat->size_y, context->state.buffer_def); else adv_bitmap_put(dst, pos_x, pos_y, flat, 0, 0, flat->size_x, flat->size_y); adv_bitmap_free(flat); }
/** * Compute the shift and mask values for the alpha channel. */ void alpha_shiftmask_get(int* shift, unsigned* mask, adv_color_def def_ordinal) { union adv_color_def_union def; unsigned pos; unsigned len; def.ordinal = def_ordinal; assert(def.nibble.type == adv_color_type_rgb); len = def.nibble.alpha_size * 8; if (def.nibble.red_pos == 0 || def.nibble.green_pos == 0 || def.nibble.blue_pos == 0) { pos = color_def_bytes_per_pixel_get(def_ordinal) * 8 - len; } else { pos = 0; } rgb_shiftmask_get(shift, mask, len, pos); }
void advance_ui_direct_update(struct advance_ui_context* context, void* ptr, unsigned dx, unsigned dy, unsigned dw, adv_color_def color_def, adv_color_rgb* palette_map, unsigned palette_max) { adv_bitmap* dst; struct ui_color_set color; ui_setup_color(context, &color, color_def, palette_map, palette_max); dst = adv_bitmap_import_rgb(dx, dy, color_def_bytes_per_pixel_get(color_def), 0, 0, ptr, dw); if (context->state.ui_direct_slow_flag) { ui_direct_slow_update(context, dst, &color); } if (context->state.ui_direct_fast_flag) { ui_direct_fast_update(context, dst, &color); } if (context->state.ui_direct_text_flag) { ui_direct_text_update(context, dst, &color); } adv_bitmap_free(dst); }
static void ui_help_update(struct advance_ui_context* context, adv_bitmap* dst, struct ui_color_set* color) { int size_x; int size_y; int pos_x; int pos_y; unsigned cx; unsigned cy; unsigned i; unsigned pb; char msg_buffer[256]; adv_bitmap* flat; adv_color_def def = color->def; struct mame_digital_map_entry digital_map[UI_MAP_MAX]; unsigned digital_mac; mame_ui_input_map(&digital_mac, digital_map, UI_MAP_MAX); size_x = context->state.help_image->size_x; size_y = context->state.help_image->size_y; pos_x = dst->size_x / 2 - size_x / 2; pos_y = dst->size_y / 8; if (ui_alpha(def)) flat = adv_bitmap_alloc(size_x, size_y, color_def_bytes_per_pixel_get(context->state.buffer_def)); else flat = adv_bitmap_alloc(size_x, size_y, color_def_bytes_per_pixel_get(def)); pb = 0; /* black on RGB format */ for (cy = 0; cy < context->state.help_image->size_y; ++cy) { for (cx = 0; cx < context->state.help_image->size_x; ++cx) { adv_pixel c; if ((adv_bitmap_pixel_get(context->state.help_image, cx, cy)) != pb) { c = color->ui_f.f; } else { c = color->ui_b.b; } adv_bitmap_pixel_put(flat, cx, cy, c); } } msg_buffer[0] = 0; for (i = 0; i < digital_mac; ++i) { unsigned j; adv_bool pred_not = 0; if (digital_map[i].port_state) { struct mame_port* p; p = mame_port_find(digital_map[i].port); if (p) { unsigned k; /* add the port name only one time */ /* if the port list is broken, a port name may appers more than one time */ for (k = 0; k < i; ++k) if (digital_map[k].port == digital_map[i].port) break; if (k == i) { if (msg_buffer[0]) sncat(msg_buffer, sizeof(msg_buffer), ", "); sncat(msg_buffer, sizeof(msg_buffer), p->desc); } } } for (j = 0; j < MAME_INPUT_MAP_MAX && digital_map[i].seq[j] != DIGITAL_SPECIAL_NONE; ++j) { if (!pred_not) { unsigned k; unsigned ckf; unsigned ckb; switch (mame_port_player(digital_map[i].port)) { case 1: ckb = color->help_p1.b; break; case 2: ckb = color->help_p2.b; break; case 3: ckb = color->help_p3.b; break; case 4: ckb = color->help_p4.b; break; default: ckb = color->help_u.b; break; } ckf = color->ui_f.f; if (digital_map[i].port_state) { ckf = color->ui_f.f; ckb = color->ui_f.b; } for (k = 0; k < context->config.help_mac; ++k) { if (context->config.help_map[k].code == digital_map[i].seq[j]) { struct help_entry* h = context->config.help_map + k; ui_help_update_key(flat, context->state.help_image, 0, 0, h->x, h->y, h->dx, h->dy, ckf, ckb, pb); } } } pred_not = digital_map[i].seq[j] == DIGITAL_SPECIAL_NOT; } } if (ui_alpha(def)) adv_bitmap_put_alpha(dst, pos_x, pos_y, def, flat, 0, 0, flat->size_x, flat->size_y, context->state.buffer_def); else adv_bitmap_put(dst, pos_x, pos_y, flat, 0, 0, flat->size_x, flat->size_y); adv_bitmap_free(flat); if (msg_buffer[0]) ui_messagebox_center(context, dst, dst->size_x / 2, pos_y + size_y + adv_font_sizey(context->state.ui_font) * 2, msg_buffer, msg_buffer + strlen(msg_buffer), color->ui_f, color->ui_b, color->ui_alpha, color->def); }
static void ui_scroll(struct advance_ui_context* context, adv_bitmap* dst, char* begin, char* end, unsigned pos, struct ui_color text_f, struct ui_color text_b, adv_pixel* text_map, struct ui_color title_f, struct ui_color title_b, adv_pixel* title_map, adv_color_def def) { unsigned size_r; unsigned size_v; int step_x, step_y; int border_x, border_y; int size_x, size_y; int pos_x, pos_y; int limit_x; char* i; char* start; unsigned n; adv_bitmap* flat; step_x = adv_font_sizex(context->state.ui_font); step_y = adv_font_sizey(context->state.ui_font); border_x = step_x; border_y = step_y / 2; /* remove unprintable chars */ i = begin; while (i != end) { if (!((*i >= ' ' && *i <= '~') || *i == '\n')) *i = ' '; ++i; } /* count size_r and compute width and wrap long line */ limit_x = dst->size_x - 6 * border_x; size_r = 0; size_x = 0; i = begin; start = begin; while (i != end) { unsigned width; char* j = i; width = 0; while (j != end && *j != '\n') { unsigned char_width; char_width = adv_font_sizex_char(context->state.ui_font, *j); if (width + char_width > limit_x) { char* b = j; /* search first space backward */ while (b != i && !isspace(*b)) --b; if (b != i) { /* adjust the position */ if (pos > size_r) ++pos; /* insert a break */ *b = '\n'; j = b; break; } } else { width += char_width; } ++j; } if (size_r == pos) start = i; ++size_r; width = adv_font_sizex_string(context->state.ui_font, i, j); if (width > size_x) size_x = width; if (j != end) i = j + 1; else i = j; } /* size */ size_x += 2 * border_x; if (size_x > dst->size_x) size_x = dst->size_x; size_v = (dst->size_y - 4 * border_y) / step_y; if (size_v > size_r) size_v = size_r; size_y = size_v * step_y + 2 * border_y; /* position */ pos_x = dst->size_x / 2 - size_x / 2; pos_y = dst->size_y / 2 - size_y / 2; if (ui_alpha(def)) flat = adv_bitmap_alloc(size_x, size_y, color_def_bytes_per_pixel_get(context->state.buffer_def)); else flat = adv_bitmap_alloc(size_x, size_y, color_def_bytes_per_pixel_get(def)); /* put */ adv_bitmap_box(flat, 0, 0, size_x, size_y, 1, text_f.f); adv_bitmap_clear(flat, 1, 1, size_x - 2, size_y - 2, text_b.b); n = 0; i = start; while (i != end && n < size_v) { struct ui_color f; struct ui_color b; adv_pixel* m; char* k; char* j = i; const char* je; while (j != end && *j != '\n') ++j; je = adv_font_sizex_limit(context->state.ui_font, i, j, size_x - 2 * border_x); for (k = i; k != j; ++k) { if (islower(*k)) break; } if (ui_recognize_title(i, j)) { f = title_f; b = title_b; m = title_map; } else { f = text_f; b = text_b; m = text_map; } ui_text_left(context, flat, border_x, border_y + n * step_y, i, je, f, b, m, def); if (j != end) i = j + 1; else i = j; ++n; } if (ui_alpha(def)) adv_bitmap_put_alpha(dst, pos_x, pos_y, def, flat, 0, 0, flat->size_x, flat->size_y, context->state.buffer_def); else adv_bitmap_put(dst, pos_x, pos_y, flat, 0, 0, flat->size_x, flat->size_y); adv_bitmap_free(flat); }
static void ui_menu(struct advance_ui_context* context, adv_bitmap* dst, struct ui_menu_entry* menu_map, unsigned menu_mac, int menu_sel, struct ui_color entry_f, struct ui_color entry_b, adv_pixel* entry_map, struct ui_color select_f, struct ui_color select_b, adv_pixel* select_map, struct ui_color title_f, struct ui_color title_b, adv_pixel* title_map, adv_color_def def) { int step_x, step_y; int border_x, border_y; int size_x, size_y; int pos_x, pos_y; int pos_r; int pos_s; int size_r; unsigned i; unsigned y; unsigned dft_dx; unsigned dft_dy; int up; int down; adv_bitmap* flat; step_x = adv_font_sizex(context->state.ui_font); step_y = adv_font_sizey(context->state.ui_font); dft_dx = dst->size_x * 3 / 4; dft_dy = dst->size_y * 2 / 5; border_x = step_x; border_y = step_y / 2; /* compute the size of the menu */ size_x = border_x * 2; size_y = border_y * 2; /* search the selected position */ pos_r = 0; pos_s = 0; for (i = 0; i < menu_mac; ++i) { switch (menu_map[i].type) { case ui_menu_text: case ui_menu_option: if (menu_sel == pos_r) { pos_s = i; } ++pos_r; break; default: break; } } up = 0; down = 0; size_r = 0; pos_r = pos_s; while (1) { unsigned width; unsigned height; if (size_r == 0) { i = pos_r; } else if (up <= down && pos_r > 0) { i = pos_r - 1; } else if (up > down && pos_r + size_r < menu_mac) { i = pos_r + size_r; } else if (pos_r > 0) { i = pos_r - 1; } else if (pos_r + size_r < menu_mac) { i = pos_r + size_r; } else { break; } switch (menu_map[i].type) { case ui_menu_title: width = border_x * 2 + adv_font_sizex_string(context->state.ui_font, menu_map[i].text_buffer, menu_map[i].text_buffer + strlen(menu_map[i].text_buffer)); height = step_y; break; case ui_menu_text: width = border_x * 2 + adv_font_sizex_string(context->state.ui_font, menu_map[i].text_buffer, menu_map[i].text_buffer + strlen(menu_map[i].text_buffer)); height = step_y; break; case ui_menu_option: width = border_x * 2 + adv_font_sizex_string(context->state.ui_font, menu_map[i].text_buffer, menu_map[i].text_buffer + strlen(menu_map[i].text_buffer)); width += border_x * 3 + adv_font_sizex_string(context->state.ui_font, menu_map[i].option_buffer, menu_map[i].option_buffer + strlen(menu_map[i].option_buffer)); height = step_y; break; case ui_menu_dft: width = dft_dx; height = dft_dy; break; default: width = 0; height = 0; break; } if (size_y + height > dst->size_y) break; size_y += height; if (size_x < width) size_x = width; if (i == pos_r) { ++size_r; } else if (i < pos_r) { up += height; --pos_r; ++size_r; } else if (i > pos_r) { down += height; ++size_r; } } if (size_x > dst->size_x) size_x = dst->size_x; /* position */ pos_x = dst->size_x / 2 - size_x / 2; pos_y = dst->size_y / 2 - size_y / 2; if (ui_alpha(def)) flat = adv_bitmap_alloc(size_x, size_y, color_def_bytes_per_pixel_get(context->state.buffer_def)); else flat = adv_bitmap_alloc(size_x, size_y, color_def_bytes_per_pixel_get(def)); /* put */ adv_bitmap_box(flat, 0, 0, size_x, size_y, 1, entry_f.f); adv_bitmap_clear(flat, 1, 1, size_x - 2, size_y - 2, entry_b.b); y = border_y; for (i = 0; i < size_r; ++i) { struct ui_menu_entry* e = &menu_map[i + pos_r]; struct ui_color cef; struct ui_color ceb; struct ui_color ctf; struct ui_color ctb; adv_pixel* cem; adv_pixel* ctm; unsigned height = e->type == ui_menu_dft ? dft_dy : step_y; unsigned width = size_x - 2 * border_x; if (i + pos_r == pos_s) { cef = select_f; ceb = select_b; cem = select_map; ctf = select_f; ctb = select_b; ctm = select_map; } else { cef = entry_f; ceb = entry_b; cem = entry_map; ctf = title_f; ctb = title_b; ctm = title_map; } adv_bitmap_clear(flat, border_x / 2, y, size_x - (border_x / 2) * 2, height, ceb.b); if (e->type == ui_menu_option) { const char* begin = e->text_buffer; const char* end = e->text_buffer + strlen(e->text_buffer); end = adv_font_sizex_limit(context->state.ui_font, begin, end, width); ui_text_left(context, flat, border_x, y, begin, end, cef, ceb, cem, def); width -= adv_font_sizex_string(context->state.ui_font, begin, end); begin = e->option_buffer; end = e->option_buffer + strlen(e->option_buffer); end = adv_font_sizex_limit(context->state.ui_font, begin, end, width); ui_text_right(context, flat, size_x - border_x, y, begin, end, ctf, ctb, ctm, def); } else if (e->type == ui_menu_title || e->type == ui_menu_text) { const char* begin = e->text_buffer; const char* end = e->text_buffer + strlen(e->text_buffer); adv_bool title = e->type == ui_menu_title; end = adv_font_sizex_limit(context->state.ui_font, begin, end, width); ui_text_center(context, flat, size_x / 2, y, begin, end, title ? ctf : cef, title ? ctb : ceb, title ? ctm : cem, def); } else if (e->type == ui_menu_dft) { ui_dft(context, flat, border_x, y + border_y, size_x - border_x * 2, height - border_y * 2, e->m, e->n, e->cut1, e->cut2, cef, ceb, ctf, def); } y += height; } if (ui_alpha(def)) adv_bitmap_put_alpha(dst, pos_x, pos_y, def, flat, 0, 0, flat->size_x, flat->size_y, context->state.buffer_def); else adv_bitmap_put(dst, pos_x, pos_y, flat, 0, 0, flat->size_x, flat->size_y); adv_bitmap_free(flat); }