/* * 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 "emu.h" #include #include #include #include #include #include /* mprotect() */ #include "vgaemu.h" #include "mapping.h" #include "init.h" #include "render.h" #include "render_priv.h" #include "remap_priv.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_gen(void); RemapFuncDesc *(*remap_list_funcs[])(void) = { remap_gen, #if 0 #if defined(__i386__) && !defined(__clang__) remap_opt, #endif #endif #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); static void rgb_color_reduce(const ColorSpaceDesc *, int, int, int, RGBColor *); static unsigned rgb_color_reduced_2int(const ColorSpaceDesc *, RGBColor); static unsigned rgb_color_2int(const ColorSpaceDesc *csd, int rbits, int gbits, int bbits, RGBColor c); static void rgb_lin_filt(RGBColor, RGBColor *, RGBColor *); static 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 RectArea remap_mem_1(RemapObject *, int, int); static RectArea remap_rect_1(RemapObject *, int, int, int, int); static RectArea remap_rect_dst_1(RemapObject *, int, int, int, int); static RectArea remap_mem_2(RemapObject *, int, 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 */ static RemapObject *_remap_init(int src_mode, int dst_mode, int features, const ColorSpaceDesc *color_space, int gamma) { RemapObject *ro = malloc(sizeof(*ro)); int color_lut_size = 256; unsigned u, u0, u1; ro->features = features; 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_rect_dst = 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_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->src_start = ro->dst_start = 0; ro->bre_x = ro->bre_y = NULL; ro->true_color_lut = NULL; ro->color_lut_size = 0; ro->bit_lut = NULL; ro->gamma_lut = malloc(256 * (sizeof *ro->gamma_lut)); for(u = 0; u < 256; u++) ro->gamma_lut[u] = gamma_fix(u, gamma); ro->gamma = gamma; ro->remap_func = ro->remap_func_init = NULL; ro->remap_func_flags = 0; ro->remap_func_name = "no_func"; #if 0 ro->co = malloc(sizeof(*ro->co)); if(ro->co == NULL) { ro->state |= ROS_MALLOC_FAIL; } else { *ro->co = code_init(); } #endif ro->remap_line = NULL; ro->func_all = ro->func_1 = ro->func_2 = NULL; if(!base_init) { do_base_init(); base_init = 1; } ro->dst_color_space = color_space; ro->dst_image = NULL; 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 && (ro->func_all->flags & RFF_LIN_FILT)) || (ro->func_1 && (ro->func_1->flags & RFF_LIN_FILT)) || (ro->func_2 && (ro->func_2->flags & RFF_LIN_FILT)) ) { color_lut_size = 256 * 3; } if( (ro->func_all && (ro->func_all->flags & RFF_BILIN_FILT)) || (ro->func_1 && (ro->func_1->flags & RFF_BILIN_FILT)) || (ro->func_2 && (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, sizeof(*ro->true_color_lut)); if(ro->true_color_lut == NULL) ro->state |= ROS_MALLOC_FAIL; ro->color_lut_size = color_lut_size; ro->palette_update = pseudo_col_palette_update; } else if((ro->dst_mode & MODE_TRUE_COL) == ro->dst_mode) { /* **** really too much for now... **** */ color_lut_size *= 3; ro->true_color_lut = calloc(color_lut_size, sizeof(*ro->true_color_lut)); if(ro->true_color_lut == NULL) ro->state |= ROS_MALLOC_FAIL; ro->color_lut_size = color_lut_size; 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; ro->remap_rect_dst = remap_rect_dst_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; } static void _remap_done(RemapObject *ro) { 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 0 if(ro->co != NULL) { code_done(ro->co); free(ro->co); ro->co = NULL; } #endif free(ro); } #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; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 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, bits, 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 && (ro->func_all->flags & RFF_LIN_FILT)) || (ro->func_1 && (ro->func_1->flags & RFF_LIN_FILT)) || (ro->func_2 && (ro->func_2->flags & RFF_LIN_FILT)) || (ro->func_all && (ro->func_all->flags & RFF_BILIN_FILT)) || (ro->func_1 && (ro->func_1->flags & RFF_BILIN_FILT)) || (ro->func_2 && (ro->func_2->flags & RFF_BILIN_FILT)) ) { rgb_color_reduce(ro->dst_color_space, bits, bits, 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 && (ro->func_all->flags & RFF_BILIN_FILT)) || (ro->func_1 && (ro->func_1->flags & RFF_BILIN_FILT)) || (ro->func_2 && (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, bits, 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(const ColorSpaceDesc *csd, int rbits, int gbits, int bbits, RGBColor *c) { c->r &= (1 << rbits) - 1; c->g &= (1 << gbits) - 1; c->b &= (1 << bbits) - 1; if(csd->r_mask || csd->g_mask || csd->b_mask) { c->r = csd->r_bits >= rbits ? c->r << (csd->r_bits - rbits) : c->r >> (rbits - csd->r_bits); c->g = csd->g_bits >= gbits ? c->g << (csd->g_bits - gbits) : c->g >> (gbits - csd->g_bits); c->b = csd->b_bits >= bbits ? c->b << (csd->b_bits - bbits) : c->b >> (bbits - csd->b_bits); } } unsigned rgb_color_reduced_2int(const 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; } static unsigned rgb_color_2int(const ColorSpaceDesc *csd, int rbits, int gbits, int bbits, RGBColor c) { unsigned r, g, b; unsigned i0, i1, i2, i3; if(csd->r_mask || csd->g_mask || csd->b_mask) { rgb_color_reduce(csd, rbits, gbits, bbits, &c); return rgb_color_reduced_2int(csd, c); } c.r &= (1 << rbits) - 1; c.g &= (1 << gbits) - 1; c.b &= (1 << bbits) - 1; #ifdef REMAP_REAL_DITHER if(csd->r_bits && csd->g_bits && csd->b_bits) { r = dit_col(1 << rbits, csd->r_bits, c.r, 5, 1); g = dit_col(1 << gbits, csd->g_bits, c.g, 5, 1); b = dit_col(1 << bbits, csd->b_bits, c.b, 5, 1); i0 = r * csd->r_shift + g * csd->g_shift + b * csd->b_shift; r = dit_col(1 << rbits, csd->r_bits, c.r, 5, 3); g = dit_col(1 << gbits, csd->g_bits, c.g, 5, 3); b = dit_col(1 << bbits, csd->b_bits, c.b, 5, 3); i1 = r * csd->r_shift + g * csd->g_shift + b * csd->b_shift; r = dit_col(1 << rbits, csd->r_bits, c.r, 5, 4); g = dit_col(1 << gbits, csd->g_bits, c.g, 5, 4); b = dit_col(1 << bbits, csd->b_bits, c.b, 5, 4); i2 = r * csd->r_shift + g * csd->g_shift + b * csd->b_shift; r = dit_col(1 << rbits, csd->r_bits, c.r, 5, 2); g = dit_col(1 << gbits, csd->g_bits, c.g, 5, 2); b = dit_col(1 << bbits, 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) >> rbits; g = (c.g * csd->g_bits) >> gbits; b = (c.b * csd->b_bits) >> bbits; i0 = r * csd->r_shift + g * csd->g_shift + b * csd->b_shift; r = (((c.r + (c.r - ((r << rbits) / csd->r_bits))) * csd->r_bits) >> rbits); g = (((c.g + (c.g - ((g << gbits) / csd->g_bits))) * csd->g_bits) >> gbits); b = (((c.b + (c.b - ((b << bbits) / csd->b_bits))) * csd->b_bits) >> bbits); 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; } static unsigned bgr_2int(const ColorSpaceDesc *csd, int rbits, int gbits, int bbits, unsigned bgr) { RGBColor c = { bgr >> (bbits + gbits), bgr >> bbits, bgr }; return rgb_color_2int(csd, rbits, gbits, bbits, c); } #if 0 static RGBColor int_2rgb_color(const 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; } #endif 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) { if ( ro->src_width == width && ro->src_height == height && ro->src_scan_len == scan_len) return; 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) { if ( ro->dst_width == width && ro->dst_height == height && ro->dst_scan_len == scan_len) return; 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; 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; } i1 = offset / ro->src_scan_len; i2 = (offset % ro->src_scan_len) / pixel_size; j1 = (offset + len) / ro->src_scan_len; j2 = ((offset + len) % ro->src_scan_len) / pixel_size; /* 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; if (ro->remap_func_flags & (RFF_REMAP_RECT | 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_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; ra.x = ra.y = 0; ra.width = ro->dst_width; ra.height = ro->dst_height; REMAP_AREA_DEBUG_FUNC(ro); ro->remap_func(ro); } return ra; } static RectArea remap_rect_dst_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->dst_width || y0 >= ro->dst_height) return ra; if(width <= 0 || height <= 0) return ra; x1 = x0 + width; y1 = y0 + height; if(x1 > ro->dst_width) x1 = ro->dst_width, width = x1 - x0; if(y1 > ro->dst_height) y1 = ro->dst_height, height = y1 - y0; ra.x = x0; ra.y = y0; ra.width = width; ra.height = height; 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 = bre_s(x0, ro->src_width, ro->dst_width); ro->src_x1 = bre_s(x1, ro->src_width, ro->dst_width); ro->src_y0 = bre_s(y0, ro->src_height, ro->dst_height); ro->src_y1 = bre_s(y1, ro->src_height, ro->dst_height); ro->src_offset = ro->src_y0 * ro->src_scan_len + ro->src_x0; ro->dst_x0 = x0; ro->dst_x1 = x1; ro->dst_y0 = y0; ro->dst_y1 = y1; 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 = bre_s(y0, ro->src_height, ro->dst_height); ro->src_y1 = bre_s(y1, ro->src_height, ro->dst_height); ro->src_offset = ro->src_y0 * ro->src_scan_len; ro->dst_x0 = 0; ro->dst_x1 = ro->dst_width; ro->dst_y0 = y0; ro->dst_y1 = y1; 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; ra.x = ra.y = 0; ra.width = ro->dst_width; ra.height = 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; 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; 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_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; #define REMAB_COMBS 4 unsigned f_list[6 * REMAB_COMBS]; int features = 6; int i; flags &= (RFF_LIN_FILT | RFF_BILIN_FILT | RFF_SCALE_ALL | RFF_SCALE_1 | RFF_SCALE_2); 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_LIN_FILT) | RFF_BILIN_FILT; f_list[features * 2 + i] = (f_list[i] & ~RFF_BILIN_FILT) | RFF_LIN_FILT; f_list[features * 3 + i] = f_list[i] & ~(RFF_LIN_FILT | RFF_BILIN_FILT); } features *= REMAB_COMBS; 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) { if (remap_features & RFF_BILIN_FILT) remap_features &= ~RFF_LIN_FILT; 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_all) ro->state |= ROS_SCALE_ALL; /* accept partial scalers only if filtering matches or no full scaler */ if (ro->func_1 && ((((ro->func_1->flags ^ remap_features) & (RFF_BILIN_FILT | RFF_LIN_FILT)) == 0) || !ro->func_all)) ro->state |= ROS_SCALE_1; if (ro->func_2 && ((((ro->func_2->flags ^ remap_features) & (RFF_BILIN_FILT | RFF_LIN_FILT)) == 0) || !ro->func_all)) ro->state |= ROS_SCALE_2; if (!ro->state) error("remap function not found for mode %i\n", ro->src_mode); ro->supported_src_modes = find_supported_modes(ro->dst_mode); } #if 0 static int _find_supported_modes(unsigned dst_mode) { int modes = 0; RemapFuncDesc *rfd; if(!base_init) { do_base_init(); base_init = 1; } rfd = remap_list; while(rfd != NULL) { if(rfd->dst_mode & dst_mode) modes |= rfd->src_mode; rfd = rfd->next; } return modes; } #endif /* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * some not so optimized remap functions * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ void gen_1to8_all(RemapObject *); void gen_1to8p_all(RemapObject *); void gen_1to16_all(RemapObject *); void gen_1to24_all(RemapObject *); void gen_1to32_all(RemapObject *); void gen_2to8_all(RemapObject *); void gen_2to8p_all(RemapObject *); void gen_2to16_all(RemapObject *); void gen_2to24_all(RemapObject *); void gen_2to32_all(RemapObject *); void gen_c2to8_all(RemapObject *); void gen_c2to8p_all(RemapObject *); void gen_c2to16_all(RemapObject *); void gen_c2to24_all(RemapObject *); void gen_c2to32_all(RemapObject *); void gen_4to8_all(RemapObject *); void gen_4to8p_all(RemapObject *); void gen_4to16_all(RemapObject *); void gen_4to24_all(RemapObject *); void gen_4to32_all(RemapObject *); void gen_8to8_all(RemapObject *); void gen_8to8_1(RemapObject *); void gen_8to8p_all(RemapObject *); void gen_8to8p_1(RemapObject *); void gen_8to16_all(RemapObject *); void gen_8to16_lin(RemapObject *); void gen_8to16_bilin(RemapObject *); void gen_8to24_all(RemapObject *); void gen_8to32_all(RemapObject *); void gen_8to32_1(RemapObject *); void gen_8to32_lin(RemapObject *); void gen_8to32_bilin(RemapObject *); //void gen_15to16_all(RemapObject *); //void gen_15to24_all(RemapObject *); void gen_15to32_all(RemapObject *); void gen_15to32_1(RemapObject *); //void gen_16to16_all(RemapObject *); void gen_16to16_1(RemapObject *); //void gen_16to24_all(RemapObject *); void gen_16to32_all(RemapObject *); void gen_16to32_1(RemapObject *); //void gen_24to24_all(RemapObject *); void gen_24to24_1(RemapObject *); void gen_24to32_all(RemapObject *); void gen_24to32_1(RemapObject *); void gen_32to32_all(RemapObject *); void gen_32to32_1(RemapObject *); static RemapFuncDesc remap_gen_list[] = { 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_PSEUDO_8, gen_1to8p_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_TRUE_8, gen_2to8_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_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_TRUE_8, gen_c2to8_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_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 ), 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_PSEUDO_8, gen_4to8p_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_ALL | RFF_REMAP_LINES, MODE_VGA_X | MODE_PSEUDO_8, MODE_TRUE_8, gen_8to8_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_PSEUDO_8, gen_8to8p_all, NULL ), 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_TRUE_15 | MODE_TRUE_16, gen_8to16_all, 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 | RFF_BILIN_FILT, MODE_PSEUDO_8, MODE_TRUE_15 | MODE_TRUE_16, gen_8to16_bilin, 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_ALL | RFF_REMAP_LINES, MODE_VGA_X | MODE_PSEUDO_8, MODE_TRUE_32, gen_8to32_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 | RFF_LIN_FILT, MODE_PSEUDO_8, MODE_TRUE_32, gen_8to32_lin, 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, MODE_TRUE_15, MODE_TRUE_32, gen_15to32_all, NULL ), REMAP_DESC( RFF_SCALE_1 | RFF_REMAP_LINES, MODE_TRUE_15, MODE_TRUE_32, gen_15to32_1, 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_ALL | RFF_REMAP_LINES, MODE_TRUE_16, MODE_TRUE_32, gen_16to32_all, NULL ), REMAP_DESC( RFF_SCALE_1 | RFF_REMAP_LINES, MODE_TRUE_16, MODE_TRUE_32, gen_16to32_1, NULL ), REMAP_DESC( RFF_SCALE_1 | RFF_REMAP_LINES, MODE_TRUE_24, MODE_TRUE_24, gen_24to24_1, NULL ), REMAP_DESC( RFF_SCALE_ALL | RFF_REMAP_LINES, MODE_TRUE_24, MODE_TRUE_32, gen_24to32_all, 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_TRUE_32, MODE_TRUE_32, gen_32to32_all, NULL ), REMAP_DESC( RFF_SCALE_1 | RFF_REMAP_LINES, MODE_TRUE_32, MODE_TRUE_32, gen_32to32_1, 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 * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* * 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; const unsigned char *src, *src0; unsigned char *dst; unsigned char *lut = (unsigned char *)ro->true_color_lut; unsigned char c0; int i; src0 = ro->src_image + ro->src_start; dst = ro->dst_image + ro->dst_start + 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 --> 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; const unsigned char *src, *src0; unsigned char *dst; src0 = ro->src_image + ro->src_start; dst = ro->dst_image + ro->dst_start + 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 --> 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; const unsigned char *src, *src0; unsigned short *dst; src0 = ro->src_image + ro->src_start; dst = (unsigned short *)(ro->dst_image + ro->dst_start + 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; const unsigned char *src, *src0; unsigned char *dst; unsigned color; src0 = ro->src_image + ro->src_start; dst = (ro->dst_image + ro->dst_start + 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; const unsigned char *src, *src0; unsigned *dst; src0 = ro->src_image + ro->src_start; dst = (unsigned *)(ro->dst_image + ro->dst_start + 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 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; const unsigned char *src, *src0; unsigned char *dst; unsigned char *lut = (unsigned char *)ro->true_color_lut; unsigned char c0, c1; int i; src0 = ro->src_image + ro->src_start; dst = ro->dst_image + ro->dst_start + 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 --> 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; const unsigned char *src, *src0; unsigned char *dst; src0 = ro->src_image + ro->src_start; dst = ro->dst_image + ro->dst_start + 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 --> 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; const unsigned char *src, *src0; unsigned short *dst; src0 = ro->src_image + ro->src_start; dst = (unsigned short *)(ro->dst_image + ro->dst_start + 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; const unsigned char *src, *src0; unsigned char *dst; unsigned color; src0 = ro->src_image + ro->src_start; dst = (ro->dst_image + ro->dst_start + 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; const unsigned char *src, *src0; unsigned *dst; src0 = ro->src_image + ro->src_start; dst = (unsigned *)(ro->dst_image + ro->dst_start + 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 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; const unsigned char *src, *src0; unsigned char *dst; unsigned char *lut = (unsigned char *)ro->true_color_lut; unsigned char c0; int i; src0 = ro->src_image + ro->src_start; dst = ro->dst_image + ro->dst_start + 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 --> 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; const unsigned char *src, *src0; unsigned char *dst; src0 = ro->src_image + ro->src_start; dst = ro->dst_image + ro->dst_start + 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 --> 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; const unsigned char *src, *src0; unsigned short *dst; src0 = ro->src_image + ro->src_start; dst = (unsigned short *)(ro->dst_image + ro->dst_start + 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; const unsigned char *src, *src0; unsigned char *dst; unsigned color; src0 = ro->src_image + ro->src_start; dst = (ro->dst_image + ro->dst_start + 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; const unsigned char *src, *src0; unsigned *dst; src0 = ro->src_image + ro->src_start; dst = (unsigned *)(ro->dst_image + ro->dst_start + 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++); } } } /* * 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; const unsigned char *src, *src0, *src_last; unsigned char *clut = (unsigned char*) ro->true_color_lut, *dst, *src1; unsigned *dst1, *lut; src0 = ro->src_image + ro->src_start; dst = ro->dst_image + ro->dst_start + 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 --> 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; const unsigned char *src, *src0, *src_last; unsigned char *dst, *src1; unsigned *dst1, *lut; src0 = ro->src_image + ro->src_start; dst = ro->dst_image + ro->dst_start + 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 --> 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; const unsigned char *src, *src0, *src_last; unsigned char *src1; unsigned short *dst; unsigned *dst1, *lut; src0 = ro->src_image + ro->src_start; dst = (unsigned short *) (ro->dst_image + ro->dst_start + 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; const unsigned char *src, *src0, *src_last; unsigned char *dst, *src1; unsigned color; src0 = ro->src_image + ro->src_start; dst = (ro->dst_image + ro->dst_start + 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; const unsigned char *src, *src0, *src_last; unsigned char *src1; unsigned *dst; src0 = ro->src_image + ro->src_start; dst = (unsigned *) (ro->dst_image + ro->dst_start + 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++); } } } /* * 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; const unsigned char *src, *src0; unsigned char *dst; unsigned char *lut = (unsigned char *)ro->true_color_lut; src0 = ro->src_image + ro->src_start; dst = ro->dst_image + ro->dst_start + 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 --> 8 bit true color (shared color map) */ void gen_8to8_1(RemapObject *ro) { int i, j, l, k; const unsigned char *src; unsigned char *dst; unsigned char *lut = (unsigned char *)ro->true_color_lut; src = ro->src_image + ro->src_start + ro->src_offset; dst = ro->dst_image + ro->dst_start + 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 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; const unsigned char *src, *src0; unsigned char *dst; src0 = ro->src_image + ro->src_start; dst = ro->dst_image + ro->dst_start + 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 pseudo color (private color map) */ void gen_8to8p_1(RemapObject *ro) { int i; const unsigned char *src; unsigned char *dst; src = ro->src_image + ro->src_start + ro->src_offset; dst = ro->dst_image + ro->dst_start + 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 --> 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; const unsigned char *src, *src0; unsigned short *dst; src0 = ro->src_image + ro->src_start; dst = (unsigned short *) (ro->dst_image + ro->dst_start + 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 --> 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; const unsigned char *src, *src0; unsigned short *dst; src0 = ro->src_image + ro->src_start; dst = (unsigned short *) (ro->dst_image + ro->dst_start + 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_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; const unsigned char *src, *src0; unsigned short *dst; unsigned *lut = ro->true_color_lut; src0 = ro->src_image + ro->src_start; dst = (unsigned short *) (ro->dst_image + ro->dst_start + 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++]; 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 --> 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; const unsigned char *src, *src0; unsigned char *dst; unsigned long long color; src0 = ro->src_image + ro->src_start; dst = (ro->dst_image + ro->dst_start + 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 * 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; const unsigned char *src, *src0; unsigned *dst; src0 = ro->src_image + ro->src_start; dst = (unsigned *) (ro->dst_image + ro->dst_start + 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 */ void gen_8to32_1(RemapObject *ro) { int i, j, l; const unsigned char *src; unsigned *dst; src = ro->src_image + ro->src_start + ro->src_offset; dst = (unsigned *) (ro->dst_image + ro->dst_start + 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_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; const unsigned char *src, *src0; unsigned *dst; src0 = ro->src_image + ro->src_start; dst = (unsigned *) (ro->dst_image + ro->dst_start + 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 --> 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; const unsigned char *src, *src0; unsigned *dst; unsigned *lut = ro->true_color_lut; src0 = ro->src_image + ro->src_start; dst = (unsigned *) (ro->dst_image + ro->dst_start + 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++]; 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"); } } } /* * 15 bit true color --> 32 bit true color * supports arbitrary scaling */ void gen_15to32_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; const unsigned char *src, *src0; unsigned char *dst; const unsigned short *src_2; unsigned *dst_4; src0 = ro->src_image + ro->src_start; dst = ro->dst_image + ro->dst_start + 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++]; src_2 = (const unsigned short *) src; dst_4 = (unsigned *) dst; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { dst_4[d_x++] = bgr_2int(ro->dst_color_space, 5, 5, 5, src_2[s_x]); s_x += *(bre_x++); } } } /* * 15 bit true color --> 32 bit true color * Source format is BGR (see vesa.c:vbe_mode_info() ) */ void gen_15to32_1(RemapObject *ro) { int i, j; const unsigned char *src; unsigned char *dst; const unsigned short *src_2; unsigned *dst_4; src = ro->src_image + ro->src_start + ro->src_offset; dst = ro->dst_image + ro->dst_start + ro->dst_offset; for(i = ro->src_y0; i < ro->src_y1; i++) { src_2 = (const unsigned short *)src; dst_4 = (unsigned *) dst; for(j = 0; j < ro->dst_width; j++) { // get 5-bit color values // (green channel is cut between two byte values) // [0] gggbbbbb // [1] 0rrrrrgg *dst_4++ = bgr_2int(ro->dst_color_space, 5, 5, 5, *src_2++); } src += ro->src_scan_len; dst += ro->dst_scan_len; } } /* * 16 bit true color --> 16 bit true color * 15 bit true color --> 15 bit true color * Source format is BGR (see vesa.c:vbe_mode_info() ) * *** ignores color space description *** */ void gen_16to16_1(RemapObject *ro) { int i; const unsigned char *src; unsigned char *dst; src = ro->src_image + ro->src_start + ro->src_offset; dst = ro->dst_image + ro->dst_start + 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; } } /* * 16 bit true color --> 32 bit true color * supports arbitrary scaling */ void gen_16to32_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; const unsigned char *src, *src0; unsigned char *dst; const unsigned short *src_2; unsigned *dst_4; src0 = ro->src_image + ro->src_start; dst = ro->dst_image + ro->dst_start + 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++]; src_2 = (const unsigned short *) src; dst_4 = (unsigned *) dst; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { dst_4[d_x++] = bgr_2int(ro->dst_color_space, 5, 6, 5, src_2[s_x]); s_x += *(bre_x++); } } } /* * 16 bit true color --> 32 bit true color * Source format is BGR (see vesa.c:vbe_mode_info() ) */ void gen_16to32_1(RemapObject *ro) { int i, j; const unsigned char *src; unsigned char *dst; const unsigned short *src_2; unsigned *dst_4; src = ro->src_image + ro->src_start + ro->src_offset; dst = ro->dst_image + ro->dst_start + ro->dst_offset; for(i = ro->src_y0; i < ro->src_y1; i++) { src_2 = (const unsigned short *)src; dst_4 = (unsigned *) dst; for(j = 0; j < ro->dst_width; j++) { // get 5-bit/6-bit color values // (green channel is cut between two byte values) // [0] gggbbbbb // [1] rrrrrggg *dst_4++ = bgr_2int(ro->dst_color_space, 5, 6, 5, *src_2++); } src += ro->src_scan_len; dst += ro->dst_scan_len; } } /* * 24 bit true color --> 24 bit true color * Source format is BGR (see vesa.c:vbe_mode_info() ) * *** ignores color space description *** */ void gen_24to24_1(RemapObject *ro) { int i; const unsigned char *src; unsigned char *dst; src = ro->src_image + ro->src_start + ro->src_offset; dst = ro->dst_image + ro->dst_start + 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; } } /* * 24 bit true color --> 32 bit true color * supports arbitrary scaling */ void gen_24to32_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; const unsigned char *src, *src0; unsigned char *dst; unsigned *dst_4; src0 = ro->src_image + ro->src_start; dst = ro->dst_image + ro->dst_start + 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++]; dst_4 = (unsigned *) dst; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { RGBColor c = { src[s_x * 3 + 2], src[s_x * 3 + 1], src[s_x * 3] }; dst_4[d_x++] = rgb_color_2int(ro->dst_color_space, 8, 8, 8, c); s_x += *(bre_x++); } } } /* * 24 bit true color --> 32 bit true color * Source format is BGR (see vesa.c:vbe_mode_info() ) */ void gen_24to32_1(RemapObject *ro) { int i, j; const unsigned char *src, *src_1; unsigned char *dst; unsigned *dst_4; src = ro->src_image + ro->src_start + ro->src_offset; dst = ro->dst_image + ro->dst_start + 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++) { RGBColor c = { src_1[2], src_1[1], src_1[0] }; *dst_4++ = rgb_color_2int(ro->dst_color_space, 8, 8, 8, c); src_1 += 3; } src += ro->src_scan_len; dst += ro->dst_scan_len; } } /* * 32 bit true color --> 32 bit true color * supports arbitrary scaling */ void gen_32to32_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; const unsigned char *src, *src0; unsigned char *dst; unsigned *dst_4; src0 = ro->src_image + ro->src_start; dst = ro->dst_image + ro->dst_start + 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++]; dst_4 = (unsigned *) dst; for(s_x = d_x = 0, bre_x = ro->bre_x; d_x < d_x_len; ) { RGBColor c = { src[s_x * 4 + 2], src[s_x * 4 + 1], src[s_x * 4] }; dst_4[d_x++] = rgb_color_2int(ro->dst_color_space, 8, 8, 8, c); s_x += *(bre_x++); } } } /* * 32 bit true color --> 32 bit true color * Source format is BGR (see vesa.c:vbe_mode_info() ) * *** ignores color space description *** */ void gen_32to32_1(RemapObject *ro) { int i; const unsigned char *src; unsigned char *dst; src = ro->src_image + ro->src_start + ro->src_offset; dst = ro->dst_image + ro->dst_start + 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; } } #define RO(p) (*(RemapObject **)p) static RemapObject *re_create_obj(RemapObject *old, int new_mode) { RemapObject *dst = _remap_init(new_mode, old->dst_mode, old->features, old->dst_color_space, old->gamma); if (old->color_lut_size && dst->color_lut_size == old->color_lut_size) memcpy(dst->true_color_lut, old->true_color_lut, dst->color_lut_size * sizeof(*dst->true_color_lut)); else dirty_all_vga_colors(); _remap_done(old); return dst; } static int _remap_palette_update(void *ros, unsigned i, unsigned bits, unsigned r, unsigned g, unsigned b) { RemapObject *ro = RO(ros); return ro->palette_update(ro, i, bits, r, g, b); } static RectArea _remap_remap_rect(void *ros, const struct bitmap_desc src_img, int src_mode, int x0, int y0, int width, int height, struct bitmap_desc dst_img) { RemapObject *ro = RO(ros); if (src_mode != ro->src_mode) RO(ros) = ro = re_create_obj(ro, src_mode); ro->src_image = src_img.img; ro->src_start = 0; ro->dst_image = dst_img.img; ro->src_resize(ro, src_img.width, src_img.height, src_img.scan_len); ro->dst_resize(ro, dst_img.width, dst_img.height, dst_img.scan_len); return ro->remap_rect(ro, x0, y0, width, height); } static RectArea _remap_remap_rect_dst(void *ros, const struct bitmap_desc src_img, int src_mode, int x0, int y0, int width, int height, struct bitmap_desc dst_img) { RemapObject *ro = RO(ros); if (src_mode != ro->src_mode) RO(ros) = ro = re_create_obj(ro, src_mode); ro->src_image = src_img.img; ro->src_start = 0; ro->dst_image = dst_img.img; ro->src_resize(ro, src_img.width, src_img.height, src_img.scan_len); ro->dst_resize(ro, dst_img.width, dst_img.height, dst_img.scan_len); return ro->remap_rect_dst(ro, x0, y0, width, height); } static RectArea _remap_remap_mem(void *ros, const struct bitmap_desc src_img, int src_mode, int src_start, int offset, int len, struct bitmap_desc dst_img) { RemapObject *ro = RO(ros); if (src_mode != ro->src_mode) RO(ros) = ro = re_create_obj(ro, src_mode); ro->src_image = src_img.img; ro->src_start = src_start; ro->dst_image = dst_img.img; ro->src_resize(ro, src_img.width, src_img.height, src_img.scan_len); ro->dst_resize(ro, dst_img.width, dst_img.height, dst_img.scan_len); return ro->remap_mem(ro, offset, len); } static int _remap_get_cap(void *ros) { RemapObject *ro = RO(ros); return ro->state; } static void *_remap_remap_init(int dst_mode, int features, const ColorSpaceDesc *color_space, int gamma) { RemapObject **p, *o; p = malloc(sizeof(*p)); o = malloc(sizeof(*o)); /* create dummy remap. init properly later, when src mode is known */ memset(o, 0, sizeof(*o)); o->dst_mode = dst_mode; o->features = features; o->dst_color_space = color_space; o->palette_update = do_nearly_nothing; o->gamma = gamma; *p = o; return p; } static void _remap_remap_done(void *ros) { RemapObject *ro = RO(ros); _remap_done(ro); free(ros); } static struct remap_calls rmcalls = { _remap_remap_init, _remap_remap_done, _remap_palette_update, _remap_remap_rect, _remap_remap_rect_dst, _remap_remap_mem, _remap_get_cap, "dosemu gfx remapper" }; CONSTRUCTOR(static void initialize(void)) { register_remapper(&rmcalls, REMAP_DOSEMU); } /* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * 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