#define GINT_NEED_VRAM #include #include #include /* dhline() - optimized drawing of a horizontal line using a rectangle mask @x1 @x2 @y Coordinates of endpoints of line (both included) @color Allowed colors: white, black, none, reverse */ static void dhline(int x1, int x2, int y, color_t color) { if((uint)y >= 64) return; if(x1 > x2) swap(x1, x2); uint32_t *lword = vram + (y << 2) + 4; uint32_t m[4]; /* Get the masks for the [x1, x2] range */ masks(x1, x2, m); switch(color) { case color_white: *--lword &= ~m[3]; *--lword &= ~m[2]; *--lword &= ~m[1]; *--lword &= ~m[0]; break; case color_black: *--lword |= m[3]; *--lword |= m[2]; *--lword |= m[1]; *--lword |= m[0]; break; case color_reverse: *--lword ^= m[3]; *--lword ^= m[2]; *--lword ^= m[1]; *--lword ^= m[0]; break; default: return; } } /* dvline() - optimized drawing of a vertical line This variant is less powerful than dhline() because the line-based structure of the vram cannot be used here. @y1 @y2 @x Coordinates of endpoints of line (both included) @color Allowed colors: black, white, none, reverse */ static void dvline(int y1, int y2, int x, color_t operator) { if((uint)x >= 128) return; if(y1 > y2) swap(y1, y2); uint32_t *base = vram + (y1 << 2) + (x >> 5); uint32_t *lword = base + ((y2 - y1 + 1) << 4); uint32_t mask = 1 << (~x & 31); switch(operator) { case color_white: while(lword > base) lword -= 4, *lword &= ~mask; break; case color_black: while(lword > base) lword -= 4, *lword |= mask; break; case color_reverse: while(lword > base) lword -= 4, *lword ^= mask; break; default: break; } } /* dline() - Bresenham line drawing algorithm Remotely adapted from MonochromeLib code by Pierre "PerriotLL" Le Gall. Relies on dhline() and dvline() for optimized situations. @x1 @y1 @x2 @y2 Coordinates of endpoints of line (included) @color Allowed colors: black, white, none, reverse */ void dline(int x1, int y1, int x2, int y2, color_t color) { /* Possible optimizations */ if(y1 == y2) { dhline(x1, x2, y1, color); return; } if(x1 == x2) { dvline(y1, y2, x1, color); return; } /* Brensenham line drawing algorithm */ int i, x = x1, y = y1, cumul; int dx = x2 - x1, dy = y2 - y1; int sx = sgn(dx), sy = sgn(dy); dx = abs(dx), dy = abs(dy); dpixel(x1, y1, color); if(dx >= dy) { /* Start with a non-zero cumul to even the overdue between the two ends of the line (for more regularity) */ cumul = dx >> 1; for(i = 1; i < dx; i++) { x += sx; cumul += dy; if(cumul > dx) cumul -= dx, y += sy; dpixel(x, y, color); } } else { cumul = dy >> 1; for(i = 1; i < dy; i++) { y += sy; cumul += dx; if(cumul > dy) cumul -= dy, x += sx; dpixel(x, y, color); } } dpixel(x2, y2, color); }