/* ----- render utilities ----- */ /*------------------------------------------------- * render_resample_argb_bitmap_hq - perform a high * quality resampling of a texture * -------------------------------------------------*/ public static void render_resample_argb_bitmap_hq(bitmap_argb32 dest, bitmap_argb32 source, render_color color, bool force = false) { if (dest.width() == 0 || dest.height() == 0) { return; } /* adjust the source base */ PointerU32 sbase = source.pix(0); //const u32 *sbase = &source.pix(0); /* determine the steppings */ u32 swidth = (u32)source.width(); u32 sheight = (u32)source.height(); u32 dwidth = (u32)dest.width(); u32 dheight = (u32)dest.height(); u32 dx = (swidth << 12) / dwidth; u32 dy = (sheight << 12) / dheight; /* if the source is higher res than the target, use full averaging */ if (dx > 0x1000 || dy > 0x1000 || force) { resample_argb_bitmap_average(dest.pix(0), (u32)dest.rowpixels(), dwidth, dheight, sbase, (u32)source.rowpixels(), swidth, sheight, color, dx, dy); } else { resample_argb_bitmap_bilinear(dest.pix(0), (u32)dest.rowpixels(), dwidth, dheight, sbase, (u32)source.rowpixels(), swidth, sheight, color, dx, dy); } }
public static void sha1_process(std.array <uint32_t, u64_const_5> st, PointerU32 data) //inline void sha1_process(std::array<uint32_t, 5> &st, uint32_t *data) { std.array <uint32_t, u64_const_5> d = st; unsigned i = 0U; while (i < 16U) { sha1_r0(data, d, i++); } while (i < 20U) { sha1_r1(data, d, i++); } while (i < 40U) { sha1_r2(data, d, i++); } while (i < 60U) { sha1_r3(data, d, i++); } while (i < 80U) { sha1_r4(data, d, i++); } for (i = 0U; i < 5U; i++) { st[i] += d[i]; } }
static uint32_t sha1_b(PointerU32 data, unsigned i) { uint32_t r = data[(i + 13) & 15U]; r ^= data[(i + 8) & 15U]; r ^= data[(i + 2) & 15U]; r ^= data[i & 15U]; r = sha1_rol(r, 1); data[i & 15U] = r; return(r); }
//------------------------------------------------- // render_triangle - render a triangle that // is used for up/down arrows and left/right // indicators //------------------------------------------------- static void render_triangle(bitmap_argb32 dest, bitmap_argb32 source, rectangle sbounds, object param) //void *param) { int halfwidth = dest.width() / 2; int height = dest.height(); // start with all-transparent dest.fill(new rgb_t(0x00, 0x00, 0x00, 0x00)); // render from the tip to the bottom for (int y = 0; y < height; y++) { int linewidth = (y * (halfwidth - 1) + (height / 2)) * 255 * 2 / height; PointerU32 target = dest.pix(y, halfwidth); //uint32_t *const target = &dest.pix(y, halfwidth); // don't antialias if height < 12 if (dest.height() < 12) { int pixels = (linewidth + 254) / 255; if (pixels % 2 == 0) { pixels++; } linewidth = pixels * 255; } // loop while we still have data to generate for (int x = 0; linewidth > 0; x++) { int dalpha; if (x == 0) { // first column we only consume one pixel dalpha = std.min(0xff, linewidth); target[x] = new rgb_t((uint8_t)dalpha, 0xff, 0xff, 0xff); //target[x] = rgb_t(dalpha, 0xff, 0xff, 0xff); } else { // remaining columns consume two pixels, one on each side dalpha = std.min(0x1fe, linewidth); target[x] = target[-x] = new rgb_t((uint8_t)(dalpha / 2), 0xff, 0xff, 0xff); //target[x] = target[-x] = rgb_t(dalpha / 2, 0xff, 0xff, 0xff); } // account for the weight we consumed linewidth -= dalpha; } } }
public static void load_translation(random_read file) { MemoryU8 translation_data_buffer; //std::unique_ptr<std::uint32_t []> translation_data; PointerU32 translation_data; //std::unique_ptr<std::uint32_t []> translation_data; std.unordered_map <string, std.pair <string, uint32_t> > translation_map = new std.unordered_map <string, std.pair <string, uint32_t> >(); //std::unordered_map<std::string_view, std::pair<char const *, std::uint32_t> > translation_map; uint64_t size = 0; if (file.length(out size) || (20 > size)) { osd_printf_error("Error reading translation file: {0}-byte file is too small to contain translation data\n", size); return; } translation_data_buffer = new MemoryU8((int)size + 3, true); //translation_data.reset(new (std::nothrow) std::uint32_t [(size + 3) / 4]); translation_data = new PointerU32(f_translation_data); if (translation_data == null) { osd_printf_error("Failed to allocate {0} bytes to load translation data file\n", size); return; } size_t read; file.read(translation_data, size, out read); if (read != size) { osd_printf_error("Error reading translation file: requested {0} bytes but got {1} bytes\n", size, read); translation_data = null; //translation_data.reset(); return; } if ((translation_data[0] != MO_MAGIC) && (translation_data[0] != MO_MAGIC_REVERSED)) { osd_printf_error("Error reading translation file: unrecognized magic number {0}\n", translation_data[0]); //0x%08X translation_data = null; //translation_data.reset(); return; } var fetch_word = new Func <size_t, uint32_t>( (size_t offset) => //[reversed = translation_data[0] == MO_MAGIC_REVERSED, words = translation_data.get()] (size_t offset) { var reversed = translation_data[0] == MO_MAGIC_REVERSED; var words = translation_data; return(reversed ? swapendian_int32(words[offset]) : words[offset]); }); // FIXME: check major/minor version number if ((fetch_word(3) % 4) != 0 || (fetch_word(4) % 4) != 0) { osd_printf_error("Error reading translation file: table offsets {0} and {1} are not word-aligned\n", fetch_word(3), fetch_word(4)); translation_data = null; //translation_data.reset(); return; } uint32_t number_of_strings = fetch_word(2); uint32_t original_table_offset = fetch_word(3) >> 2; uint32_t translation_table_offset = fetch_word(4) >> 2; if ((4 * (original_table_offset + ((uint64_t)number_of_strings * 2))) > size) { osd_printf_error("Error reading translation file: {0}-entry original string table at offset {1} extends past end of {2}-byte file\n", number_of_strings, fetch_word(3), size); translation_data = null; //translation_data.reset(); return; } if ((4 * (translation_table_offset + ((uint64_t)number_of_strings * 2))) > size) { osd_printf_error("Error reading translation file: {0}-entry translated string table at offset {1} extends past end of {2}-byte file\n", number_of_strings, fetch_word(4), size); translation_data = null; //translation_data.reset(); return; } osd_printf_verbose("Reading translation file: {0} strings, original table at word offset {1}, translated table at word offset {2}\n", number_of_strings, original_table_offset, translation_table_offset); PointerU8 data = new PointerU8(translation_data); //char const *const data = reinterpret_cast<char const *>(translation_data.get()); for (uint32_t i = 1; number_of_strings > i; ++i) { uint32_t original_length = fetch_word(original_table_offset + (2 * i)); uint32_t original_offset = fetch_word(original_table_offset + (2 * i) + 1); if ((original_length + original_offset) >= size) { osd_printf_error("Error reading translation file: {0}-byte original string {1} at offset {2} extends past end of {3}-byte file\n", original_length, i, original_offset, size); continue; } if (data[original_length + original_offset] != 0) { osd_printf_error("Error reading translation file: {0}-byte original string {1} at offset {2} is not correctly NUL-terminated\n", original_length, i, original_offset); continue; } uint32_t translation_length = fetch_word(translation_table_offset + (2 * i)); uint32_t translation_offset = fetch_word(translation_table_offset + (2 * i) + 1); if ((translation_length + translation_offset) >= size) { osd_printf_error("Error reading translation file: {0}-byte translated string {1} at offset {2} extends past end of {3}-byte file\n", translation_length, i, translation_offset, size); continue; } if (data[translation_length + translation_offset] != 0) { osd_printf_error("Error reading translation file: {0}-byte translated string {1} at offset {2} is not correctly NUL-terminated\n", translation_length, i, translation_offset); continue; } string original = data.ToString((int)original_offset, int.MaxValue); //std::string_view const original(&data[original_offset], original_length); string translation = data.ToString((int)translation_offset, int.MaxValue); //char const *const translation(&data[translation_offset]); var ins = translation_map.emplace(original, std.make_pair(translation, translation_length)); //auto const ins = translation_map.emplace(original, std::make_pair(translation, translation_length)); if (!ins) { osd_printf_warning( "Loading translation file: translation {0} '{1}'='{2}' conflicts with previous translation '{3}'='{4}'\n", i, original, translation, null, //ins.first->first, null); //ins.first->second.first); } } osd_printf_verbose("Loaded {0} translated string from file\n", translation_map.size()); f_translation_data = translation_data; f_translation_map = translation_map; }
// updates //void animate(u16 auto_time); //void draw(render_container &container, u8 fade); // private helpers //------------------------------------------------- // create_bitmap - create the rendering // structures for the given player //------------------------------------------------- void create_bitmap() { rgb_t color = m_player < (int)std.size(crosshair_colors) ? crosshair_colors[m_player] : rgb_t.white(); // if we have a bitmap and texture for this player, kill it if (m_bitmap == null) { m_bitmap = new bitmap_argb32(); m_texture = m_machine.render().texture_alloc(render_texture.hq_scale); } else { m_bitmap.reset(); } emu_file crossfile = new emu_file(m_machine.options().crosshair_path(), OPEN_FLAG_READ); if (!m_name.empty()) { // look for user specified file if (!crossfile.open(m_name + ".png")) { render_load_png(out m_bitmap, crossfile.core_file_get()); crossfile.close(); } } else { // look for default cross?.png in crsshair/game dir string filename = util.string_format("cross{0}.png", m_player + 1); if (!crossfile.open(m_machine.system().name + (PATH_SEPARATOR + filename))) { render_load_png(out m_bitmap, crossfile.core_file_get()); crossfile.close(); } // look for default cross?.png in crsshair dir if (!m_bitmap.valid() && !crossfile.open(filename)) { render_load_png(out m_bitmap, crossfile.core_file_get()); crossfile.close(); } } /* if that didn't work, use the built-in one */ if (!m_bitmap.valid()) { /* allocate a blank bitmap to start with */ m_bitmap.allocate(CROSSHAIR_RAW_SIZE, CROSSHAIR_RAW_SIZE); m_bitmap.fill(new rgb_t(0x00, 0xff, 0xff, 0xff)); /* extract the raw source data to it */ for (int y = 0; y < CROSSHAIR_RAW_SIZE / 2; y++) { /* assume it is mirrored vertically */ PointerU32 dest0 = m_bitmap.pix(y); //u32 *dest0 = &m_bitmap->pix(y); PointerU32 dest1 = m_bitmap.pix(CROSSHAIR_RAW_SIZE - 1 - y); //u32 *dest1 = &m_bitmap->pix(CROSSHAIR_RAW_SIZE - 1 - y); /* extract to two rows simultaneously */ for (int x = 0; x < CROSSHAIR_RAW_SIZE; x++) { if (((crosshair_raw_top[y * CROSSHAIR_RAW_ROWBYTES + x / 8] << (x % 8)) & 0x80) != 0) { dest0[x] = dest1[x] = new rgb_t(0xff, 0x00, 0x00, 0x00) | color; } } } } /* reference the new bitmap */ m_texture.set_bitmap(m_bitmap, m_bitmap.cliprect(), texture_format.TEXFORMAT_ARGB32); }
/*------------------------------------------------- * resample_argb_bitmap_bilinear - perform texture * sampling via a bilinear filter * -------------------------------------------------*/ static void resample_argb_bitmap_bilinear(PointerU32 dest, u32 drowpixels, u32 dwidth, u32 dheight, PointerU32 source, u32 srowpixels, u32 swidth, u32 sheight, render_color color, u32 dx, u32 dy) //static void resample_argb_bitmap_bilinear(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy) { u32 maxx = swidth << 12; u32 maxy = sheight << 12; u32 r; u32 g; u32 b; u32 a; u32 x; u32 y; /* precompute premultiplied R/G/B/A factors */ r = (u32)(color.r * color.a * 256.0f); g = (u32)(color.g * color.a * 256.0f); b = (u32)(color.b * color.a * 256.0f); a = (u32)(color.a * 256.0f); /* loop over the target vertically */ for (y = 0; y < dheight; y++) { u32 starty = y * dy; /* loop over the target horizontally */ for (x = 0; x < dwidth; x++) { u32 startx = x * dx; rgb_t pix0; rgb_t pix1; rgb_t pix2; rgb_t pix3; u32 sumr; u32 sumg; u32 sumb; u32 suma; u32 nextx; u32 nexty; u32 curx; u32 cury; u32 factor; /* adjust start to the center; note that this math will tend to produce */ /* negative results on the first pixel, which is why we clamp below */ curx = startx + dx / 2 - 0x800; cury = starty + dy / 2 - 0x800; /* compute the neighboring pixel */ nextx = curx + 0x1000; nexty = cury + 0x1000; /* fetch the four relevant pixels */ pix0 = pix1 = pix2 = pix3 = new rgb_t(0); if ((int)cury >= 0 && cury < maxy && (int)curx >= 0 && curx < maxx) { pix0 = new rgb_t(source[(cury >> 12) * srowpixels + (curx >> 12)]); //pix0 = source[(cury >> 12) * srowpixels + (curx >> 12)]; } if ((int)cury >= 0 && cury < maxy && (int)nextx >= 0 && nextx < maxx) { pix1 = new rgb_t(source[(cury >> 12) * srowpixels + (nextx >> 12)]); //pix1 = source[(cury >> 12) * srowpixels + (nextx >> 12)]; } if ((int)nexty >= 0 && nexty < maxy && (int)curx >= 0 && curx < maxx) { pix2 = new rgb_t(source[(nexty >> 12) * srowpixels + (curx >> 12)]); //pix2 = source[(nexty >> 12) * srowpixels + (curx >> 12)]; } if ((int)nexty >= 0 && nexty < maxy && (int)nextx >= 0 && nextx < maxx) { pix3 = new rgb_t(source[(nexty >> 12) * srowpixels + (nextx >> 12)]); //pix3 = source[(nexty >> 12) * srowpixels + (nextx >> 12)]; } /* compute the x/y scaling factors */ curx &= 0xfff; cury &= 0xfff; /* contributions from pixel 0 (top,left) */ factor = (0x1000 - curx) * (0x1000 - cury); sumr = factor * pix0.r(); sumg = factor * pix0.g(); sumb = factor * pix0.b(); suma = factor * pix0.a(); /* contributions from pixel 1 (top,right) */ factor = curx * (0x1000 - cury); sumr += factor * pix1.r(); sumg += factor * pix1.g(); sumb += factor * pix1.b(); suma += factor * pix1.a(); /* contributions from pixel 2 (bottom,left) */ factor = (0x1000 - curx) * cury; sumr += factor * pix2.r(); sumg += factor * pix2.g(); sumb += factor * pix2.b(); suma += factor * pix2.a(); /* contributions from pixel 3 (bottom,right) */ factor = curx * cury; sumr += factor * pix3.r(); sumg += factor * pix3.g(); sumb += factor * pix3.b(); suma += factor * pix3.a(); /* apply scaling */ suma = (suma >> 24) * a / 256; sumr = (sumr >> 24) * r / 256; sumg = (sumg >> 24) * g / 256; sumb = (sumb >> 24) * b / 256; /* if we're translucent, add in the destination pixel contribution */ if (a < 256) { rgb_t dpix = new rgb_t(dest[y * drowpixels + x]); //rgb_t dpix = dest[y * drowpixels + x]; suma += dpix.a() * (256 - a); sumr += dpix.r() * (256 - a); sumg += dpix.g() * (256 - a); sumb += dpix.b() * (256 - a); } /* store the target pixel, dividing the RGBA values by the overall scale factor */ dest[y * drowpixels + x] = new rgb_t((u8)suma, (u8)sumr, (u8)sumg, (u8)sumb); //dest[y * drowpixels + x] = rgb_t(suma, sumr, sumg, sumb); } } }
/*------------------------------------------------- * resample_argb_bitmap_average - resample a texture * by performing a true weighted average over * all contributing pixels * -------------------------------------------------*/ static void resample_argb_bitmap_average(PointerU32 dest, u32 drowpixels, u32 dwidth, u32 dheight, PointerU32 source, u32 srowpixels, u32 swidth, u32 sheight, render_color color, u32 dx, u32 dy) //static void resample_argb_bitmap_average(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy) { u64 sumscale = (u64)dx * (u64)dy; u32 r; u32 g; u32 b; u32 a; u32 x; u32 y; /* precompute premultiplied R/G/B/A factors */ r = (u32)(color.r * color.a * 256.0f); g = (u32)(color.g * color.a * 256.0f); b = (u32)(color.b * color.a * 256.0f); a = (u32)(color.a * 256.0f); /* loop over the target vertically */ for (y = 0; y < dheight; y++) { u32 starty = y * dy; /* loop over the target horizontally */ for (x = 0; x < dwidth; x++) { u64 sumr = 0; u64 sumg = 0; u64 sumb = 0; u64 suma = 0; u32 startx = x * dx; u32 xchunk; u32 ychunk; u32 curx; u32 cury; u32 yremaining = dy; /* accumulate all source pixels that contribute to this pixel */ for (cury = starty; yremaining != 0; cury += ychunk) { u32 xremaining = dx; /* determine the Y contribution, clamping to the amount remaining */ ychunk = 0x1000 - (cury & 0xfff); if (ychunk > yremaining) { ychunk = yremaining; } yremaining -= ychunk; /* loop over all source pixels in the X direction */ for (curx = startx; xremaining != 0; curx += xchunk) { u32 factor; /* determine the X contribution, clamping to the amount remaining */ xchunk = 0x1000 - (curx & 0xfff); if (xchunk > xremaining) { xchunk = xremaining; } xremaining -= xchunk; /* total contribution = x * y */ factor = xchunk * ychunk; /* fetch the source pixel */ rgb_t pix = new rgb_t(source[(cury >> 12) * srowpixels + (curx >> 12)]); //rgb_t pix = source[(cury >> 12) * srowpixels + (curx >> 12)]; /* accumulate the RGBA values */ sumr += factor * pix.r(); sumg += factor * pix.g(); sumb += factor * pix.b(); suma += factor * pix.a(); } } /* apply scaling */ suma = (suma / sumscale) * a / 256; sumr = (sumr / sumscale) * r / 256; sumg = (sumg / sumscale) * g / 256; sumb = (sumb / sumscale) * b / 256; /* if we're translucent, add in the destination pixel contribution */ if (a < 256) { rgb_t dpix = new rgb_t(dest[y * drowpixels + x]); //rgb_t dpix = dest[y * drowpixels + x]; suma += dpix.a() * (256 - a); sumr += dpix.r() * (256 - a); sumg += dpix.g() * (256 - a); sumb += dpix.b() * (256 - a); } /* store the target pixel, dividing the RGBA values by the overall scale factor */ dest[y * drowpixels + x] = new rgb_t((u8)suma, (u8)sumr, (u8)sumg, (u8)sumb); //dest[y * drowpixels + x] = rgb_t(suma, sumr, sumg, sumb); } } }
static void sha1_r4(PointerU32 data, std.array <uint32_t, u64_const_5> d, unsigned i) //inline void sha1_r4(uint32_t *data, std::array<uint32_t, 5> &d, unsigned i) { d[i % 5] = d[i % 5] + (d[(i + 3) % 5] ^ d[(i + 2) % 5] ^ d[(i + 1) % 5]) + sha1_b(data, i) + 0xca62c1d6U + sha1_rol(d[(i + 4) % 5], 5); d[(i + 3) % 5] = sha1_rol(d[(i + 3) % 5], 30); }
static void sha1_r3(PointerU32 data, std.array <uint32_t, u64_const_5> d, unsigned i) //inline void sha1_r3(uint32_t *data, std::array<uint32_t, 5> &d, unsigned i) { d[i % 5] = d[i % 5] + (((d[(i + 3) % 5] | d[(i + 2) % 5]) & d[(i + 1) % 5]) | (d[(i + 3) % 5] & d[(i + 2) % 5])) + sha1_b(data, i) + 0x8f1bbcdcU + sha1_rol(d[(i + 4) % 5], 5); d[(i + 3) % 5] = sha1_rol(d[(i + 3) % 5], 30); }
static void sha1_r0(PointerU32 data, std.array <uint32_t, u64_const_5> d, unsigned i) //inline void sha1_r0(const uint32_t *data, std::array<uint32_t, 5> &d, unsigned i) { d[i % 5] = d[i % 5] + ((d[(i + 3) % 5] & (d[(i + 2) % 5] ^ d[(i + 1) % 5])) ^ d[(i + 1) % 5]) + data[i] + 0x5a827999U + sha1_rol(d[(i + 4) % 5], 5); d[(i + 3) % 5] = sha1_rol(d[(i + 3) % 5], 30); }
//------------------------------------------------- // char_expand - expand the raw data for a // character into a bitmap //------------------------------------------------- void char_expand(char32_t chnum, glyph gl) { LOG("render_font::char_expand: expanding character {0}\n", chnum); rgb_t fgcol = (gl.color != 0 ? gl.color : new rgb_t(0xff, 0xff, 0xff, 0xff)); rgb_t bgcol = new rgb_t(0x00, 0xff, 0xff, 0xff); bool is_cmd = ((chnum >= COMMAND_UNICODE) && (chnum < COMMAND_UNICODE + MAX_GLYPH_FONT)); if (is_cmd) { throw new emu_unimplemented(); #if false // punt if nothing there if (gl.bmwidth == 0 || gl.bmheight == 0 || gl.rawdata == null) { return; } // allocate a new bitmap of the size we need gl.bitmap.allocate(gl.bmwidth, m_height_cmd); gl.bitmap.fill(0); // extract the data const char *ptr = gl.rawdata; byte accum = 0; byte accumbit = 7; for (int y = 0; y < gl.bmheight; y++) { int desty = y + m_height_cmd + m_yoffs_cmd - gl.yoffs - gl.bmheight; u32 *dest = (desty >= 0 && desty < m_height_cmd) ? &gl.bitmap.pix(desty, 0) : nullptr; { for (int x = 0; x < gl.bmwidth; x++) { if (accumbit == 7) { accum = *ptr++; } if (dest != null) { *dest++ = (accum & (1 << accumbit)) ? color : rgb_t(0x00, 0xff, 0xff, 0xff); } accumbit = (accumbit - 1) & 7; } } } #endif } else if (m_format == format.OSD) { throw new emu_unimplemented(); #if false // if we're an OSD font, query the info #endif } else if (gl.bmwidth == 0 || gl.bmheight == 0 || gl.rawdata == null) { // abort if nothing there LOG("render_font::char_expand: empty bitmap bounds or no raw data\n"); return; } else { // other formats need to parse their data LOG("render_font::char_expand: building bitmap from raw data\n"); // allocate a new bitmap of the size we need gl.bitmap.allocate(gl.bmwidth, m_height); gl.bitmap.fill(0); // extract the data Pointer <u8> ptr = new Pointer <u8>(gl.rawdata); //const char *ptr = gl.rawdata; u8 accum = 0; u8 accumbit = 7; for (int y = 0; y < gl.bmheight; y++) { int desty = y + m_height + m_yoffs - gl.yoffs - gl.bmheight; PointerU32 dest = ((0 <= desty) && (m_height > desty)) ? gl.bitmap.pix(desty) : null; //u32 *dest(((0 <= desty) && (m_height > desty)) ? &gl.bitmap.pix(desty) : nullptr); if (m_format == format.TEXT) { if (dest != null) { for (int x = 0; gl.bmwidth > x;) { // scan for the next hex digit int bits = -1; while ('\r' != ptr[0] && '\n' != ptr[0] && 0 > bits) // while (('\r' != *ptr) && ('\n' != *ptr) && (0 > bits)) { if (ptr[0] >= '0' && ptr[0] <= '9') { bits = ptr[0] - '0'; //bits = *ptr++ - '0'; ptr++; } else if (ptr[0] >= 'A' && ptr[0] <= 'F') { bits = ptr[0] - 'A' + 10; ptr++; } else if (ptr[0] >= 'a' && ptr[0] <= 'f') { bits = ptr[0] - 'a' + 10; ptr++; } else { ptr++; } } // expand the four bits dest[0] = (bits & 8) != 0 ? fgcol : bgcol; dest++; //*dest++ = (bits & 8) ? fgcol : bgcol; if (gl.bmwidth > ++x) { dest[0] = (bits & 4) != 0 ? fgcol : bgcol; dest++; } //*dest++ = (bits & 4) ? fgcol : bgcol; if (gl.bmwidth > ++x) { dest[0] = (bits & 2) != 0 ? fgcol : bgcol; dest++; } //*dest++ = (bits & 2) ? fgcol : bgcol; if (gl.bmwidth > ++x) { dest[0] = (bits & 1) != 0 ? fgcol : bgcol; dest++; } //*dest++ = (bits & 1) ? fgcol : bgcol; x++; } // advance to the next line ptr = next_line(ptr); } } else if (m_format == format.CACHED) { for (int x = 0; x < gl.bmwidth; x++) { if (accumbit == 7) { accum = ptr[0]; ptr++; } if (dest != null) { dest[0] = (accum & (1 << accumbit)) != 0 ? fgcol : bgcol; dest++; } //*dest++ = (accum & (1 << accumbit)) ? fgcol : bgcol; accumbit = (u8)((accumbit - 1) & 7); } } } } // wrap a texture around the bitmap gl.texture = m_manager.texture_alloc(render_texture.hq_scale); gl.texture.set_bitmap(gl.bitmap, gl.bitmap.cliprect(), texture_format.TEXFORMAT_ARGB32); }