/* ************************************************************************** */ /* _____ _ */ /* ML_bmp.c |_ _|__ _ _| |__ ___ _ _ */ /* | Project : libmonochrome | |/ _ \| | | | '_ \ / _ \ | | | */ /* | | (_) | |_| | | | | __/ |_| | */ /* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ /* Last updated: 2016/05/29 01:55:54 |___/ */ /* */ /* ************************************************************************** */ #include static inline void ML_bmp_line(unsigned char *vram, const unsigned char *b, int width, int offset, ML_Mode mode); static inline void ML_bmp_byte(unsigned char *v, int b, int offset, int width, ML_Mode mode); void ML_bmp(const void *bmp, int x, int y, int width, int height, ML_Mode mode) { /* FIXME: no support for non-clipping blit. */ /* Oh, and yeah : most of this code is adapted from Caphics. Clipping is, of course, on by default, and this function is not optimized for when its disabled. */ if (x < width + 1 || x >= 128 || y < height + 1 || y >= 64) return ; // check clipping for retrocompatibility ? int ls = (width >> 3) + ((width & 7) != 0); // line size const unsigned char *b = (const unsigned char*)bmp; // pass first lines if (y < 0) { b += -y * ls; height += y; y = 0; } if (height > 64 - y) height = 64 - y; // pass first pixels if x < 0 int offset = 0; if (x < 0) { b += -x >> 3; width += x & 8; x = 0; } if (width > 128 - x) width = 128 - x; // go to first interesting byte of vram char *vram = ML_vram_xy(x, y); // then draw while (height--) { ML_bmp_line((unsigned char*)vram, b, width, offset, mode); vram += 8, bmp += ls; } } static inline void ML_bmp_line(unsigned char *vram, const unsigned char *b, int width, int offset, ML_Mode mode) { while (1) { ML_bmp_byte(vram, *b, offset, width, mode); if (width < 8) break ; vram++, b++; width -= 8; } } static inline void ML_bmp_byte(unsigned char *v, int b, int offset, int width, ML_Mode mode) { if (width < 8) b &= 255 << (8 - width); switch (mode) { case ML_MAND: *v &= ~(b >> offset); if (width > 8 - offset) *(++v) &= ~(b << (8 - offset)); break; case ML_MOR: *v |= b >> offset; if (width > 8 - offset) *(++v) |= b << (8 - offset); break; case ML_MXOR: *v ^= b >> offset; if (width > 8 - offset) *(++v) ^= b << (8 - offset); break; } }