/* * All modifications in this file to the original code are * (C) Copyright 1992, ..., 2005 the "DOSEMU-Development-Team". * * for details see file COPYING in the DOSEMU distribution */ /* * DANG_BEGIN_MODULE * * REMARK * Transform a 2D image (rescale and color space conversion). * * Here are functions to adapt the VGA graphics to various * X displays. * * /REMARK * DANG_END_MODULE * * Copyright (c) 1997 Steffen Winterfeldt * * * DANG_BEGIN_CHANGELOG * * 1997/07/08: Gamma correction now uses only integer operations. * -- sw (Steffen Winterfeldt ) * * 1998/11/01: Added so far unsupported video modes. We now * support all but the Hercules mode. * -- sw * * 1999/01/05: Added support for Hercules mode. * -- sw * * DANG_END_CHANGELOG * */ #include "config.h" #include #include #include #include /* mprotect() */ #include /* EXEC_PAGESIZE */ #include "remap.h" #include "mapping.h" #define LUT_OFS_33 256 * 3 #define LUT_OFS_67 256 * 4 #define LUT_OFS_11 256 * 5 #define LUT_OFS_22 256 * 6 #define LUT_OFS_45 256 * 7 #ifdef REMAP_TEST RemapFuncDesc *remap_test(void); #endif RemapFuncDesc *remap_opt(void); RemapFuncDesc *remap_gen(void); RemapFuncDesc *(*remap_list_funcs[])(void) = { remap_gen, remap_opt, #ifdef REMAP_TEST remap_test, #endif NULL }; static RemapFuncDesc *remap_list = NULL; static int base_init = 0; static FILE *rdm = NULL; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ static void do_base_init(void); static void do_nothing(void) {}; static void do_nothing_remap(struct RemapObjectStruct *a) {}; static int do_nearly_nothing(RemapObject *a, unsigned b, unsigned c, unsigned d, unsigned e, unsigned f) { return 0; }; static RectArea do_nearly_something_rect(RemapObject *ro, int x0, int y0, int width, int height) { RectArea ra = {0, 0, 0, 0}; return ra; }; static RectArea do_nearly_something_mem(RemapObject *ro, int offset, int len) { RectArea ra = {0, 0, 0, 0}; return ra; }; static unsigned u_pow(unsigned, unsigned); static unsigned gamma_fix(unsigned, unsigned); static int true_col_palette_update(RemapObject *, unsigned, unsigned, unsigned, unsigned, unsigned); static int pseudo_col_palette_update(RemapObject *, unsigned, unsigned, unsigned, unsigned, unsigned); void rgb_color_reduce(ColorSpaceDesc *, unsigned, RGBColor *); unsigned rgb_color_reduced_2int(ColorSpaceDesc *, RGBColor); void rgb_lin_filt(RGBColor, RGBColor *, RGBColor *); void rgb_bilin_filt(RGBColor, RGBColor *, RGBColor *, RGBColor *); static void src_resize_update(RemapObject *, int, int, int); static void dst_resize_update(RemapObject *, int, int, int); static void resize_update(RemapObject *); int bre_s(int, int, int); int bre_s2(int, int, int); int bre_acc(int, int, int); int bre_d_0(int, int, int); void bre_update(RemapObject *); void bre_lin_filt_update(RemapObject *); void bre_bilin_filt_update(RemapObject *); static RemapFuncDesc *find_remap_func(unsigned, int, int, RemapFuncDesc *); static RemapFuncDesc *find_best_remap_func(unsigned, int, int, RemapFuncDesc *); static void install_remap_funcs(RemapObject *, int); static void find_supported_modes(RemapObject *); static RectArea remap_mem_1(RemapObject *, int, int); static RectArea remap_rect_1(RemapObject *, int, int, int, int); static RectArea remap_mem_2(RemapObject *, int, int); void _a_ret(CodeObj *); void _a_movb_dl_dh(CodeObj *); void _a_movb_dh_dl(CodeObj *); void _a_movb_n_ecx_4eax_dl(CodeObj *, int); void _a_movb_n_ecx_4eax_dh(CodeObj *, int); void _a_movb_n_ecx_4ebx_dl(CodeObj *, int); void _a_movb_n_ecx_4ebx_dh(CodeObj *, int); void _a_movl_ebx_4eax_ebp(CodeObj *); void _a_movl_ebx_4ecx_edx(CodeObj *); void _a_movl_ecx_4eax_ebp(CodeObj *); void _a_movl_edx_4eax_ebp(CodeObj *); void _a_addl_edx_4eax_ebp(CodeObj *); void _a_movb_esi_al(CodeObj *, int); void _a_movb_esi_bl(CodeObj *, int); void _a_movb_esi_cl(CodeObj *, int); void _a_movb_esi_dl(CodeObj *, int); void _a_movb_esi_dh(CodeObj *, int); void _a_movl_ebp_edi(CodeObj *, int); void _a_movw_bp_edi(CodeObj *, int); void _a_movl_edx_edi(CodeObj *, int); void _a_movw_dx_edi(CodeObj *, int); void _a_movb_dl_edi(CodeObj *, int); void _a_addl_n_edi(CodeObj *, int); void _a_addl_n_esi(CodeObj *, int); void _a_shrl_n_ebp(CodeObj *, int); void _a_shll_n_edx(CodeObj *, int); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* * set file handle for debug messages */ void set_remap_debug_msg(FILE *_rdm) { rdm = _rdm; } /* * some basic intializations */ static void do_base_init(void) { RemapFuncDesc *rfd0, *rfd; int i = 0; /* setup remap_list to hold a chained list of remap function descriptions */ remap_list = NULL; while(remap_list_funcs[i] != NULL) { rfd0 = rfd = remap_list_funcs[i++](); if(rfd != NULL) { while(rfd->next != NULL) rfd = rfd->next; rfd->next = remap_list; remap_list = rfd0; } } } /* * initialize a remap object */ RemapObject remap_init(int src_mode, int dst_mode, int features) { RemapObject ro; int color_lut_size = 256; unsigned u, u0, u1; ro.palette_update = do_nearly_nothing; ro.src_resize = src_resize_update; ro.dst_resize = dst_resize_update; ro.remap_rect = do_nearly_something_rect; ro.remap_mem = do_nearly_something_mem; ro.state = 0; ro.src_mode = src_mode; ro.dst_mode = dst_mode; ro.src_color_space = ro.dst_color_space = NULL; ro.src_image = ro.dst_image = ro.src_tmp_line = NULL; ro.src_width = ro.src_height = ro.src_scan_len = ro.dst_width = ro.dst_height = ro.dst_scan_len = ro.src_x0 = ro.src_y0 = ro.src_x1 = ro.src_y1 = ro.dst_x0 = ro.dst_y0 = ro.dst_x1 = ro.dst_y1 = ro.src_offset = ro.dst_offset = 0; ro.bre_x = ro.bre_y = NULL; ro.true_color_lut = NULL; ro.bit_lut = NULL; ro.gamma_lut = NULL; adjust_gamma(&ro, 100); ro.remap_func = ro.remap_func_init = NULL; ro.remap_func_flags = 0; ro.remap_func_name = "no_func"; ro.co = malloc(sizeof(*ro.co)); if(ro.co == NULL) { ro.state |= ROS_MALLOC_FAIL; } else { *ro.co = code_init(); } ro.remap_line = NULL; ro.func_all = ro.func_1 = ro.func_2 = NULL; if(!base_init) { do_base_init(); base_init = 1; } ro.src_color_space = calloc(1, sizeof(*ro.src_color_space)); if(ro.src_color_space == NULL) ro.state |= ROS_MALLOC_FAIL; ro.dst_color_space = calloc(1, sizeof(*ro.dst_color_space)); if(ro.dst_color_space == NULL) ro.state |= ROS_MALLOC_FAIL; ro.bre_x = calloc(1, sizeof(*ro.bre_x)); if(ro.bre_x == NULL) ro.state |= ROS_MALLOC_FAIL; ro.bre_y = calloc(1, sizeof(*ro.bre_y)); if(ro.bre_y == NULL) ro.state |= ROS_MALLOC_FAIL; install_remap_funcs(&ro, features); if( ro.func_all != NULL && (ro.func_all->flags & RFF_LIN_FILT || ro.func_1->flags & RFF_LIN_FILT || ro.func_2->flags & RFF_LIN_FILT) ) { color_lut_size = 256 * 3; } if( ro.func_all != NULL && (ro.func_all->flags & RFF_BILIN_FILT || ro.func_1->flags & RFF_BILIN_FILT || ro.func_2->flags & RFF_BILIN_FILT) ) { color_lut_size = 256 * 6; } if( ( ro.src_mode & ( MODE_PSEUDO_8 | MODE_VGA_X | MODE_VGA_1 | MODE_VGA_2 | MODE_VGA_4 | MODE_CGA_1 | MODE_CGA_2 | MODE_HERC ) ) == ro.src_mode ) { if((ro.dst_mode & MODE_PSEUDO_8) == ro.dst_mode) { ro.palette_update = do_nearly_nothing; } if((ro.dst_mode & MODE_TRUE_8) == ro.dst_mode) { ro.true_color_lut = calloc(color_lut_size * 1, sizeof(*ro.true_color_lut)); if(ro.true_color_lut == NULL) ro.state |= ROS_MALLOC_FAIL; ro.palette_update = pseudo_col_palette_update; } else if((ro.dst_mode & MODE_TRUE_COL) == ro.dst_mode) { /* **** really too much for now... **** */ ro.true_color_lut = calloc(color_lut_size * 3, sizeof(*ro.true_color_lut)); if(ro.true_color_lut == NULL) ro.state |= ROS_MALLOC_FAIL; ro.palette_update = true_col_palette_update; } ro.bit_lut = calloc(8*4*256, 1); if(ro.bit_lut == NULL) { ro.state |= ROS_MALLOC_FAIL; } else { for(u = 0; u < 0x100; u++) { u0 = u1 = 0; if((u & 0x80)) u0 |= 1 << 0; if((u & 0x40)) u0 |= 1 << 8; if((u & 0x20)) u0 |= 1 << 16; if((u & 0x10)) u0 |= 1 << 24; if((u & 0x08)) u1 |= 1 << 0; if((u & 0x04)) u1 |= 1 << 8; if((u & 0x02)) u1 |= 1 << 16; if((u & 0x01)) u1 |= 1 << 24; ro.bit_lut[2 * u ] = u0; ro.bit_lut[2 * u + 1 ] = u1; ro.bit_lut[2 * u + 0x200] = u0 << 1; ro.bit_lut[2 * u + 1 + 0x200] = u1 << 1; ro.bit_lut[2 * u + 0x400] = u0 << 2; ro.bit_lut[2 * u + 1 + 0x400] = u1 << 2; ro.bit_lut[2 * u + 0x600] = u0 << 3; ro.bit_lut[2 * u + 1 + 0x600] = u1 << 3; } } } if( (ro.src_mode & ( MODE_TRUE_COL | MODE_PSEUDO_8 | MODE_VGA_X | MODE_VGA_1 | MODE_VGA_2 | MODE_VGA_4 ) ) && (ro.dst_mode & (MODE_TRUE_COL | MODE_PSEUDO_8)) == ro.dst_mode ) { ro.remap_mem = remap_mem_1; ro.remap_rect = remap_rect_1; } if((ro.src_mode & (MODE_CGA_1 | MODE_CGA_2 | MODE_HERC)) && (ro.dst_mode & (MODE_TRUE_COL | MODE_PSEUDO_8)) == ro.dst_mode ) { ro.remap_mem = remap_mem_2; } return ro; } /* * destroy a remap object */ #define FreeIt(_p_) if(_p_ != NULL) { free(_p_); _p_ = NULL; } void remap_done(RemapObject *ro) { FreeIt(ro->src_color_space) FreeIt(ro->dst_color_space) FreeIt(ro->gamma_lut) FreeIt(ro->bre_x) FreeIt(ro->bre_y) FreeIt(ro->true_color_lut) FreeIt(ro->bit_lut); FreeIt(ro->src_tmp_line); if(ro->co != NULL) { code_done(ro->co); free(ro->co); ro->co = NULL; } } #undef FreeIt /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* * Calculate a^b (a >= 0, b >= 0). * a, b are fixed point numbers with 16 bit decimals. * * The result is accurate enough for our purpose (relative * error typically 10^-4, worst cases still better than 10^-2). */ unsigned u_pow(unsigned a, unsigned b) { unsigned long long l, l2, r; unsigned b0; int i, j; if(a == 0) return b ? 0 : 1 << 16; b0 = b >> 16; r = 1 << 16; /* 1.0 */ for(l = a, i = 0; i < 16 && b0; i++) { if(b0 & 1) r = r * l >> 16; l = l * l >> 16; b0 >>= 1; } for(l = a, i = 0; i < 16 && (b & ((1 << 16) - 1)); i++) { for(l2 = l, j = 0; j < 10; j++) { l2 = (l2 >> 1) + (l << 15) / l2; } /* l2 = sqrt(l) now */ l = l2; if(b & (1 << 15)) r = r * l >> 16; b <<= 1; } return r; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ void adjust_gamma(RemapObject *ro, unsigned gamma) { int i; if(gamma == 100 || gamma == 0) { gamma = 100; if(ro->gamma_lut != NULL) { free(ro->gamma_lut); ro->gamma_lut = NULL; } } else { if(ro->gamma_lut == NULL) { ro->gamma_lut = malloc(256 * (sizeof *ro->gamma_lut)); if(ro->gamma_lut == NULL) { ro->state |= ROS_MALLOC_FAIL; gamma = 100; } } } if(gamma != 100) { for(i = 0; i < 256; i++) { ro->gamma_lut[i] = gamma_fix(i, gamma); } } ro->gamma = gamma; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ unsigned gamma_fix(unsigned color, unsigned gamma) { return gamma ? u_pow(color << 8, (100 << 16) / gamma) >> 8 : color; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ void gamma_correct(RemapObject *ro, RGBColor *c, unsigned *bits) { int i; if(*bits <= 1) return; if(ro->gamma_lut == NULL) return; i = *bits - 8; if(i > 0) { c->r >>= i; c->g >>= i; c->b >>= i; } if(i < 0) { i = -i; c->r <<= i; c->g <<= i; c->b <<= i; } c->r &= 255; c->g &= 255; c->b &= 255; c->r = ro->gamma_lut[c->r]; c->g = ro->gamma_lut[c->g]; c->b = ro->gamma_lut[c->b]; *bits = 8; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ static int true_col_palette_update(RemapObject *ro, unsigned i, unsigned bits, unsigned r, unsigned g, unsigned b) { RGBColor c = {r, g, b}, c1, c2, c3; unsigned u, u0, uo; if(i >= 256) return 0; gamma_correct(ro, &c, &bits); u0 = u = rgb_color_2int(ro->dst_color_space, bits, c); if(ro->dst_color_space->bits == 8) u |= u << 8; if(ro->dst_color_space->bits <= 16) u |= u << 16; #if 0 fprintf(rdm, "true_col_palette_update: pal[%u] = (0x%x, 0x%x, 0x%x) = 0x%08x\n", i, r, g, b, u); #endif uo = ro->true_color_lut[i]; ro->true_color_lut[i] = u; if( ro->func_all->flags & RFF_LIN_FILT || ro->func_1->flags & RFF_LIN_FILT || ro->func_2->flags & RFF_LIN_FILT || ro->func_all->flags & RFF_BILIN_FILT || ro->func_1->flags & RFF_BILIN_FILT || ro->func_2->flags & RFF_BILIN_FILT ) { rgb_color_reduce(ro->dst_color_space, bits, &c); rgb_lin_filt(c, &c1, &c2); ro->true_color_lut[i + LUT_OFS_33] = rgb_color_reduced_2int(ro->dst_color_space, c1); ro->true_color_lut[i + LUT_OFS_67] = rgb_color_reduced_2int(ro->dst_color_space, c2); } if( ro->func_all->flags & RFF_BILIN_FILT || ro->func_1->flags & RFF_BILIN_FILT || ro->func_2->flags & RFF_BILIN_FILT ) { rgb_bilin_filt(c, &c1, &c2, &c3); ro->true_color_lut[i + LUT_OFS_11] = rgb_color_reduced_2int(ro->dst_color_space, c1); ro->true_color_lut[i + LUT_OFS_22] = rgb_color_reduced_2int(ro->dst_color_space, c2); ro->true_color_lut[i + LUT_OFS_45] = rgb_color_reduced_2int(ro->dst_color_space, c3); } if(ro->dst_color_space->bits > 8 && ro->dst_color_space->bits <= 16) { ro->true_color_lut[i + 256] = u0; ro->true_color_lut[i + 256 * 2] = u0 << 16; } return uo == u ? 0 : 1; } static int pseudo_col_palette_update(RemapObject *ro, unsigned i, unsigned bits, unsigned r, unsigned g, unsigned b) { RGBColor c = {r, g, b}; unsigned u, uo; gamma_correct(ro, &c, &bits); u = rgb_color_2int(ro->dst_color_space, bits, c); #if 0 fprintf(rdm, "pseudo_col_palette_update: pal[%u] = (0x%x, 0x%x, 0x%x) = 0x%02x:0x%02x\n", i, r, g, b, u0, u1); #endif if(i < 256) { uo = ro->true_color_lut[i]; ro->true_color_lut[i] = u; return u == uo ? 0 : 1; } return 0; } static unsigned dit_col(int s_c, int d_c, int col, int dit, int lim) { int k, l, k0, k1, kr; k0 = ((d_c - 1) * col + d_c - 2) / (s_c - 1); k1 = k0 + 1; if(k1 >= d_c) k1 = k0; k = ((s_c - 1) * k0) / (d_c - 1); l = ((s_c - 1) * k1) / (d_c - 1); if(k != l) { kr = ((col - k) * dit + ((l - k) >> 1) ) / (l - k); } else { kr = 0; } return kr <= lim ? k0 : k1; /* or < ? */ } void rgb_color_reduce(ColorSpaceDesc *csd, unsigned bits, RGBColor *c) { c->r &= (1 << bits) - 1; c->g &= (1 << bits) - 1; c->b &= (1 << bits) - 1; if(csd->r_mask || csd->g_mask || csd->b_mask) { c->r = csd->r_bits >= bits ? c->r << (csd->r_bits - bits) : c->r >> (bits - csd->r_bits); c->g = csd->g_bits >= bits ? c->g << (csd->g_bits - bits) : c->g >> (bits - csd->g_bits); c->b = csd->b_bits >= bits ? c->b << (csd->b_bits - bits) : c->b >> (bits - csd->b_bits); } } unsigned rgb_color_reduced_2int(ColorSpaceDesc *csd, RGBColor c) { c.r <<= csd->r_shift; c.g <<= csd->g_shift; c.b <<= csd->b_shift; return c.r | c.g | c.b; } unsigned rgb_color_2int(ColorSpaceDesc *csd, unsigned bits, RGBColor c) { unsigned r, g, b; unsigned i0, i1, i2, i3; c.r &= (1 << bits) - 1; c.g &= (1 << bits) - 1; c.b &= (1 << bits) - 1; if(csd->r_mask || csd->g_mask || csd->b_mask) { rgb_color_reduce(csd, bits, &c); return rgb_color_reduced_2int(csd, c); } #ifdef REMAP_REAL_DITHER if(csd->r_bits && csd->g_bits && csd->b_bits && bits) { r = dit_col(1 << bits, csd->r_bits, c.r, 5, 1); g = dit_col(1 << bits, csd->g_bits, c.g, 5, 1); b = dit_col(1 << bits, csd->b_bits, c.b, 5, 1); i0 = r * csd->r_shift + g * csd->g_shift + b * csd->b_shift; r = dit_col(1 << bits, csd->r_bits, c.r, 5, 3); g = dit_col(1 << bits, csd->g_bits, c.g, 5, 3); b = dit_col(1 << bits, csd->b_bits, c.b, 5, 3); i1 = r * csd->r_shift + g * csd->g_shift + b * csd->b_shift; r = dit_col(1 << bits, csd->r_bits, c.r, 5, 4); g = dit_col(1 << bits, csd->g_bits, c.g, 5, 4); b = dit_col(1 << bits, csd->b_bits, c.b, 5, 4); i2 = r * csd->r_shift + g * csd->g_shift + b * csd->b_shift; r = dit_col(1 << bits, csd->r_bits, c.r, 5, 2); g = dit_col(1 << bits, csd->g_bits, c.g, 5, 2); b = dit_col(1 << bits, csd->b_bits, c.b, 5, 2); i3 = r * csd->r_shift + g * csd->g_shift + b * csd->b_shift; if(csd->pixel_lut != NULL) { i0 = csd->pixel_lut[i0]; i1 = csd->pixel_lut[i1]; i2 = csd->pixel_lut[i2]; i3 = csd->pixel_lut[i3]; } return i0 + (i1 << 8) + (i2 << 16) + (i3 << 24); } #else /* * the following calculation is taken directly from X.c */ if(csd->r_bits && csd->g_bits && csd->b_bits && bits) { r = (c.r * csd->r_bits) >> bits; g = (c.g * csd->g_bits) >> bits; b = (c.b * csd->b_bits) >> bits; i0 = r * csd->r_shift + g * csd->g_shift + b * csd->b_shift; r = (((c.r + (c.r - ((r << bits) / csd->r_bits))) * csd->r_bits) >> bits); g = (((c.g + (c.g - ((g << bits) / csd->g_bits))) * csd->g_bits) >> bits); b = (((c.b + (c.b - ((b << bits) / csd->b_bits))) * csd->b_bits) >> bits); if(r >= csd->r_bits) r = csd->r_bits - 1; if(g >= csd->g_bits) g = csd->g_bits - 1; if(b >= csd->b_bits) b = csd->b_bits - 1; i1 = r * csd->r_shift + g * csd->g_shift + b * csd->b_shift; if(csd->pixel_lut != NULL) { i0 = csd->pixel_lut[i0]; i1 = csd->pixel_lut[i1]; } return i0 + (i1 << 8) + (i1 << 16) + (i0 << 24); } #endif return 0; } RGBColor int_2rgb_color(ColorSpaceDesc *csd, unsigned bits, unsigned u) { RGBColor c = {0, 0, 0}; unsigned nr = u & csd->r_mask, ng = u & csd->g_mask, nb = u & csd->b_mask; if(csd->r_mask || csd->g_mask || csd->b_mask) { nr >>= csd->r_shift; ng >>= csd->g_shift; nb >>= csd->b_shift; c.r = csd->r_bits >= bits ? nr >> (csd->r_bits - bits) : nr << (bits - csd->r_bits); c.g = csd->g_bits >= bits ? ng >> (csd->g_bits - bits) : ng << (bits - csd->g_bits); c.b = csd->b_bits >= bits ? nb >> (csd->b_bits - bits) : nb << (bits - csd->b_bits); return c; } return c; } void color_space_complete(ColorSpaceDesc *csd) { unsigned ui; if((ui = csd->r_mask)) for(csd->r_shift = 0; !(ui & 1); ui >>= 1, csd->r_shift++); if(ui) for(; ui; ui >>= 1, csd->r_bits++); if((ui = csd->g_mask)) for(csd->g_shift = 0; !(ui & 1); ui >>= 1, csd->g_shift++); if(ui) for(; ui; ui >>= 1, csd->g_bits++); if((ui = csd->b_mask)) for(csd->b_shift = 0; !(ui & 1); ui >>= 1, csd->b_shift++); if(ui) for(; ui; ui >>= 1, csd->b_bits++); } void rgb_lin_filt(RGBColor c, RGBColor *c1, RGBColor *c2) { unsigned u; u = (c.r + 1) / 3; c1->r = u; c2->r = c.r - u; u = (c.g + 1) / 3; c1->g = u; c2->g = c.g - u; u = (c.b + 1) / 3; c1->b = u; c2->b = c.b - u; } void rgb_bilin_filt(RGBColor c, RGBColor *c1, RGBColor *c2, RGBColor *c3) { unsigned u; #if 0 u = c.r; c1->r = (u + 1) / 9; c2->r = (u * 2 + 1) / 9; c3->r = (u * 4 + 1) / 9; if(c1->r + 2 * c2->r + c3->r < u) c3->r++; if(c1->r + 2 * c2->r + c3->r < u) c2->r++; u = c.g; c1->g = (u + 1) / 9; c2->g = (u * 2 + 1) / 9; c3->g = (u * 4 + 1) / 9; if(c1->g + 2 * c2->g + c3->g < u) c3->g++; if(c1->g + 2 * c2->g + c3->g < u) c2->g++; u = c.b; c1->b = (u + 1) / 9; c2->b = (u * 2 + 1) / 9; c3->b = (u * 4 + 1) / 9; if(c1->b + 2 * c2->b + c3->b < u) c3->b++; if(c1->b + 2 * c2->b + c3->b < u) c2->b++; #endif u = c.r; c1->r = (u + 4) / 9; c2->r = (u * 2 + 4) / 9; c3->r = u - c1->r - 2 * c2->r; u = c.g; c1->g = (u + 4) / 9; c2->g = (u * 2 + 4) / 9; c3->g = u - c1->g - 2 * c2->g; u = c.b; c1->b = (u + 4) / 9; c2->b = (u * 2 + 4) / 9; c3->b = u - c1->b - 2 * c2->b; /* magic !!! */ if(c3->r == 114) c3->r--; if(c3->g == 114) c3->g--; if(c3->b == 114) c3->b--; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ static void src_resize_update(RemapObject *ro, int width, int height, int scan_len) { ro->src_width = width; ro->src_height = height; ro->src_scan_len = scan_len; ro->src_tmp_line = realloc(ro->src_tmp_line, width); // check return value? resize_update(ro); } static void dst_resize_update(RemapObject *ro, int width, int height, int scan_len) { ro->dst_width = width; ro->dst_height = height; ro->dst_scan_len = scan_len; resize_update(ro); } static void resize_update(RemapObject *ro) { ro->state &= ~(ROS_REMAP_FUNC_OK | ROS_REMAP_IGNORE); if(!(ro->state & (ROS_SCALE_ALL | ROS_SCALE_1 | ROS_SCALE_2))) { return; } if( ro->src_width == 0 || ro->src_height == 0 || ro->dst_width == 0 || ro->dst_height == 0 || ro->src_scan_len == 0 || ro->dst_scan_len == 0 ) { ro->state |= ROS_REMAP_FUNC_OK | ROS_REMAP_IGNORE; return; } ro->remap_line = do_nothing; if( ro->src_width == ro->dst_width && ro->src_height == ro->dst_height && (ro->state & ROS_SCALE_1) ) { ro->remap_func = ro->func_1->func; ro->remap_func_flags = ro->func_1->flags; ro->remap_func_name = ro->func_1->func_name; ro->remap_func_init = ro->func_1->func_init; } else if( (ro->src_width << 1) == ro->dst_width && (ro->src_height << 1) == ro->dst_height && (ro->state & ROS_SCALE_2) ) { ro->remap_func = ro->func_2->func; ro->remap_func_flags = ro->func_2->flags; ro->remap_func_name = ro->func_2->func_name; ro->remap_func_init = ro->func_2->func_init; } else if(ro->state & ROS_SCALE_ALL) { ro->remap_func = ro->func_all->func; ro->remap_func_flags = ro->func_all->flags; ro->remap_func_name = ro->func_all->func_name; ro->remap_func_init = ro->func_all->func_init; } else { ro->remap_func = do_nothing_remap; ro->remap_func_flags = 0; ro->remap_func_name = "do_nothing"; ro->remap_func_init = NULL; } if(ro->remap_func_flags & RFF_BILIN_FILT) bre_bilin_filt_update(ro); else if(ro->remap_func_flags & RFF_LIN_FILT) bre_lin_filt_update(ro); else bre_update(ro); if(ro->remap_func_init != NULL) { ro->remap_func_init(ro); } if(ro->remap_func != NULL && ro->remap_func != do_nothing_remap) { ro->state |= ROS_REMAP_FUNC_OK; } #ifdef REMAP_RESIZE_DEBUG fprintf(rdm, "resize_update: using %s for remap %dx%d --> %dx%d\n", ro->remap_func_name, ro->src_width, ro->src_height, ro->dst_width, ro->dst_height ); #endif } int bre_s(int d, int s_len, int d_len) { return (s_len / 2 + s_len * d) / d_len; } int bre_s2(int d, int s_len, int d_len) { return (s_len * d) / d_len; } int bre_acc(int d, int s_len, int d_len) { return (s_len / 2 + s_len * d) % d_len; } int bre_d_0(int s, int s_len, int d_len) { return ((s_len + 1) / 2 - 1 + s * d_len) / s_len; } void bre_update(RemapObject *ro) { int i, l, *ii, y; if(ro->bre_x != NULL) free(ro->bre_x); if(ro->bre_y != NULL) free(ro->bre_y); if(!(l = ro->dst_width)) l++; ro->bre_x = ii = malloc(l * sizeof(*ro->bre_x)); if(ro->bre_x == NULL) { ro->state |= ROS_MALLOC_FAIL; } else { for(i = 0; i < l; i++) ii[i] = bre_s(i + 1, ro->src_width, l); if(ro->src_mode == MODE_VGA_X) { for(i = 0; i < l; i++) ii[i] = (ii[i] >> 2) + ((ii[i] & 3) << 16); } for(i = l - 1; i > 0; i--) ii[i] -= ii[i - 1]; } if(!(l = ro->dst_height)) l++; ro->bre_y = ii = malloc(l * sizeof(*ro->bre_y)); if(ro->bre_y == NULL) { ro->state |= ROS_MALLOC_FAIL; } else { for(i = 0; i < l; i++) { if(ro->src_mode == MODE_CGA_1 || ro->src_mode == MODE_CGA_2) { y = bre_s(i, ro->src_height, l); ii[i] = (y >> 1) * ro->src_scan_len + ((y & 1) ? 0x2000 : 0); } else if(ro->src_mode == MODE_HERC) { y = bre_s(i, ro->src_height, l); ii[i] = (y >> 2) * ro->src_scan_len + (y & 3) * 0x2000; } else { ii[i] = bre_s(i, ro->src_height, l) * ro->src_scan_len; } } } } void bre_lin_filt_update(RemapObject *ro) { int i, k, l, *ii; if(ro->bre_x != NULL) free(ro->bre_x); if(ro->bre_y != NULL) free(ro->bre_y); if(!(l = ro->dst_width)) l++; ro->bre_x = ii = malloc(2 * l * sizeof(*ro->bre_x)); if(ro->bre_x == NULL) { ro->state |= ROS_MALLOC_FAIL; } else { k = ro->src_width; if(k == 0) k = 1; k = 3 * (k - 1); for(i = 0; i < l; i++) { ii[i] = bre_s2(i + 1, k, l - 1); } for(ii[l] = 0, i = 1; i < l; i++) { ii[l + i] = ii[i - 1] % 3; } for(i = 0; i < l; i++) { ii[i] /= 3; } ii[l - 1] = ro->src_width - 1; /* just for fun... (value is never needed) */ for(i = l - 1; i > 0; i--) { ii[i] -= ii[i - 1]; } ii[0] = 0; if(ii[2 * l - 1] != 0) fprintf(stderr, "**** oho: %d remains\n", ii[2 * l - 1]); } if(!(l = ro->dst_height)) l++; ro->bre_y = ii = malloc(l * sizeof(*ro->bre_y)); if(ro->bre_y == NULL) { ro->state |= ROS_MALLOC_FAIL; } else { for(i = 0; i < l; i++) { ii[i] = bre_s(i, ro->src_height, l) * ro->src_scan_len; } } } void bre_bilin_filt_update(RemapObject *ro) { int i, k, l, *ii; if(ro->bre_x != NULL) free(ro->bre_x); if(ro->bre_y != NULL) free(ro->bre_y); if(!(l = ro->dst_width)) l++; ro->bre_x = ii = malloc(2 * l * sizeof(*ro->bre_x)); if(ro->bre_x == NULL) { ro->state |= ROS_MALLOC_FAIL; } else { k = ro->src_width; if(k == 0) k = 1; k = 3 * (k - 1); for(i = 0; i < l; i++) { ii[i] = bre_s2(i + 1, k, l - 1); } for(ii[l] = 0, i = 1; i < l; i++) { ii[l + i] = ii[i - 1] % 3; } for(i = 0; i < l; i++) { ii[i] /= 3; } ii[l - 1] = ro->src_width - 1; /* just for fun... (value is never needed) */ for(i = l - 1; i > 0; i--) { ii[i] -= ii[i - 1]; } ii[0] = 0; if(ii[2 * l - 1] != 0) fprintf(stderr, "**** oho: %d remains\n", ii[2 * l - 1]); } if(!(l = ro->dst_height)) l++; ro->bre_y = ii = malloc(2 * l * sizeof(*ro->bre_y)); if(ro->bre_y == NULL) { ro->state |= ROS_MALLOC_FAIL; } else { k = ro->src_height; if(k == 0) k = 1; k = 3 * (k - 1); for(i = 0; i < l; i++) { ii[i] = bre_s2(i, k, l - 1); } for(i = 0; i < l; i++) { ii[l + i] = ii[i] % 3; } for(i = 0; i < l; i++) { ii[i] /= 3; } if(ii[2 * l - 1] != 0) fprintf(stderr, "**** oho: %d remains\n", ii[2 * l - 1]); if(ii[l - 1] >= ro->src_height) fprintf(stderr, "**** oho: %d lines is out of bounds\n", ii[l - 1]); for(i = 0; i < l; i++) { ii[i] *= ro->src_scan_len; } } } #ifdef REMAP_AREA_DEBUG #define REMAP_AREA_DEBUG_FUNC(_ro_) remap_area_debug_func(_ro_) static void remap_area_debug_func(RemapObject *ro) { fprintf(rdm, "[%s]\n", ro->remap_func_name); fprintf(rdm, " src_offset = %d, src_scan_len = %d, src_area = %d x %d, %d x %d\n", ro->src_offset, ro->src_scan_len, ro->src_x0, ro->src_y0, ro->src_x1, ro->src_y1 ); fprintf(rdm, " dst_offset = %d, dst_scan_len = %d, dst_area = %d x %d, %d x %d\n", ro->dst_offset, ro->dst_scan_len, ro->dst_x0, ro->dst_y0, ro->dst_x1, ro->dst_y1 ); } #else #define REMAP_AREA_DEBUG_FUNC(_ro_) #endif static RectArea remap_mem_1(RemapObject *ro, int offset, int len) { RectArea ra = {0, 0, 0, 0}; int i1, i2, j1, j2; int pixel_size = 1; if(ro->state & ROS_REMAP_IGNORE) return ra; if(ro->remap_func == NULL) return ra; #ifdef REMAP_AREA_DEBUG fprintf(rdm, "remap_mem: ofs = %d, len = %d\n", offset, len); fprintf(rdm, " src: base = 0x%x, width = %d, height = %d, scan_len = %d\n", (unsigned) ro->src_image, ro->src_width, ro->src_height, ro->src_scan_len ); fprintf(rdm, " dst: base = 0x%x, width = %d, height = %d, scan_len = %d\n", (unsigned) ro->dst_image, ro->dst_width, ro->dst_height, ro->dst_scan_len ); #endif if(offset < 0) len += offset, offset = 0; if(len <= 0) return ra; ra.width = ro->dst_width; i1 = offset / ro->src_scan_len; i2 = offset % ro->src_scan_len; j1 = (offset + len) / ro->src_scan_len; j2 = (offset + len) % ro->src_scan_len; /* make sure it's all visible */ if(i2 >= ro->src_width) i1++, i2 = 0, offset = i1 * ro->src_scan_len; if(i1 >= ro->src_height || i1 > j1) return ra; if(j2 >= ro->src_width) j1++, j2 = 0; if(j1 >= ro->src_height) j1 = ro->src_height, j2 = 0; switch(ro->dst_mode) { case MODE_TRUE_15: case MODE_TRUE_16: pixel_size = 2; break; case MODE_TRUE_24: pixel_size = 3; break; case MODE_TRUE_32: pixel_size = 4; break; case MODE_TRUE_8: case MODE_PSEUDO_8: default: pixel_size = 1; } if(ro->remap_func_flags & RFF_REMAP_RECT) { if(i2) { ro->src_offset = offset; offset += ro->src_scan_len - i2; ro->src_x0 = i2; ro->src_x1 = ro->src_width; ro->src_y0 = i1; ro->src_y1 = ro->src_y0 + 1; ro->dst_x0 = bre_d_0(ro->src_x0, ro->src_width, ro->dst_width); ro->dst_x1 = ro->dst_width; ro->dst_y0 = bre_d_0(ro->src_y0, ro->src_height, ro->dst_height); ro->dst_y1 = bre_d_0(ro->src_y1, ro->src_height, ro->dst_height); ro->dst_offset = ro->dst_y0 * ro->dst_scan_len + ro->dst_x0 * pixel_size; ra.y = ro->dst_y0; ra.height = ro->dst_y1 - ra.y; REMAP_AREA_DEBUG_FUNC(ro); if(ro->dst_y0 != ro->dst_y1 && ro->dst_x1 != ro->dst_x0) { ro->remap_func(ro); } i2 = 0; i1++; } if(i1 < j1) { ro->src_offset = offset; offset += ro->src_scan_len * (j1 - i1); ro->src_x0 = ro->dst_x0 = 0; ro->src_x1 = ro->src_width; ro->src_y0 = i1; ro->src_y1 = j1; ro->dst_x0 = 0; ro->dst_x1 = ro->dst_width; ro->dst_y0 = bre_d_0(ro->src_y0, ro->src_height, ro->dst_height); ro->dst_y1 = bre_d_0(ro->src_y1, ro->src_height, ro->dst_height); ro->dst_offset = ro->dst_y0 * ro->dst_scan_len; ra.height = ro->dst_y1 - ra.y; REMAP_AREA_DEBUG_FUNC(ro); if(ro->dst_y0 != ro->dst_y1) { ro->remap_func(ro); } } if(j2) { ro->src_offset = offset; ro->src_x0 = 0; ro->src_x1 = j2; ro->src_y0 = j1; ro->src_y1 = ro->src_y0 + 1; ro->dst_x0 = 0; ro->dst_x1 = bre_d_0(ro->src_x1, ro->src_width, ro->dst_width); ro->dst_y0 = bre_d_0(ro->src_y0, ro->src_height, ro->dst_height); ro->dst_y1 = bre_d_0(ro->src_y1, ro->src_height, ro->dst_height); ro->dst_offset = ro->dst_y0 * ro->dst_scan_len; ra.height = ro->dst_y1 - ra.y; REMAP_AREA_DEBUG_FUNC(ro); if(ro->dst_y0 != ro->dst_y1 && ro->dst_x1 != ro->dst_x0) { ro->remap_func(ro); } } } else if(ro->remap_func_flags & RFF_REMAP_LINES) { ro->src_offset = i1 * ro->src_scan_len; ro->src_x0 = ro->dst_x0 = 0; ro->src_x1 = ro->src_width; ro->dst_x1 = ro->dst_width; ro->src_y0 = i1; ro->src_y1 = j1; if(j2) ro->src_y1++; ro->dst_y0 = bre_d_0(ro->src_y0, ro->src_height, ro->dst_height); ro->dst_y1 = bre_d_0(ro->src_y1, ro->src_height, ro->dst_height); ro->dst_offset = ro->dst_y0 * ro->dst_scan_len; ra.y = ro->dst_y0; ra.height = ro->dst_y1 - ro->dst_y0; REMAP_AREA_DEBUG_FUNC(ro); if(ro->dst_y0 != ro->dst_y1) { ro->remap_func(ro); } } else { ro->src_y0 = i1; ro->src_y1 = j1; if(j2) ro->src_y1++; ro->dst_y0 = bre_d_0(ro->src_y0, ro->src_height, ro->dst_height); ro->dst_y1 = bre_d_0(ro->src_y1, ro->src_height, ro->dst_height); ra.y = ro->dst_y0; ra.height = ro->dst_y1 - ro->dst_y0; ro->src_offset = ro->dst_offset = 0; ro->src_x0 = ro->dst_x0 = ro->src_y0 = ro->dst_y0 = 0; ro->src_x1 = ro->src_width; ro->dst_x1 = ro->dst_width; ro->src_y1 = ro->src_height; ro->dst_y1 = ro->dst_height; ra.height = ro->dst_height; REMAP_AREA_DEBUG_FUNC(ro); ro->remap_func(ro); } return ra; } static RectArea remap_rect_1(RemapObject *ro, int x0, int y0, int width, int height) { RectArea ra = {0, 0, 0, 0}; int x1, y1; int pixel_size = 1; if(ro->state & ROS_REMAP_IGNORE) return ra; if(ro->remap_func == NULL) return ra; if(x0 < 0) width -= x0, x0 = 0; if(y0 < 0) height -= y0, y0 = 0; if(x0 >= ro->src_width || y0 >= ro->src_height) return ra; if(width <= 0 || height <= 0) return ra; x1 = x0 + width; y1 = y0 + height; if(x1 > ro->src_width) x1 = ro->src_width, width = x1 - x0; if(y1 > ro->src_height) y1 = ro->src_height, height = y1 - y0; ra.x = bre_d_0(x0, ro->src_width, ro->dst_width); ra.y = bre_d_0(y0, ro->src_height, ro->dst_height); ra.width = bre_d_0(x1, ro->src_width, ro->dst_width) - ra.x; ra.height = bre_d_0(y1, ro->src_height, ro->dst_height) - ra.y; if(!(ra.width && ra.height)) return ra; switch(ro->dst_mode) { case MODE_TRUE_15: case MODE_TRUE_16: pixel_size = 2; break; case MODE_TRUE_24: pixel_size = 3; break; case MODE_TRUE_32: pixel_size = 4; break; case MODE_TRUE_8: case MODE_PSEUDO_8: default: pixel_size = 1; } if(ro->remap_func_flags & RFF_REMAP_RECT) { ro->src_x0 = x0; ro->src_x1 = x1; ro->src_y0 = y0; ro->src_y1 = y1; ro->src_offset = ro->src_y0 * ro->src_scan_len + ro->src_x0; ro->dst_x0 = ra.x; ro->dst_x1 = ra.x + ra.width; ro->dst_y0 = ra.y; ro->dst_y1 = ra.y + ra.height; ro->dst_offset = ro->dst_y0 * ro->dst_scan_len + ro->dst_x0 * pixel_size; REMAP_AREA_DEBUG_FUNC(ro); ro->remap_func(ro); } else if(ro->remap_func_flags & RFF_REMAP_LINES) { ro->src_x0 = 0; ro->src_x1 = ro->src_width; ro->src_y0 = y0; ro->src_y1 = y1; ro->src_offset = ro->src_y0 * ro->src_scan_len; ro->dst_x0 = 0; ro->dst_x1 = ro->dst_width; ro->dst_y0 = ra.y; ro->dst_y1 = ra.y + ra.height; ro->dst_offset = ro->dst_y0 * ro->dst_scan_len; REMAP_AREA_DEBUG_FUNC(ro); ro->remap_func(ro); } else { ro->src_offset = ro->dst_offset = 0; ro->src_x0 = ro->dst_x0 = ro->src_y0 = ro->dst_y0 = 0; ro->src_x1 = ro->src_width; ro->dst_x1 = ro->dst_width; ro->src_y1 = ro->src_height; ro->dst_y1 = ro->dst_height; REMAP_AREA_DEBUG_FUNC(ro); ro->remap_func(ro); } return ra; } /* * for CGA/Hercules-like modes */ static RectArea remap_mem_2(RemapObject *ro, int offset, int len) { RectArea ra = {0, 0, 0, 0}; int i1, i2, j1, j2; int pixel_size = 1; if(ro->state & ROS_REMAP_IGNORE) return ra; if(ro->remap_func == NULL) return ra; #ifdef REMAP_AREA_DEBUG fprintf(rdm, "remap_mem: ofs = %d, len = %d\n", offset, len); fprintf(rdm, " src: base = 0x%x, width = %d, height = %d, scan_len = %d\n", (unsigned) ro->src_image, ro->src_width, ro->src_height, ro->src_scan_len ); fprintf(rdm, " dst: base = 0x%x, width = %d, height = %d, scan_len = %d\n", (unsigned) ro->dst_image, ro->dst_width, ro->dst_height, ro->dst_scan_len ); #endif if(offset < 0) len += offset, offset = 0; if(len <= 0) return ra; ra.width = ro->dst_width; i1 = offset / ro->src_scan_len; i2 = offset % ro->src_scan_len; j1 = (offset + len) / ro->src_scan_len; j2 = (offset + len) % ro->src_scan_len; if(ro->src_mode == MODE_HERC) { i1 <<= 2; j1 <<= 2; j1 += 3; } else { /* CGA */ i1 <<= 1; j1 <<= 1; j1++; } /* make sure it's all visible */ if(i2 >= ro->src_width) i1++, i2 = 0, offset = i1 * ro->src_scan_len; if(i1 >= ro->src_height || i1 > j1) return ra; if(j2 >= ro->src_width) j1++, j2 = 0; if(j1 >= ro->src_height) j1 = ro->src_height, j2 = 0; switch(ro->dst_mode) { case MODE_TRUE_15: case MODE_TRUE_16: pixel_size = 2; break; case MODE_TRUE_24: pixel_size = 3; break; case MODE_TRUE_32: pixel_size = 4; break; case MODE_TRUE_8: case MODE_PSEUDO_8: default: pixel_size = 1; } if( (ro->remap_func_flags & RFF_REMAP_RECT) || (ro->remap_func_flags & RFF_REMAP_LINES) ) { if(ro->src_mode == MODE_HERC) { ro->src_offset = (i1 >> 2) * ro->src_scan_len + (i1 & 3) * 0x2000; } else { /* CGA */ ro->src_offset = (i1 >> 1) * ro->src_scan_len + (i1 & 1 ? 0x2000 : 0); } ro->src_x0 = ro->dst_x0 = 0; ro->src_x1 = ro->src_width; ro->dst_x1 = ro->dst_width; ro->src_y0 = i1; ro->src_y1 = j1; if(j2) ro->src_y1++; ro->dst_y0 = bre_d_0(ro->src_y0, ro->src_height, ro->dst_height); ro->dst_y1 = bre_d_0(ro->src_y1, ro->src_height, ro->dst_height); ro->dst_offset = ro->dst_y0 * ro->dst_scan_len; ra.y = ro->dst_y0; ra.height = ro->dst_y1 - ro->dst_y0; REMAP_AREA_DEBUG_FUNC(ro); if(ro->dst_y0 != ro->dst_y1) { ro->remap_func(ro); } } else { ro->src_y0 = i1; ro->src_y1 = j1; if(j2) ro->src_y1++; ro->dst_y0 = bre_d_0(ro->src_y0, ro->src_height, ro->dst_height); ro->dst_y1 = bre_d_0(ro->src_y1, ro->src_height, ro->dst_height); ra.y = ro->dst_y0; ra.height = ro->dst_y1 - ro->dst_y0; ro->src_offset = ro->dst_offset = 0; ro->src_x0 = ro->dst_x0 = ro->src_y0 = ro->dst_y0 = 0; ro->src_x1 = ro->src_width; ro->dst_x1 = ro->dst_width; ro->src_y1 = ro->src_height; ro->dst_y1 = ro->dst_height; ra.height = ro->dst_height; REMAP_AREA_DEBUG_FUNC(ro); ro->remap_func(ro); } return ra; } /* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * some functions for managing the list of remap functions * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* * Search for the first suitable remap function. */ static RemapFuncDesc *find_remap_func(unsigned flags, int src_mode, int dst_mode, RemapFuncDesc *rfd) { while(rfd != NULL) { if((rfd->src_mode & src_mode) && (rfd->dst_mode & dst_mode) && (rfd->flags & (flags | RFF_BILIN_FILT | RFF_LIN_FILT)) == flags ) break; rfd = rfd->next; } return rfd; } /* * Searches for the best remap function available. * Prefers optimized ones over generic implementations and * functions that remap rectangular areas over those that * can remap only complete lines. */ static RemapFuncDesc *find_best_remap_func(unsigned flags, int src_mode, int dst_mode, RemapFuncDesc *rfd) { RemapFuncDesc *rfd1 = NULL; unsigned f_list[6 * 3]; int features = 6; int i; if(flags & RFF_BILIN_FILT) flags &= ~RFF_LIN_FILT; f_list[0] = flags | RFF_OPT_PENTIUM | RFF_REMAP_RECT; f_list[1] = flags | RFF_OPT_PENTIUM | RFF_REMAP_LINES; f_list[2] = flags | RFF_REMAP_RECT; f_list[3] = flags | RFF_REMAP_LINES; f_list[4] = flags | RFF_OPT_PENTIUM; f_list[5] = flags; for(i = 0; i < 6; i++) { f_list[features + i] = (f_list[ i] & ~RFF_BILIN_FILT) | RFF_LIN_FILT; f_list[features * 2 + i] = f_list[features + i] & ~RFF_LIN_FILT; } features *= 3; for(i = 0; i < features; i++) { if((rfd1 = find_remap_func(f_list[i], src_mode, dst_mode, rfd)) != NULL) break; } return rfd1; } /* * Looks up all remap functions that are (possibly) needed * for a particular mode. Does _not_ set ro->remap_func! */ static void install_remap_funcs(RemapObject *ro, int remap_features) { ro->func_all = find_best_remap_func(remap_features | RFF_SCALE_ALL, ro->src_mode, ro->dst_mode, remap_list); ro->func_1 = find_best_remap_func(remap_features | RFF_SCALE_1 , ro->src_mode, ro->dst_mode, remap_list); ro->func_2 = find_best_remap_func(remap_features | RFF_SCALE_2 , ro->src_mode, ro->dst_mode, remap_list); if(ro->func_1 == NULL) ro->func_1 = ro->func_all; if(ro->func_2 == NULL) ro->func_2 = ro->func_all; if(ro->func_all != NULL) ro->state |= ROS_SCALE_ALL; if(ro->func_1 != NULL) ro->state |= ROS_SCALE_1; if(ro->func_2 != NULL) ro->state |= ROS_SCALE_2; find_supported_modes(ro); } static void find_supported_modes(RemapObject *ro) { RemapFuncDesc *rfd = remap_list; ro->supported_src_modes = 0; while(rfd != NULL) { if(rfd->dst_mode & ro->dst_mode) ro->supported_src_modes |= rfd->src_mode; rfd = rfd->next; } } /* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * code generating functions * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* * initialize a code object */ CodeObj code_init(void) { CodeObj co = {&do_nothing, NULL, NULL, 0, 0}; return co; } /* * destroy a code object */ void code_done(CodeObj *co) { if(co->mem != NULL) free(co->mem); co->mem = co->text = NULL; co->exec = &do_nothing; co->size = co->pc = 0; } /* * append new instructions */ void code_append_ins(CodeObj *co, int len, void *nc) { /* EXEC_PAGESIZE is assumed to be a power of 2 */ unsigned char *mem, *text; int size; if(co->size == -1) return; if(co->size < len + co->pc) { size = len + co->pc + 2 * EXEC_PAGESIZE - 1; mem = (unsigned char *) malloc(size); if(mem == NULL) { co->size = -1; co->exec = &do_nothing; return; } text = mem + EXEC_PAGESIZE - 1; text -= ((unsigned) text) & (EXEC_PAGESIZE - 1); size -= text - mem; if(mprotect_mapping(MAPPING_VGAEMU, text, size, PROT_READ|PROT_WRITE|PROT_EXEC) < 0) { co->size = -1; co->exec = &do_nothing; free(mem); return; } if(co->pc) memcpy(text, co->text, co->pc); free(co->mem); co->mem = mem; co->text = text; co->exec = (void (*)(void)) text; co->size = size; } memcpy(co->text + co->pc, nc, len); co->pc += len; #if 0 fprintf(rdm, "[CodeObj]\n"); fprintf(rdm, " co.mem = 0x%x\n", (unsigned) co->mem); fprintf(rdm, " co.text = 0x%x\n", (unsigned) co->text); fprintf(rdm, " co.size = %d\n", co->size); fprintf(rdm, " co.pc = %d\n", co->pc); #endif } /* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * some functions that generate specific instructions * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #if GCC_VERSION_CODE >= 2095 /* * NOTE: * gcc-2.95 will optimize away all code behind the 'return' * and the function end (closing curly bracket), * hence it will remove our code generator templates. * To fool gcc, we define 'return' to be conditional on a variable * _we_ know will ever be true. * For this we define START_TEMPLATE, which contains this * conditional return statement: */ int trick_out_gcc295_for_remap = 1; #define START_TEMPLATE if (trick_out_gcc295_for_remap) return; #else /* * For all gcc below gcc-2.95 we use a normal return statement: */ #define START_TEMPLATE return; #endif void _a_ret(CodeObj *co) { __label__ _cf_001; #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tret\n", co->pc); #endif code_append_ins(co, 1, &&_cf_001); START_TEMPLATE _cf_001: asm("ret\n"); } void _a_movb_dl_dh(CodeObj *co) { __label__ _cf_001; #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb %%dl,%%dh\n", co->pc); #endif code_append_ins(co, 2, &&_cf_001); START_TEMPLATE _cf_001: asm("movb %dl,%dh\n"); } void _a_movb_dh_dl(CodeObj *co) { __label__ _cf_001; #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb %%dh,%%dl\n", co->pc); #endif code_append_ins(co, 2, &&_cf_001); START_TEMPLATE _cf_001: asm("movb %dh,%dl\n"); } void _a_movb_n_ecx_4eax_dl(CodeObj *co, int ofs) { __label__ _cf_001, _cf_002, _cf_003; if(!ofs) { #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb (%%ecx,%%eax,4),%%dl\n", co->pc); #endif code_append_ins(co, 3, &&_cf_001); START_TEMPLATE _cf_001: asm("movb (%ecx,%eax,4),%dl\n"); return; } #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb $%d(%%ecx,%%eax,4),%%dl\n", co->pc, ofs); #endif if(ofs >=-128 && ofs <=127) { code_append_ins(co, 3, &&_cf_002); code_append_ins(co, 1, &ofs); START_TEMPLATE _cf_002: asm("movb 0x1(%ecx,%eax,4),%dl\n"); return; } code_append_ins(co, 3, &&_cf_003); code_append_ins(co, 4, &ofs); START_TEMPLATE _cf_003: asm("movb 0x100(%ecx,%eax,4),%dl\n"); return; /* gcc >= 2.96 wants a statement after label */ } void _a_movb_n_ecx_4eax_dh(CodeObj *co, int ofs) { __label__ _cf_001, _cf_002, _cf_003; if(!ofs) { #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb (%%ecx,%%eax,4),%%dh\n", co->pc); #endif code_append_ins(co, 3, &&_cf_001); START_TEMPLATE _cf_001: asm("movb (%ecx,%eax,4),%dh\n"); return; } #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb $%d(%%ecx,%%eax,4),%%dh\n", co->pc, ofs); #endif if(ofs >=-128 && ofs <=127) { code_append_ins(co, 3, &&_cf_002); code_append_ins(co, 1, &ofs); START_TEMPLATE _cf_002: asm("movb 0x1(%ecx,%eax,4),%dh\n"); return; } code_append_ins(co, 3, &&_cf_003); code_append_ins(co, 4, &ofs); START_TEMPLATE _cf_003: asm("movb 0x100(%ecx,%eax,4),%dh\n"); return; /* gcc >= 2.96 wants a statement after label */ } void _a_movb_n_ecx_4ebx_dl(CodeObj *co, int ofs) { __label__ _cf_001, _cf_002, _cf_003; if(!ofs) { #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb (%%ecx,%%ebx,4),%%dl\n", co->pc); #endif code_append_ins(co, 3, &&_cf_001); START_TEMPLATE _cf_001: asm("movb (%ecx,%ebx,4),%dl\n"); return; } #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb $%d(%%ecx,%%ebx,4),%%dl\n", co->pc, ofs); #endif if(ofs >=-128 && ofs <=127) { code_append_ins(co, 3, &&_cf_002); code_append_ins(co, 1, &ofs); START_TEMPLATE _cf_002: asm("movb 0x1(%ecx,%ebx,4),%dl\n"); return; } code_append_ins(co, 3, &&_cf_003); code_append_ins(co, 4, &ofs); START_TEMPLATE _cf_003: asm("movb 0x100(%ecx,%ebx,4),%dl\n"); return; /* gcc >= 2.96 wants a statement after label */ } void _a_movb_n_ecx_4ebx_dh(CodeObj *co, int ofs) { __label__ _cf_001, _cf_002, _cf_003; if(!ofs) { #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb (%%ecx,%%ebx,4),%%dh\n", co->pc); #endif code_append_ins(co, 3, &&_cf_001); START_TEMPLATE _cf_001: asm("movb (%ecx,%ebx,4),%dh\n"); return; } #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb $%d(%%ecx,%%ebx,4),%%dh\n", co->pc, ofs); #endif if(ofs >=-128 && ofs <=127) { code_append_ins(co, 3, &&_cf_002); code_append_ins(co, 1, &ofs); START_TEMPLATE _cf_002: asm("movb 0x1(%ecx,%ebx,4),%dh\n"); return; } code_append_ins(co, 3, &&_cf_003); code_append_ins(co, 4, &ofs); START_TEMPLATE _cf_003: asm("movb 0x100(%ecx,%ebx,4),%dh\n"); return; /* gcc >= 2.96 wants a statement after label */ } void _a_movl_ebx_4eax_ebp(CodeObj *co) { __label__ _cf_001; #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovl (%%ebx,%%eax,4),%%ebp\n", co->pc); #endif code_append_ins(co, 3, &&_cf_001); START_TEMPLATE _cf_001: asm("movl (%ebx,%eax,4),%ebp\n"); } void _a_movl_ebx_4ecx_edx(CodeObj *co) { __label__ _cf_001; #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovl (%%ebx,%%ecx,4),%%edx\n", co->pc); #endif code_append_ins(co, 3, &&_cf_001); START_TEMPLATE _cf_001: asm("movl (%ebx,%ecx,4),%edx\n"); } void _a_movl_ecx_4eax_ebp(CodeObj *co) { __label__ _cf_001; #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovl (%%ecx,%%eax,4),%%ebp\n", co->pc); #endif code_append_ins(co, 3, &&_cf_001); START_TEMPLATE _cf_001: asm("movl (%ecx,%eax,4),%ebp\n"); } void _a_movl_edx_4eax_ebp(CodeObj *co) { __label__ _cf_001; #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovl (%%edx,%%eax,4),%%ebp\n", co->pc); #endif code_append_ins(co, 3, &&_cf_001); START_TEMPLATE _cf_001: asm("movl (%edx,%eax,4),%ebp\n"); } void _a_addl_edx_4eax_ebp(CodeObj *co) { __label__ _cf_001; #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\taddl (%%edx,%%eax,4),%%ebp\n", co->pc); #endif code_append_ins(co, 3, &&_cf_001); START_TEMPLATE _cf_001: asm("addl (%edx,%eax,4),%ebp\n"); } void _a_movb_esi_al(CodeObj *co, int ofs) { __label__ _cf_001, _cf_002, _cf_003; if(!ofs) { #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb (%%esi),%%al\n", co->pc); #endif code_append_ins(co, 2, &&_cf_001); START_TEMPLATE _cf_001: asm("movb (%esi),%al\n"); return; } #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb $%d(%%esi),%%al\n", co->pc, ofs); #endif if(ofs >=-128 && ofs <=127) { code_append_ins(co, 2, &&_cf_002); code_append_ins(co, 1, &ofs); START_TEMPLATE _cf_002: asm("movb 0x1(%esi),%al\n"); return; } code_append_ins(co, 2, &&_cf_003); code_append_ins(co, 4, &ofs); START_TEMPLATE _cf_003: asm("movb 0x100(%esi),%al\n"); } void _a_movb_esi_bl(CodeObj *co, int ofs) { __label__ _cf_001, _cf_002, _cf_003; if(!ofs) { #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb (%%esi),%%bl\n", co->pc); #endif code_append_ins(co, 2, &&_cf_001); START_TEMPLATE _cf_001: asm("movb (%esi),%bl\n"); return; } #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb $%d(%%esi),%%bl\n", co->pc, ofs); #endif if(ofs >=-128 && ofs <=127) { code_append_ins(co, 2, &&_cf_002); code_append_ins(co, 1, &ofs); START_TEMPLATE _cf_002: asm("movb 0x1(%esi),%bl\n"); return; } code_append_ins(co, 2, &&_cf_003); code_append_ins(co, 4, &ofs); START_TEMPLATE _cf_003: asm("movb 0x100(%esi),%bl\n"); } void _a_movb_esi_cl(CodeObj *co, int ofs) { __label__ _cf_001, _cf_002, _cf_003; if(!ofs) { #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb (%%esi),%%cl\n", co->pc); #endif code_append_ins(co, 2, &&_cf_001); START_TEMPLATE _cf_001: asm("movb (%esi),%cl\n"); return; } #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb $%d(%%esi),%%cl\n", co->pc, ofs); #endif if(ofs >=-128 && ofs <=127) { code_append_ins(co, 2, &&_cf_002); code_append_ins(co, 1, &ofs); START_TEMPLATE _cf_002: asm("movb 0x1(%esi),%cl\n"); return; } code_append_ins(co, 2, &&_cf_003); code_append_ins(co, 4, &ofs); START_TEMPLATE _cf_003: asm("movb 0x100(%esi),%cl\n"); } void _a_movb_esi_dl(CodeObj *co, int ofs) { __label__ _cf_001, _cf_002, _cf_003; if(!ofs) { #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb (%%esi),%%dl\n", co->pc); #endif code_append_ins(co, 2, &&_cf_001); START_TEMPLATE _cf_001: asm("movb (%esi),%dl\n"); return; } #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb $%d(%%esi),%%dl\n", co->pc, ofs); #endif if(ofs >=-128 && ofs <=127) { code_append_ins(co, 2, &&_cf_002); code_append_ins(co, 1, &ofs); START_TEMPLATE _cf_002: asm("movb 0x1(%esi),%dl\n"); return; } code_append_ins(co, 2, &&_cf_003); code_append_ins(co, 4, &ofs); START_TEMPLATE _cf_003: asm("movb 0x100(%esi),%dl\n"); } void _a_movb_esi_dh(CodeObj *co, int ofs) { __label__ _cf_001, _cf_002, _cf_003; if(!ofs) { #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb (%%esi),%%dh\n", co->pc); #endif code_append_ins(co, 2, &&_cf_001); START_TEMPLATE _cf_001: asm("movb (%esi),%dh\n"); return; } #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb $%d(%%esi),%%dh\n", co->pc, ofs); #endif if(ofs >=-128 && ofs <=127) { code_append_ins(co, 2, &&_cf_002); code_append_ins(co, 1, &ofs); START_TEMPLATE _cf_002: asm("movb 0x1(%esi),%dh\n"); return; } code_append_ins(co, 2, &&_cf_003); code_append_ins(co, 4, &ofs); START_TEMPLATE _cf_003: asm("movb 0x100(%esi),%dh\n"); } void _a_movl_ebp_edi(CodeObj *co, int ofs) { __label__ _cf_001, _cf_002, _cf_003; if(!ofs) { #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovl %%ebp,(%%edi)\n", co->pc); #endif code_append_ins(co, 2, &&_cf_001); START_TEMPLATE _cf_001: asm("movl %ebp,(%edi)\n"); return; } #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovl %%ebp,$%d(%%edi)\n", co->pc, ofs); #endif if(ofs >=-128 && ofs <=127) { code_append_ins(co, 2, &&_cf_002); code_append_ins(co, 1, &ofs); START_TEMPLATE _cf_002: asm("movl %ebp,0x1(%edi)\n"); return; } code_append_ins(co, 2, &&_cf_003); code_append_ins(co, 4, &ofs); START_TEMPLATE _cf_003: asm("movl %ebp,0x100(%edi)\n"); } void _a_movw_bp_edi(CodeObj *co, int ofs) { __label__ _cf_001, _cf_002, _cf_003; if(!ofs) { #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovw %%bp,(%%edi)\n", co->pc); #endif code_append_ins(co, 3, &&_cf_001); START_TEMPLATE _cf_001: asm("movw %bp,(%edi)\n"); return; } #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovw %%bp,$%d(%%edi)\n", co->pc, ofs); #endif if(ofs >=-128 && ofs <=127) { code_append_ins(co, 3, &&_cf_002); code_append_ins(co, 1, &ofs); START_TEMPLATE _cf_002: asm("movw %bp,0x1(%edi)\n"); return; } code_append_ins(co, 3, &&_cf_003); code_append_ins(co, 4, &ofs); START_TEMPLATE _cf_003: asm("movw %bp,0x100(%edi)\n"); } void _a_movl_edx_edi(CodeObj *co, int ofs) { __label__ _cf_001, _cf_002, _cf_003; if(!ofs) { #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovl %%edx,(%%edi)\n", co->pc); #endif code_append_ins(co, 2, &&_cf_001); START_TEMPLATE _cf_001: asm("movl %edx,(%edi)\n"); return; } #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovl %%edx,$%d(%%edi)\n", co->pc, ofs); #endif if(ofs >=-128 && ofs <=127) { code_append_ins(co, 2, &&_cf_002); code_append_ins(co, 1, &ofs); START_TEMPLATE _cf_002: asm("movl %edx,0x1(%edi)\n"); return; } code_append_ins(co, 2, &&_cf_003); code_append_ins(co, 4, &ofs); START_TEMPLATE _cf_003: asm("movl %edx,0x100(%edi)\n"); } void _a_movw_dx_edi(CodeObj *co, int ofs) { __label__ _cf_001, _cf_002, _cf_003; if(!ofs) { #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovw %%dx,(%%edi)\n", co->pc); #endif code_append_ins(co, 3, &&_cf_001); START_TEMPLATE _cf_001: asm("movw %dx,(%edi)\n"); return; } #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovw %%dx,$%d(%%edi)\n", co->pc, ofs); #endif if(ofs >=-128 && ofs <=127) { code_append_ins(co, 3, &&_cf_002); code_append_ins(co, 1, &ofs); START_TEMPLATE _cf_002: asm("movw %dx,0x1(%edi)\n"); return; } code_append_ins(co, 3, &&_cf_003); code_append_ins(co, 4, &ofs); START_TEMPLATE _cf_003: asm("movw %dx,0x100(%edi)\n"); } void _a_movb_dl_edi(CodeObj *co, int ofs) { __label__ _cf_001, _cf_002, _cf_003; if(!ofs) { #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb %%dl,(%%edi)\n", co->pc); #endif code_append_ins(co, 2, &&_cf_001); START_TEMPLATE _cf_001: asm("movb %dl,(%edi)\n"); return; } #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tmovb %%dl,$%d(%%edi)\n", co->pc, ofs); #endif if(ofs >=-128 && ofs <=127) { code_append_ins(co, 2, &&_cf_002); code_append_ins(co, 1, &ofs); START_TEMPLATE _cf_002: asm("movb %dl,0x1(%edi)\n"); return; } code_append_ins(co, 2, &&_cf_003); code_append_ins(co, 4, &ofs); START_TEMPLATE _cf_003: asm("movb %dl,0x100(%edi)\n"); } void _a_addl_n_edi(CodeObj *co, int n) { __label__ _cf_001, _cf_002, _cf_003; if(!n) return; if(n == 1) { #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tincl %%edi\n", co->pc); #endif code_append_ins(co, 1, &&_cf_001); START_TEMPLATE _cf_001: asm("incl %edi\n"); return; } #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\taddl $%d,%%edi\n", co->pc, n); #endif if(n >=-128 && n <=127) { code_append_ins(co, 2, &&_cf_002); code_append_ins(co, 1, &n); START_TEMPLATE _cf_002: asm("addl $1,%edi\n"); return; } code_append_ins(co, 2, &&_cf_003); code_append_ins(co, 4, &n); START_TEMPLATE _cf_003: asm("addl $0x100,%edi\n"); } void _a_addl_n_esi(CodeObj *co, int n) { __label__ _cf_001, _cf_002, _cf_003; if(!n) return; if(n == 1) { #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tincl %%esi\n", co->pc); #endif code_append_ins(co, 1, &&_cf_001); START_TEMPLATE _cf_001: asm("incl %esi\n"); return; } #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\taddl $%d,%%esi\n", co->pc, n); #endif if(n >=-128 && n <=127) { code_append_ins(co, 2, &&_cf_002); code_append_ins(co, 1, &n); START_TEMPLATE _cf_002: asm("addl $1,%esi\n"); return; } code_append_ins(co, 2, &&_cf_003); code_append_ins(co, 4, &n); START_TEMPLATE _cf_003: asm("addl $0x100,%esi\n"); } void _a_shrl_n_ebp(CodeObj *co, int n) { __label__ _cf_001, _cf_002; n &= 0x1f; if(!n) return; if(n == 1) { #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tshrl %%ebp\n", co->pc); #endif code_append_ins(co, 2, &&_cf_001); START_TEMPLATE _cf_001: asm("shrl %ebp\n"); return; } #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tshrl $%d,%%ebp\n", co->pc, n); #endif code_append_ins(co, 2, &&_cf_002); code_append_ins(co, 1, &n); START_TEMPLATE _cf_002: asm("shrl $2,%ebp\n"); } void _a_shll_n_edx(CodeObj *co, int n) { __label__ _cf_001, _cf_002; n &= 0x1f; if(!n) return; if(n == 1) { #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tshll %%edx\n", co->pc); #endif code_append_ins(co, 2, &&_cf_001); START_TEMPLATE _cf_001: asm("shll %edx\n"); return; } #ifdef REMAP_CODE_DEBUG fprintf(rdm, "0x%04x:\tshll $%d,%%edx\n", co->pc, n); #endif code_append_ins(co, 2, &&_cf_002); code_append_ins(co, 1, &n); START_TEMPLATE _cf_002: asm("shll $2,%edx\n"); } /* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * Pentium optimized functions * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ void pent_8to8_1(RemapObject *); void pent_8to8_all(RemapObject *); static void pent_8to8_all_init(RemapObject *); void pent_8to8p_all(RemapObject *); static void pent_8to8p_all_init(RemapObject *); void pent_8to16_test(RemapObject *); void pent_8to16_1(RemapObject *); void pent_8to16_all(RemapObject *); static void pent_8to16_all_init(RemapObject *); void pent_8to32_1(RemapObject *); void pent_8to32_all(RemapObject *); static void pent_8to32_all_init(RemapObject *); static RemapFuncDesc remap_opt_list[] = { REMAP_DESC( RFF_SCALE_1 | RFF_OPT_PENTIUM | RFF_REMAP_RECT, MODE_PSEUDO_8, MODE_TRUE_8, pent_8to8_1, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_OPT_PENTIUM | RFF_REMAP_LINES, MODE_VGA_X | MODE_PSEUDO_8, MODE_TRUE_8, pent_8to8_all, pent_8to8_all_init ), REMAP_DESC( RFF_SCALE_ALL | RFF_OPT_PENTIUM | RFF_REMAP_LINES, MODE_VGA_X | MODE_PSEUDO_8, MODE_PSEUDO_8, pent_8to8p_all, pent_8to8p_all_init ), #if 0 REMAP_DESC(RFF_SCALE_ALL | RFF_OPT_PENTIUM | RFF_REMAP_LINES, MODE_PSEUDO_8, MODE_TRUE_15 | MODE_TRUE_16, pent_8to16_test, NULL ), #endif REMAP_DESC( RFF_SCALE_1 | RFF_OPT_PENTIUM | RFF_REMAP_RECT, MODE_PSEUDO_8, MODE_TRUE_15 | MODE_TRUE_16, pent_8to16_1, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_OPT_PENTIUM | RFF_REMAP_LINES, MODE_VGA_X | MODE_PSEUDO_8, MODE_TRUE_15 | MODE_TRUE_16, pent_8to16_all, pent_8to16_all_init ), REMAP_DESC( RFF_SCALE_1 | RFF_OPT_PENTIUM | RFF_REMAP_RECT, MODE_PSEUDO_8, MODE_TRUE_32, pent_8to32_1, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_OPT_PENTIUM | RFF_REMAP_LINES, MODE_VGA_X | MODE_PSEUDO_8, MODE_TRUE_32, pent_8to32_all, pent_8to32_all_init ) }; /* * returns chained list of modes */ RemapFuncDesc *remap_opt(void) { int i; for(i = 0; i < sizeof(remap_opt_list) / sizeof(*remap_opt_list) - 1; i++) { remap_opt_list[i].next = remap_opt_list + i + 1; } return remap_opt_list; } /* * create code that remaps a complete line; * needed for pent_8to8_all */ void pent_8to8_all_init(RemapObject *ro) { int i, j, d_o_r, s_o_r, d_o, s_o; int d_len = ro->dst_width & ~3; int *bre_x = ro->bre_x; int b0, b1, b2, b3; CodeObj *co = ro->co; if(co != NULL) { code_done(co); } *co = code_init(); #ifdef REMAP_CODE_DEBUG fprintf(rdm, "- - - - - - - - \n"); fprintf(rdm, "pent_8to8_all_line_remap:\n"); #endif /* * esi, edi: src, dst * eax, ebx: 0 * ecx: true_color_lut * edx: [4*eax], [4*ebx] */ for(i = s_o_r = d_o = s_o = d_o_r = 0; i < d_len; ) { if(d_o > 127) { j = d_o + 128; if(j > ro->dst_scan_len - d_o_r) j = ro->dst_scan_len - d_o_r; _a_addl_n_edi(co, j); d_o_r += j; d_o -= j; } if(s_o > 127) { _a_addl_n_esi(co, j = s_o + 128); s_o_r += j; s_o -= j; } b0 = 0; b1 = bre_x[i++]; b2 = b1 + bre_x[i++]; b3 = b2 + bre_x[i++]; _a_movb_esi_al(co, s_o + b3); if(b3 != b2) { _a_movb_esi_bl(co, s_o + b2); } _a_movb_n_ecx_4eax_dh(co, 1); if(b3 == b2) { _a_movb_n_ecx_4eax_dl(co, 0); } else { _a_movb_n_ecx_4ebx_dl(co, 0); } _a_shll_n_edx(co, 16); if(b1 == b2 && b2 != b3) { if(b0 != b1) { _a_movb_esi_al(co, s_o + b0); } _a_movb_n_ecx_4ebx_dh(co, 1); if(b0 == b1) { _a_movb_n_ecx_4ebx_dl(co, 0); } else { _a_movb_n_ecx_4eax_dl(co, 0); } } else { if(b1 != b3) { _a_movb_esi_al(co, s_o + b1); } if(b0 != b1) { _a_movb_esi_bl(co, s_o + b0); } _a_movb_n_ecx_4eax_dh(co, 1); if(b0 == b1) { _a_movb_n_ecx_4eax_dl(co, 0); } else { _a_movb_n_ecx_4ebx_dl(co, 0); } } _a_movl_edx_edi(co, d_o); d_o += 4; s_o += b3 + bre_x[i++]; } if(ro->dst_width & 2) { _a_movb_esi_al(co, s_o); s_o += bre_x[i++]; _a_movb_esi_bl(co, s_o); s_o += bre_x[i++]; _a_movb_n_ecx_4eax_dl(co, 0); _a_movb_n_ecx_4ebx_dh(co, 1); _a_movw_dx_edi(co, d_o); d_o += 2; } if(ro->dst_width & 1) { _a_movb_esi_al(co, s_o); _a_movb_n_ecx_4eax_dl(co, 0); _a_movb_dl_edi(co, d_o); } _a_addl_n_edi(co, ro->dst_scan_len - d_o_r); _a_ret(co); #ifdef REMAP_CODE_DEBUG fprintf(rdm, "- - - - - - - - \n"); #endif ro->remap_line = co->exec; } /* * create code that remaps a complete line; * needed for pent_8to8p_all */ void pent_8to8p_all_init(RemapObject *ro) { int i, j, d_o_r, s_o_r, d_o, s_o; int d_len = ro->dst_width & ~3; int *bre_x = ro->bre_x; int b0, b1, b2, b3; CodeObj *co = ro->co; if(co != NULL) { code_done(co); } *co = code_init(); #ifdef REMAP_CODE_DEBUG fprintf(rdm, "- - - - - - - - \n"); fprintf(rdm, "pent_8to8p_all_line_remap:\n"); #endif /* * esi, edi: src, dst * eax, ebx, ecx, edx: 0 */ for(i = s_o_r = d_o = s_o = d_o_r = 0; i < d_len; ) { if(d_o > 127) { j = d_o + 128; if(j > ro->dst_scan_len - d_o_r) j = ro->dst_scan_len - d_o_r; _a_addl_n_edi(co, j); d_o_r += j; d_o -= j; } if(s_o > 127) { _a_addl_n_esi(co, j = s_o + 128); s_o_r += j; s_o -= j; } b0 = 0; b1 = bre_x[i++]; b2 = b1 + bre_x[i++]; b3 = b2 + bre_x[i++]; _a_movb_esi_dh(co, s_o + b3); if(b3 == b2) { _a_movb_dh_dl(co); } else { _a_movb_esi_dl(co, s_o + b2); } _a_shll_n_edx(co, 16); _a_movb_esi_dh(co, s_o + b1); if(b3 == b2) { _a_movb_dh_dl(co); } else { _a_movb_esi_dl(co, s_o + b0); } _a_movl_edx_edi(co, d_o); d_o += 4; s_o += b3 + bre_x[i++]; } if(ro->dst_width & 2) { _a_movb_esi_dl(co, s_o); s_o += bre_x[i++]; _a_movb_esi_dh(co, s_o); s_o += bre_x[i++]; _a_movw_dx_edi(co, d_o); d_o += 2; } if(ro->dst_width & 1) { _a_movb_esi_dl(co, s_o); _a_movb_dl_edi(co, d_o); } _a_addl_n_edi(co, ro->dst_scan_len - d_o_r); _a_ret(co); #ifdef REMAP_CODE_DEBUG fprintf(rdm, "- - - - - - - - \n"); #endif ro->remap_line = co->exec; } /* * create code that remaps a complete line; * needed for pent_8to16_all */ void pent_8to16_all_init(RemapObject *ro) { int i, j, d_o_r, s_o_r, d_o, s_o; int d_len = ro->dst_width & ~1; int *bre_x = ro->bre_x; int last_dx0 = -1, last_dx = -1; CodeObj *co = ro->co; if(co != NULL) { code_done(co); } *co = code_init(); #ifdef REMAP_CODE_DEBUG fprintf(rdm, "- - - - - - - - \n"); fprintf(rdm, "pent_8to16_all_line_remap:\n"); #endif /* * esi, edi: src, dst * eax: 0 * ebx, ecx, edx: &true_color_lut[0, 100, 200] * ebp: [4*eax] */ for(i = s_o_r = d_o = s_o = d_o_r = 0; i < d_len; i += 2) { if(d_o > 127) { j = d_o + 128; if(j > ro->dst_scan_len - d_o_r) j = ro->dst_scan_len - d_o_r; _a_addl_n_edi(co, j); d_o_r += j; d_o -= j; } if(ro->src_mode != MODE_VGA_X) { if(s_o > 127) { _a_addl_n_esi(co, j = s_o + 128); s_o_r += j; s_o -= j; } } if(bre_x[i]) { if(last_dx) { _a_movb_esi_al(co, s_o); _a_movl_ecx_4eax_ebp(co); } else { _a_shrl_n_ebp(co, 16); } s_o += bre_x[i]; _a_movb_esi_al(co, s_o); _a_addl_edx_4eax_ebp(co); _a_movl_ebp_edi(co, d_o); } else { if(last_dx) { _a_movb_esi_al(co, s_o); _a_movl_ebx_4eax_ebp(co); } else { if(last_dx0) _a_movl_ebx_4eax_ebp(co); } _a_movl_ebp_edi(co, d_o); } last_dx0 = bre_x[i]; d_o += 4; s_o += (last_dx = bre_x[i + 1]); } if(ro->dst_width & 1) { if(last_dx) { _a_movb_esi_al(co, s_o); _a_movl_ecx_4eax_ebp(co); } else { _a_shrl_n_ebp(co, 16); } _a_movw_bp_edi(co, d_o); } _a_addl_n_edi(co, ro->dst_scan_len - d_o_r); _a_ret(co); #ifdef REMAP_CODE_DEBUG fprintf(rdm, "- - - - - - - - \n"); #endif ro->remap_line = co->exec; } /* * create code that remaps a complete line; * needed for pent_8to32_all */ void pent_8to32_all_init(RemapObject *ro) { int i, j, k, d_o_r, s_o_r, d_o, s_o; int d_len = ro->dst_width; int *bre_x = ro->bre_x; int l0, l1; int b0, b1; CodeObj *co = ro->co; if(co != NULL) { code_done(co); } *co = code_init(); #ifdef REMAP_CODE_DEBUG fprintf(rdm, "- - - - - - - - \n"); fprintf(rdm, "pent_8to32_all_line_remap:\n"); #endif /* * esi, edi: src, dst * eax, ecx: 0 * ebx: true_color_lut * ebp, edx: [4*eax], [4*ecx] */ l0 = l1 = 1; b0 = b1 = j = 0; for(i = s_o_r = d_o = s_o = d_o_r = 0; i < d_len; i++) { if(bre_x[i] == 0) { if(j == 0) l0++; else l1++; } else { if(j == 0) b0 = bre_x[i]; else b1 = bre_x[i]; j++; } if(j == 2 || i == d_len - 1) { if(d_o > 127) { k = d_o + 128; if(k > ro->dst_scan_len - d_o_r) k = ro->dst_scan_len - d_o_r; _a_addl_n_edi(co, k); d_o_r += k; d_o -= k; } if(ro->src_mode != MODE_VGA_X) { if(s_o > 127) { _a_addl_n_esi(co, k = s_o + 128); s_o_r += k; s_o -= k; } } if(j == 1) { _a_movb_esi_al(co, s_o); _a_movl_ebx_4eax_ebp(co); _a_movl_ebp_edi(co, d_o); } if(j == 2) { _a_movb_esi_al(co, s_o); _a_movb_esi_cl(co, s_o + b0); _a_movl_ebx_4eax_ebp(co); _a_movl_ebx_4ecx_edx(co); for(k = 0; k < l0; k++) _a_movl_ebp_edi(co, d_o + (k << 2)); for(k = 0; k < l1; k++) _a_movl_edx_edi(co, d_o + ((k + l0) << 2)); d_o += (l0 + l1) << 2; s_o += b0 + b1; } l0 = l1 = 1; j = 0; } } _a_addl_n_edi(co, ro->dst_scan_len - d_o_r); _a_ret(co); #ifdef REMAP_CODE_DEBUG fprintf(rdm, "- - - - - - - - \n"); #endif ro->remap_line = co->exec; } /* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * some not so optimized remap functions * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ void gen_8to8p_1(RemapObject *); void gen_8to8p_all(RemapObject *); void gen_8to8_1(RemapObject *); void gen_8to8_all(RemapObject *); void gen_8to16_all(RemapObject *); void gen_8to24_all(RemapObject *); void gen_8to32_1(RemapObject *); void gen_8to32_all(RemapObject *); void gen_8to32_bilin(RemapObject *); void gen_8to16_bilin(RemapObject *); void gen_8to32_lin(RemapObject *); void gen_8to16_lin(RemapObject *); void gen_4to8p_all(RemapObject *); void gen_4to8_all(RemapObject *); void gen_4to16_all(RemapObject *); void gen_4to24_all(RemapObject *); void gen_4to32_all(RemapObject *); void gen_16to16_1(RemapObject *); void gen_24to24_1(RemapObject *); void gen_32to32_1(RemapObject *); void gen_24to32_1(RemapObject *); void gen_1to8p_all(RemapObject *); void gen_1to8_all(RemapObject *); void gen_1to16_all(RemapObject *); void gen_1to24_all(RemapObject *); void gen_1to32_all(RemapObject *); void gen_2to8p_all(RemapObject *); void gen_2to8_all(RemapObject *); void gen_2to16_all(RemapObject *); void gen_2to24_all(RemapObject *); void gen_2to32_all(RemapObject *); void gen_c2to8p_all(RemapObject *); void gen_c2to8_all(RemapObject *); void gen_c2to16_all(RemapObject *); void gen_c2to24_all(RemapObject *); void gen_c2to32_all(RemapObject *); static RemapFuncDesc remap_gen_list[] = { REMAP_DESC( RFF_SCALE_1 | RFF_REMAP_LINES, MODE_PSEUDO_8, MODE_PSEUDO_8, gen_8to8p_1, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_VGA_X | MODE_PSEUDO_8, MODE_PSEUDO_8, gen_8to8p_all, NULL ), REMAP_DESC( RFF_SCALE_1 | RFF_REMAP_RECT, MODE_PSEUDO_8, MODE_TRUE_8, gen_8to8_1, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_VGA_X | MODE_PSEUDO_8, MODE_TRUE_8, gen_8to8_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_VGA_X | MODE_PSEUDO_8, MODE_TRUE_15 | MODE_TRUE_16, gen_8to16_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_VGA_X | MODE_PSEUDO_8, MODE_TRUE_24, gen_8to24_all, NULL ), REMAP_DESC( RFF_SCALE_1 | RFF_REMAP_RECT, MODE_PSEUDO_8, MODE_TRUE_32, gen_8to32_1, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_VGA_X | MODE_PSEUDO_8, MODE_TRUE_32, gen_8to32_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES | RFF_BILIN_FILT, MODE_PSEUDO_8, MODE_TRUE_32, gen_8to32_bilin, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES | RFF_BILIN_FILT, MODE_PSEUDO_8, MODE_TRUE_15 | MODE_TRUE_16, gen_8to16_bilin, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES | RFF_LIN_FILT, MODE_PSEUDO_8, MODE_TRUE_32, gen_8to32_lin, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES | RFF_LIN_FILT, MODE_PSEUDO_8, MODE_TRUE_15 | MODE_TRUE_16, gen_8to16_lin, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_VGA_4, MODE_PSEUDO_8, gen_4to8p_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_VGA_4, MODE_TRUE_8, gen_4to8_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_VGA_4, MODE_TRUE_15 | MODE_TRUE_16, gen_4to16_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_VGA_4, MODE_TRUE_24, gen_4to24_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_VGA_4, MODE_TRUE_32, gen_4to32_all, NULL ), REMAP_DESC( RFF_SCALE_1 | RFF_REMAP_LINES, MODE_TRUE_15, MODE_TRUE_15, gen_16to16_1, NULL ), REMAP_DESC( RFF_SCALE_1 | RFF_REMAP_LINES, MODE_TRUE_16, MODE_TRUE_16, gen_16to16_1, NULL ), REMAP_DESC( RFF_SCALE_1 | RFF_REMAP_LINES, MODE_TRUE_24, MODE_TRUE_24, gen_24to24_1, NULL ), REMAP_DESC( RFF_SCALE_1 | RFF_REMAP_LINES, MODE_TRUE_32, MODE_TRUE_32, gen_32to32_1, NULL ), REMAP_DESC( RFF_SCALE_1 | RFF_REMAP_LINES, MODE_TRUE_24, MODE_TRUE_32, gen_24to32_1, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_VGA_1 | MODE_CGA_1 | MODE_HERC, MODE_PSEUDO_8, gen_1to8p_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_VGA_1 | MODE_CGA_1 | MODE_HERC, MODE_TRUE_8, gen_1to8_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_VGA_1 | MODE_CGA_1 | MODE_HERC, MODE_TRUE_15 | MODE_TRUE_16, gen_1to16_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_VGA_1 | MODE_CGA_1 | MODE_HERC, MODE_TRUE_24, gen_1to24_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_VGA_1 | MODE_CGA_1 | MODE_HERC, MODE_TRUE_32, gen_1to32_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_VGA_2, MODE_PSEUDO_8, gen_2to8p_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_VGA_2, MODE_TRUE_8, gen_2to8_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_VGA_2, MODE_TRUE_15 | MODE_TRUE_16, gen_2to16_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_VGA_2, MODE_TRUE_24, gen_2to24_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_VGA_2, MODE_TRUE_32, gen_2to32_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_CGA_2, MODE_PSEUDO_8, gen_c2to8p_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_CGA_2, MODE_TRUE_8, gen_c2to8_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_CGA_2, MODE_TRUE_15 | MODE_TRUE_16, gen_c2to16_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_CGA_2, MODE_TRUE_24, gen_c2to24_all, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_CGA_2, MODE_TRUE_32, gen_c2to32_all, NULL ), }; /* * returns chained list of modes */ RemapFuncDesc *remap_gen(void) { int i; for(i = 0; i < sizeof(remap_gen_list) / sizeof(*remap_gen_list) - 1; i++) { remap_gen_list[i].next = remap_gen_list + i + 1; } return remap_gen_list; } /* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * now the implementation * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* * 8 bit pseudo color --> 8 bit pseudo color (private color map) */ void gen_8to8p_1(RemapObject *ro) { int i; unsigned char *src, *dst; src = ro->src_image + ro->src_offset; dst = ro->dst_image + ro->dst_offset; for(i = ro->src_y0; i < ro->src_y1; i++) { memcpy(dst, src, ro->src_width); src += ro->src_scan_len; dst += ro->dst_scan_len; } } /* * 8 bit pseudo color --> 8 bit pseudo color (private color map) * supports arbitrary scaling */ void gen_8to8p_all(RemapObject *ro) { int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len; int *bre_x; int *bre_y = ro->bre_y; unsigned char *src, *src0, *dst; src0 = ro->src_image; dst = ro->dst_image + ro->dst_offset; d_x_len = ro->dst_width; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { dst[d_x++] = src[s_x]; s_x += *(bre_x++); } } } /* * 8 bit pseudo color --> 8 bit true color (shared color map) */ void gen_8to8_1(RemapObject *ro) { int i, j, l, k; unsigned char *src, *dst; unsigned char *lut = (unsigned char*) ro->true_color_lut; src = ro->src_image + ro->src_offset; dst = ro->dst_image + ro->dst_offset; l = ro->src_x1 - ro->src_x0; for(j = ro->src_y0; j < ro->src_y1; j++) { k = (j & 1) << 1; for(i = 0; i < l; i++) { dst[i] = lut[4 * src[i] + (k ^= 1)]; } dst += ro->dst_scan_len; src += ro->src_scan_len; } } /* * 8 bit pseudo color --> 8 bit true color (shared color map) * supports arbitrary scaling */ void gen_8to8_all(RemapObject *ro) { int k; int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len; int *bre_x; int *bre_y = ro->bre_y; unsigned char *src, *src0, *dst; unsigned char *lut = (unsigned char*) ro->true_color_lut; src0 = ro->src_image; dst = ro->dst_image + ro->dst_offset; d_x_len = ro->dst_width; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; k = (d_y & 1) << 1; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { dst[d_x++] = lut[4 * src[s_x] + (k ^= 1)]; s_x += *(bre_x++); } } } /* * 8 bit pseudo color --> 15/16 bit true color * supports arbitrary scaling */ void gen_8to16_all(RemapObject *ro) { int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len >> 1; int *bre_x; int *bre_y = ro->bre_y; unsigned char *src, *src0; unsigned short *dst; src0 = ro->src_image; dst = (unsigned short *) (ro->dst_image + ro->dst_offset); d_x_len = ro->dst_width; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { dst[d_x++] = ro->true_color_lut[src[s_x]]; s_x += *(bre_x++); } } } /* * 8 bit pseudo color --> 24 bit true color * supports arbitrary scaling */ void gen_8to24_all(RemapObject *ro) { int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len; int *bre_x; int *bre_y = ro->bre_y; unsigned char *src, *src0; unsigned char *dst; unsigned long long color; src0 = ro->src_image; dst = (ro->dst_image + ro->dst_offset); d_x_len = ro->dst_width *3; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { color = ro->true_color_lut[src[s_x]]; dst[d_x++] = color & 0xFF; dst[d_x++] = (color >> 8) & 0xFF; dst[d_x++] = (color >> 16) & 0xFF; s_x += *(bre_x++); } } } /* * 8 bit pseudo color --> 32 bit true color */ void gen_8to32_1(RemapObject *ro) { int i, j, l; unsigned char *src; unsigned *dst; src = ro->src_image + ro->src_offset; dst = (unsigned *) (ro->dst_image + ro->dst_offset); l = (ro->src_x1 - ro->src_x0); for(j = ro->src_y0; j < ro->src_y1; j++) { for(i = 0; i < l; i++) { dst[i] = ro->true_color_lut[src[i]]; } dst += ro->dst_scan_len >> 2; src += ro->src_scan_len; } } /* * 8 bit pseudo color --> 32 bit true color * supports arbitrary scaling */ void gen_8to32_all(RemapObject *ro) { int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len >> 2; int *bre_x; int *bre_y = ro->bre_y; unsigned char *src, *src0; unsigned *dst; src0 = ro->src_image; dst = (unsigned *) (ro->dst_image + ro->dst_offset); d_x_len = ro->dst_width; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { dst[d_x++] = ro->true_color_lut[src[s_x]]; s_x += *(bre_x++); } } } /* * 8 bit pseudo color --> 32 bit true color * supports arbitrary scaling */ void gen_8to32_bilin(RemapObject *ro) { int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len >> 2; int s_scan_len = ro->src_scan_len; int *bre_x; int *bre_y = ro->bre_y; unsigned char *src, *src0, *src1; unsigned *dst; unsigned *lut = ro->true_color_lut; src0 = ro->src_image; dst = (unsigned *) (ro->dst_image + ro->dst_offset); d_x_len = ro->dst_width; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; src1 = src + s_scan_len; switch(*(bre_y + d_y - 1 + ro->dst_height)) { case 0: for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { switch(*(bre_x + d_x_len)) { case 0: dst[d_x++] = lut[src[s_x]]; break; case 1: dst[d_x++] = lut[src[s_x] + LUT_OFS_67] + lut[src[s_x + 1] + LUT_OFS_33]; break; case 2: dst[d_x++] = lut[src[s_x] + LUT_OFS_33] + lut[src[s_x + 1] + LUT_OFS_67]; break; default: fprintf(stderr, "***** oops\n"); } s_x += *(bre_x++); } break; case 1: for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { switch(*(bre_x + d_x_len)) { case 0: dst[d_x++] = lut[src[s_x ] + LUT_OFS_67] + lut[src[s_x + s_scan_len] + LUT_OFS_33]; break; case 1: dst[d_x++] = lut[src[s_x ] + LUT_OFS_45] + lut[src[s_x + 1 ] + LUT_OFS_22] + lut[src[s_x + s_scan_len] + LUT_OFS_22] + lut[src[s_x + s_scan_len + 1] + LUT_OFS_11]; break; case 2: dst[d_x++] = lut[src[s_x ] + LUT_OFS_22] + lut[src[s_x + 1 ] + LUT_OFS_45] + lut[src[s_x + s_scan_len] + LUT_OFS_11] + lut[src[s_x + s_scan_len + 1] + LUT_OFS_22]; break; default: fprintf(stderr, "***** oops\n"); } s_x += *(bre_x++); } break; case 2: for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { switch(*(bre_x + d_x_len)) { case 0: dst[d_x++] = lut[src[s_x ] + LUT_OFS_33] + lut[src[s_x + s_scan_len] + LUT_OFS_67]; break; case 1: dst[d_x++] = lut[src[s_x ] + LUT_OFS_22] + lut[src[s_x + 1 ] + LUT_OFS_11] + lut[src[s_x + s_scan_len] + LUT_OFS_45] + lut[src[s_x + s_scan_len + 1] + LUT_OFS_22]; break; case 2: dst[d_x++] = lut[src[s_x ] + LUT_OFS_11] + lut[src[s_x + 1 ] + LUT_OFS_22] + lut[src[s_x + s_scan_len] + LUT_OFS_22] + lut[src[s_x + s_scan_len + 1] + LUT_OFS_45]; break; default: fprintf(stderr, "***** oops\n"); } s_x += *(bre_x++); } break; default: fprintf(stderr, "###### oops\n"); } } } /* * 8 bit pseudo color --> 15/16 bit true color * supports arbitrary scaling */ void gen_8to16_bilin(RemapObject *ro) { int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len >> 1; int s_scan_len = ro->src_scan_len; int *bre_x; int *bre_y = ro->bre_y; unsigned char *src, *src0, *src1; unsigned short *dst; unsigned *lut = ro->true_color_lut; src0 = ro->src_image; dst = (unsigned short *) (ro->dst_image + ro->dst_offset); d_x_len = ro->dst_width; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; src1 = src + s_scan_len; switch(*(bre_y + d_y - 1 + ro->dst_height)) { case 0: for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { switch(*(bre_x + d_x_len)) { case 0: dst[d_x++] = lut[src[s_x]]; break; case 1: dst[d_x++] = lut[src[s_x] + LUT_OFS_67] + lut[src[s_x + 1] + LUT_OFS_33]; break; case 2: dst[d_x++] = lut[src[s_x] + LUT_OFS_33] + lut[src[s_x + 1] + LUT_OFS_67]; break; default: fprintf(stderr, "***** oops\n"); } s_x += *(bre_x++); } break; case 1: for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { switch(*(bre_x + d_x_len)) { case 0: dst[d_x++] = lut[src[s_x ] + LUT_OFS_67] + lut[src[s_x + s_scan_len] + LUT_OFS_33]; break; case 1: dst[d_x++] = lut[src[s_x ] + LUT_OFS_45] + lut[src[s_x + 1 ] + LUT_OFS_22] + lut[src[s_x + s_scan_len] + LUT_OFS_22] + lut[src[s_x + s_scan_len + 1] + LUT_OFS_11]; break; case 2: dst[d_x++] = lut[src[s_x ] + LUT_OFS_22] + lut[src[s_x + 1 ] + LUT_OFS_45] + lut[src[s_x + s_scan_len] + LUT_OFS_11] + lut[src[s_x + s_scan_len + 1] + LUT_OFS_22]; break; default: fprintf(stderr, "***** oops\n"); } s_x += *(bre_x++); } break; case 2: for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { switch(*(bre_x + d_x_len)) { case 0: dst[d_x++] = lut[src[s_x ] + LUT_OFS_33] + lut[src[s_x + s_scan_len] + LUT_OFS_67]; break; case 1: dst[d_x++] = lut[src[s_x ] + LUT_OFS_22] + lut[src[s_x + 1 ] + LUT_OFS_11] + lut[src[s_x + s_scan_len] + LUT_OFS_45] + lut[src[s_x + s_scan_len + 1] + LUT_OFS_22]; break; case 2: dst[d_x++] = lut[src[s_x ] + LUT_OFS_11] + lut[src[s_x + 1 ] + LUT_OFS_22] + lut[src[s_x + s_scan_len] + LUT_OFS_22] + lut[src[s_x + s_scan_len + 1] + LUT_OFS_45]; break; default: fprintf(stderr, "***** oops\n"); } s_x += *(bre_x++); } break; default: fprintf(stderr, "###### oops\n"); } } } /* * 8 bit pseudo color --> 32 bit true color * supports arbitrary scaling */ void gen_8to32_lin(RemapObject *ro) { int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len >> 2; int *bre_x; int *bre_y = ro->bre_y; unsigned char *src, *src0; unsigned *dst; src0 = ro->src_image; dst = (unsigned *) (ro->dst_image + ro->dst_offset); d_x_len = ro->dst_width; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { switch(*(bre_x + d_x_len)) { case 0: dst[d_x++] = ro->true_color_lut[src[s_x]]; break; case 1: dst[d_x++] = ro->true_color_lut[src[s_x] + LUT_OFS_67] + ro->true_color_lut[src[s_x + 1] + LUT_OFS_33]; break; case 2: dst[d_x++] = ro->true_color_lut[src[s_x] + LUT_OFS_33] + ro->true_color_lut[src[s_x + 1] + LUT_OFS_67]; break; default: fprintf(stderr, "***** oops\n"); } s_x += *(bre_x++); } } } /* * 8 bit pseudo color --> 15/16 bit true color * supports arbitrary scaling */ void gen_8to16_lin(RemapObject *ro) { int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len >> 1; int *bre_x; int *bre_y = ro->bre_y; unsigned char *src, *src0; unsigned short *dst; src0 = ro->src_image; dst = (unsigned short *) (ro->dst_image + ro->dst_offset); d_x_len = ro->dst_width; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { switch(*(bre_x + d_x_len)) { case 0: dst[d_x++] = ro->true_color_lut[src[s_x]]; break; case 1: dst[d_x++] = ro->true_color_lut[src[s_x] + LUT_OFS_67] + ro->true_color_lut[src[s_x + 1] + LUT_OFS_33]; break; case 2: dst[d_x++] = ro->true_color_lut[src[s_x] + LUT_OFS_33] + ro->true_color_lut[src[s_x + 1] + LUT_OFS_67]; break; default: fprintf(stderr, "***** oops\n"); } s_x += *(bre_x++); } } } /* * 4 bit pseudo color --> 8 bit pseudo color (private color map) * supports arbitrary scaling * */ void gen_4to8p_all(RemapObject *ro) { int d_x_len, s_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len; int *bre_x; int *bre_y = ro->bre_y; unsigned char *src, *src0, *dst, *src1, *src_last; unsigned *dst1, *lut; src0 = ro->src_image; dst = ro->dst_image + ro->dst_offset; d_x_len = ro->dst_width; s_x_len = ro->src_width >> 3; src1 = ro->src_tmp_line; dst1 = (unsigned *) src1; lut = ro->bit_lut; src_last = NULL; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; if(src != src_last) { src_last = src; for(s_x = d_x = 0; s_x < s_x_len; s_x++, d_x += 2) { dst1[d_x ] = lut[2 * src[s_x ] ] | lut[2 * src[s_x + 0x10000] + 0x200] | lut[2 * src[s_x + 0x20000] + 0x400] | lut[2 * src[s_x + 0x30000] + 0x600]; dst1[d_x + 1] = lut[2 * src[s_x ] + 1 ] | lut[2 * src[s_x + 0x10000] + 1 + 0x200] | lut[2 * src[s_x + 0x20000] + 1 + 0x400] | lut[2 * src[s_x + 0x30000] + 1 + 0x600]; } } for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { dst[d_x++] = src1[s_x]; s_x += *(bre_x++); } } } /* * 4 bit pseudo color --> 8 bit true color (shared color map) * supports arbitrary scaling * */ void gen_4to8_all(RemapObject *ro) { int k; int d_x_len, s_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len; int *bre_x; int *bre_y = ro->bre_y; unsigned char *src, *src0, *dst, *src1, *src_last; unsigned char *clut = (unsigned char*) ro->true_color_lut; unsigned *dst1, *lut; src0 = ro->src_image; dst = ro->dst_image + ro->dst_offset; d_x_len = ro->dst_width; s_x_len = ro->src_width >> 3; src1 = ro->src_tmp_line; dst1 = (unsigned *) src1; lut = ro->bit_lut; src_last = NULL; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; k = (d_y & 1) << 1; if(src != src_last) { src_last = src; for(s_x = d_x = 0; s_x < s_x_len; s_x++, d_x += 2) { dst1[d_x ] = lut[2 * src[s_x ] ] | lut[2 * src[s_x + 0x10000] + 0x200] | lut[2 * src[s_x + 0x20000] + 0x400] | lut[2 * src[s_x + 0x30000] + 0x600]; dst1[d_x + 1] = lut[2 * src[s_x ] + 1 ] | lut[2 * src[s_x + 0x10000] + 1 + 0x200] | lut[2 * src[s_x + 0x20000] + 1 + 0x400] | lut[2 * src[s_x + 0x30000] + 1 + 0x600]; } } for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { dst[d_x++] = clut[4 * src1[s_x] + (k ^= 1)]; s_x += *(bre_x++); } } } /* * 4 bit pseudo color --> 15/16 bit true color * supports arbitrary scaling * */ void gen_4to16_all(RemapObject *ro) { int d_x_len, s_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len >> 1; int *bre_x; int *bre_y = ro->bre_y; unsigned char *src, *src0, *src1, *src_last; unsigned short *dst; unsigned *dst1, *lut; src0 = ro->src_image; dst = (unsigned short *) (ro->dst_image + ro->dst_offset); d_x_len = ro->dst_width; s_x_len = ro->src_width >> 3; src1 = ro->src_tmp_line; dst1 = (unsigned *) src1; lut = ro->bit_lut; src_last = NULL; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; if(src != src_last) { src_last = src; for(s_x = d_x = 0; s_x < s_x_len; s_x++, d_x += 2) { dst1[d_x ] = lut[2 * src[s_x ] ] | lut[2 * src[s_x + 0x10000] + 0x200] | lut[2 * src[s_x + 0x20000] + 0x400] | lut[2 * src[s_x + 0x30000] + 0x600]; dst1[d_x + 1] = lut[2 * src[s_x ] + 1 ] | lut[2 * src[s_x + 0x10000] + 1 + 0x200] | lut[2 * src[s_x + 0x20000] + 1 + 0x400] | lut[2 * src[s_x + 0x30000] + 1 + 0x600]; } } for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { dst[d_x++] = ro->true_color_lut[src1[s_x]]; s_x += *(bre_x++); } } } /* * 4 bit pseudo color --> 24 bit true color * supports arbitrary scaling * */ void gen_4to24_all(RemapObject *ro) { int d_x_len, s_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len; int *bre_x; int *bre_y = ro->bre_y; unsigned *dst1, *lut; unsigned char *src, *src0, *src1, *src_last; unsigned char *dst; unsigned color; src0 = ro->src_image; dst = (ro->dst_image + ro->dst_offset); d_x_len = ro->dst_width *3; s_x_len = ro->src_width >> 3; src1 = ro->src_tmp_line; dst1 = (unsigned *) src1; lut = ro->bit_lut; src_last = NULL; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; if(src != src_last) { src_last = src; for(s_x = d_x = 0; s_x < s_x_len; s_x++, d_x += 2) { dst1[d_x ] = lut[2 * src[s_x ] ] | lut[2 * src[s_x + 0x10000] + 0x200] | lut[2 * src[s_x + 0x20000] + 0x400] | lut[2 * src[s_x + 0x30000] + 0x600]; dst1[d_x + 1] = lut[2 * src[s_x ] + 1 ] | lut[2 * src[s_x + 0x10000] + 1 + 0x200] | lut[2 * src[s_x + 0x20000] + 1 + 0x400] | lut[2 * src[s_x + 0x30000] + 1 + 0x600]; } } for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { color = ro->true_color_lut[src1[s_x]]; dst[d_x++] = color & 0xFF; dst[d_x++] = (color >> 8) & 0xFF; dst[d_x++] = (color >> 16) & 0xFF; s_x += *(bre_x++); } } } /* * 4 bit pseudo color --> 32 bit true color * supports arbitrary scaling * */ void gen_4to32_all(RemapObject *ro) { int d_x_len, s_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len >> 2; int *bre_x; int *bre_y = ro->bre_y; unsigned *dst1, *lut; unsigned char *src, *src0, *src1, *src_last; unsigned *dst; src0 = ro->src_image; dst = (unsigned *) (ro->dst_image + ro->dst_offset); d_x_len = ro->dst_width; s_x_len = ro->src_width >> 3; src1 = ro->src_tmp_line; dst1 = (unsigned *) src1; lut = ro->bit_lut; src_last = NULL; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; if(src != src_last) { src_last = src; for(s_x = d_x = 0; s_x < s_x_len; s_x++, d_x += 2) { dst1[d_x ] = lut[2 * src[s_x ] ] | lut[2 * src[s_x + 0x10000] + 0x200] | lut[2 * src[s_x + 0x20000] + 0x400] | lut[2 * src[s_x + 0x30000] + 0x600]; dst1[d_x + 1] = lut[2 * src[s_x ] + 1 ] | lut[2 * src[s_x + 0x10000] + 1 + 0x200] | lut[2 * src[s_x + 0x20000] + 1 + 0x400] | lut[2 * src[s_x + 0x30000] + 1 + 0x600]; } } for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { dst[d_x++] = ro->true_color_lut[src1[s_x]]; s_x += *(bre_x++); } } } /* * 16 bit true color --> 16 bit true color * 15 bit true color --> 15 bit true color */ void gen_16to16_1(RemapObject *ro) { int i; unsigned char *src, *dst; src = ro->src_image + ro->src_offset; dst = ro->dst_image + ro->dst_offset; for(i = ro->src_y0; i < ro->src_y1; i++) { memcpy(dst, src, ro->src_width << 1); src += ro->src_scan_len; dst += ro->dst_scan_len; } } /* * 24 bit true color --> 24 bit true color */ void gen_24to24_1(RemapObject *ro) { int i; unsigned char *src, *dst; src = ro->src_image + ro->src_offset; dst = ro->dst_image + ro->dst_offset; for(i = ro->src_y0; i < ro->src_y1; i++) { memcpy(dst, src, ro->src_width * 3); src += ro->src_scan_len; dst += ro->dst_scan_len; } } /* * 32 bit true color --> 32 bit true color */ void gen_32to32_1(RemapObject *ro) { int i; unsigned char *src, *dst; src = ro->src_image + ro->src_offset; dst = ro->dst_image + ro->dst_offset; for(i = ro->src_y0; i < ro->src_y1; i++) { memcpy(dst, src, ro->src_width << 2); src += ro->src_scan_len; dst += ro->dst_scan_len; } } /* * 24 bit true color --> 32 bit true color * *** ingnores color space description *** */ void gen_24to32_1(RemapObject *ro) { int i, j; unsigned char *src, *dst, *src_1; unsigned *dst_4; src = ro->src_image + ro->src_offset; dst = ro->dst_image + ro->dst_offset; for(i = ro->src_y0; i < ro->src_y1; i++) { src_1 = src; dst_4 = (unsigned *) dst; for(j = 0; j < ro->src_width; j++) { *dst_4++ = src_1[0] + (src_1[1] << 8) + (src_1[2] << 16); src_1 += 3; } src += ro->src_scan_len; dst += ro->dst_scan_len; } } /* * 1 bit pseudo color --> 8 bit pseudo color (private color map) * supports arbitrary scaling * * -- very basic and slow -- */ void gen_1to8p_all(RemapObject *ro) { int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len; int *bre_x; int *bre_y = ro->bre_y; unsigned char c0; int i; unsigned char *src, *src0, *dst; src0 = ro->src_image; dst = ro->dst_image + ro->dst_offset; d_x_len = ro->dst_width; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { i = s_x >> 3; c0 = src[i]; i = (s_x & 7) ^ 7; c0 >>= i; c0 &= 1; dst[d_x++] = c0; s_x += *(bre_x++); } } } /* * 1 bit pseudo color --> 8 bit true color (shared color map) * supports arbitrary scaling * * -- very basic and slow -- */ void gen_1to8_all(RemapObject *ro) { int k; int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len; int *bre_x; int *bre_y = ro->bre_y; unsigned char *src, *src0, *dst; unsigned char *lut = (unsigned char*) ro->true_color_lut; unsigned char c0; int i; src0 = ro->src_image; dst = ro->dst_image + ro->dst_offset; d_x_len = ro->dst_width; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; k = (d_y & 1) << 1; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { i = s_x >> 3; c0 = src[i]; i = (s_x & 7) ^ 7; c0 >>= i; c0 &= 1; dst[d_x++] = lut[4 * c0 + (k ^= 1)]; s_x += *(bre_x++); } } } /* * 1 bit pseudo color --> 15/16 bit true color * supports arbitrary scaling * * -- very basic and slow -- */ void gen_1to16_all(RemapObject *ro) { int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len >> 1; int *bre_x; int *bre_y = ro->bre_y; unsigned char c0; unsigned char *src, *src0; unsigned short *dst; src0 = ro->src_image; dst = (unsigned short *) (ro->dst_image + ro->dst_offset); d_x_len = ro->dst_width; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { c0 = (src[s_x >> 3] >> ((s_x & 7) ^ 7)) & 1; dst[d_x++] = ro->true_color_lut[c0]; s_x += *(bre_x++); } } } /* * 1 bit pseudo color --> 24 bit true color * supports arbitrary scaling * * -- very basic and slow -- */ void gen_1to24_all(RemapObject *ro) { int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len; int *bre_x; int *bre_y = ro->bre_y; unsigned char c0; unsigned char *src, *src0; unsigned char *dst; unsigned color; src0 = ro->src_image; dst = (ro->dst_image + ro->dst_offset); d_x_len = ro->dst_width *3; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { c0 = (src[s_x >> 3] >> ((s_x & 7) ^ 7)) & 1; color = ro->true_color_lut[c0]; dst[d_x++] = color & 0xFF; dst[d_x++] = (color >> 8) & 0xFF; dst[d_x++] = (color >> 16) & 0xFF; s_x += *(bre_x++); } } } /* * 1 bit pseudo color --> 32 bit true color * supports arbitrary scaling * * -- very basic and slow -- */ void gen_1to32_all(RemapObject *ro) { int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len >> 2; int *bre_x; int *bre_y = ro->bre_y; unsigned char c0; unsigned char *src, *src0; unsigned *dst; src0 = ro->src_image; dst = (unsigned *) (ro->dst_image + ro->dst_offset); d_x_len = ro->dst_width; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { c0 = (src[s_x >> 3] >> ((s_x & 7) ^ 7)) & 1; dst[d_x++] = ro->true_color_lut[c0]; s_x += *(bre_x++); } } } /* * 2 bit VGA pseudo color --> 8 bit pseudo color (private color map) * supports arbitrary scaling * * -- very basic and slow -- */ void gen_2to8p_all(RemapObject *ro) { int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len; int *bre_x; int *bre_y = ro->bre_y; unsigned char c0, c1; int i; unsigned char *src, *src0, *dst; src0 = ro->src_image; dst = ro->dst_image + ro->dst_offset; d_x_len = ro->dst_width; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { i = s_x >> 3; c0 = src[i]; c1 = src[i + 0x20000]; i = (s_x & 7) ^ 7; c0 >>= i; c1 >>= i; c0 &= 1; c1 &= 1; c0 |= c1 << 1; dst[d_x++] = c0; s_x += *(bre_x++); } } } /* * 2 bit VGA pseudo color --> 8 bit true color (shared color map) * supports arbitrary scaling * * -- very basic and slow -- */ void gen_2to8_all(RemapObject *ro) { int k; int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len; int *bre_x; int *bre_y = ro->bre_y; unsigned char *src, *src0, *dst; unsigned char *lut = (unsigned char*) ro->true_color_lut; unsigned char c0, c1; int i; src0 = ro->src_image; dst = ro->dst_image + ro->dst_offset; d_x_len = ro->dst_width; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; k = (d_y & 1) << 1; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { i = s_x >> 3; c0 = src[i]; c1 = src[i + 0x20000]; i = (s_x & 7) ^ 7; c0 >>= i; c1 >>= i; c0 &= 1; c1 &= 1; c0 |= c1 << 1; dst[d_x++] = lut[4 * c0 + (k ^= 1)]; s_x += *(bre_x++); } } } /* * 2 bit VGA pseudo color --> 15/16 bit true color * supports arbitrary scaling * * -- very basic and slow -- */ void gen_2to16_all(RemapObject *ro) { int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len >> 1; int *bre_x; int *bre_y = ro->bre_y; unsigned char c0, c1; int i; unsigned char *src, *src0; unsigned short *dst; src0 = ro->src_image; dst = (unsigned short *) (ro->dst_image + ro->dst_offset); d_x_len = ro->dst_width; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { i = s_x >> 3; c0 = src[i]; c1 = src[i + 0x20000]; i = (s_x & 7) ^ 7; c0 >>= i; c1 >>= i; c0 &= 1; c1 &= 1; c0 |= (c1 << 1); dst[d_x++] = ro->true_color_lut[c0]; s_x += *(bre_x++); } } } /* * 2 bit VGA pseudo color --> 24 bit true color * supports arbitrary scaling * * -- very basic and slow -- */ void gen_2to24_all(RemapObject *ro) { int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len; int *bre_x; int *bre_y = ro->bre_y; unsigned char c0, c1; int i; unsigned char *src, *src0; unsigned char *dst; unsigned color; src0 = ro->src_image; dst = (ro->dst_image + ro->dst_offset); d_x_len = ro->dst_width *3; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { i = s_x >> 3; c0 = src[i]; c1 = src[i + 0x20000]; i = (s_x & 7) ^ 7; c0 >>= i; c1 >>= i; c0 &= 1; c1 &= 1;; c0 |= c1 << 1; color = ro->true_color_lut[c0]; dst[d_x++] = color & 0xFF; dst[d_x++] = (color >> 8) & 0xFF; dst[d_x++] = (color >> 16) & 0xFF; s_x += *(bre_x++); } } } /* * 2 bit VGA pseudo color --> 32 bit true color * supports arbitrary scaling * * -- very basic and slow -- */ void gen_2to32_all(RemapObject *ro) { int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len >> 2; int *bre_x; int *bre_y = ro->bre_y; unsigned char c0, c1; int i; unsigned char *src, *src0; unsigned *dst; src0 = ro->src_image; dst = (unsigned *) (ro->dst_image + ro->dst_offset); d_x_len = ro->dst_width; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { i = s_x >> 3; c0 = src[i]; c1 = src[i + 0x20000]; i = (s_x & 7) ^ 7; c0 >>= i; c1 >>= i; c0 &= 1; c1 &= 1;; c0 |= c1 << 1; dst[d_x++] = ro->true_color_lut[c0]; s_x += *(bre_x++); } } } /* * 2 bit CGA pseudo color --> 8 bit pseudo color (private color map) * supports arbitrary scaling * * -- very basic and slow -- */ void gen_c2to8p_all(RemapObject *ro) { int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len; int *bre_x; int *bre_y = ro->bre_y; unsigned char c0; int i; unsigned char *src, *src0, *dst; src0 = ro->src_image; dst = ro->dst_image + ro->dst_offset; d_x_len = ro->dst_width; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { i = s_x >> 2; c0 = src[i]; i = 2 * ((s_x & 3) ^ 3); c0 >>= i; c0 &= 3; dst[d_x++] = c0; s_x += *(bre_x++); } } } /* * 2 bit CGA pseudo color --> 8 bit true color (shared color map) * supports arbitrary scaling * * -- very basic and slow -- */ void gen_c2to8_all(RemapObject *ro) { int k; int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len; int *bre_x; int *bre_y = ro->bre_y; unsigned char *src, *src0, *dst; unsigned char *lut = (unsigned char*) ro->true_color_lut; unsigned char c0; int i; src0 = ro->src_image; dst = ro->dst_image + ro->dst_offset; d_x_len = ro->dst_width; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; k = (d_y & 1) << 1; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { i = s_x >> 2; c0 = src[i]; i = 2 * ((s_x & 3) ^ 3); c0 >>= i; c0 &= 3; dst[d_x++] = lut[4 * c0 + (k ^= 1)]; s_x += *(bre_x++); } } } /* * 2 bit CGA pseudo color --> 15/16 bit true color * supports arbitrary scaling * * -- very basic and slow -- */ void gen_c2to16_all(RemapObject *ro) { int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len >> 1; int *bre_x; int *bre_y = ro->bre_y; unsigned char c0; unsigned char *src, *src0; unsigned short *dst; src0 = ro->src_image; dst = (unsigned short *) (ro->dst_image + ro->dst_offset); d_x_len = ro->dst_width; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { c0 = (src[s_x >> 2] >> (2 * ((s_x & 3) ^ 3))) & 3; dst[d_x++] = ro->true_color_lut[c0]; s_x += *(bre_x++); } } } /* * 2 bit CGA pseudo color --> 24 bit true color * supports arbitrary scaling * * -- very basic and slow -- */ void gen_c2to24_all(RemapObject *ro) { int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len; int *bre_x; int *bre_y = ro->bre_y; unsigned char c0; unsigned char *src, *src0; unsigned char *dst; unsigned color; src0 = ro->src_image; dst = (ro->dst_image + ro->dst_offset); d_x_len = ro->dst_width*3; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { c0 = (src[s_x >> 2] >> (2 * ((s_x & 3) ^ 3))) & 3; color = ro->true_color_lut[c0]; dst[d_x++] = color & 0xFF; dst[d_x++] = (color >> 8) & 0xFF; dst[d_x++] = (color >> 16) & 0xFF; s_x += *(bre_x++); } } } /* * 2 bit CGA pseudo color --> 32 bit true color * supports arbitrary scaling * * -- very basic and slow -- */ void gen_c2to32_all(RemapObject *ro) { int d_x_len; int s_x, d_x, d_y; int d_scan_len = ro->dst_scan_len >> 2; int *bre_x; int *bre_y = ro->bre_y; unsigned char c0; unsigned char *src, *src0; unsigned *dst; src0 = ro->src_image; dst = (unsigned *) (ro->dst_image + ro->dst_offset); d_x_len = ro->dst_width; for(d_y = ro->dst_y0; d_y < ro->dst_y1; dst += d_scan_len) { src = src0 + bre_y[d_y++]; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { c0 = (src[s_x >> 2] >> (2 * ((s_x & 3) ^ 3))) & 3; dst[d_x++] = ro->true_color_lut[c0]; s_x += *(bre_x++); } } } /* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * some test remap functions * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifdef REMAP_TEST void test_8to32_(RemapObject *); static RemapFuncDesc remap_test_list[] = { }; /* * returns chained list of modes */ RemapFuncDesc *remap_test(void) { int i; for(i = 0; i < sizeof(remap_test_list) / sizeof(*remap_test_list) - 1; i++) { remap_test_list[i].next = remap_test_list + i + 1; } return remap_test_list; } #endif