diff --git a/src/gray/gline.c b/src/gray/gline.c
new file mode 100644
index 0000000..4714204
--- /dev/null
+++ b/src/gray/gline.c
@@ -0,0 +1,55 @@
+#include <gint/gray.h>
+#include <gint/defs/util.h>
+#include <display/common.h>
+
+/* gline(): Bresenham line drawing algorithm
+   Remotely adapted from MonochromeLib code by Pierre "PerriotLL" Le Gall.
+   Relies on grect() for optimized situations.
+   @x1 @y1 @x2 @y2  Coordinates of endpoints of line (included)
+   @color           Any color */
+void gline(int x1, int y1, int x2, int y2, color_t color)
+{
+	/* Trivial optimizations */
+	if(x1 == x2 || y1 == y2)
+	{
+		grect(x1, y1, x2, y2, 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);
+
+	gpixel(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;
+			gpixel(x, y, color);
+		}
+	}
+	else
+	{
+		cumul = dy >> 1;
+		for(i = 1; i < dy; i++)
+		{
+			y += sy;
+			cumul += dx;
+			if(cumul > dy) cumul -= dy, x += sx;
+			gpixel(x, y, color);
+		}
+	}
+
+	gpixel(x2, y2, color);
+}
diff --git a/src/gray/gpixel.c b/src/gray/gpixel.c
new file mode 100644
index 0000000..87af2a4
--- /dev/null
+++ b/src/gray/gpixel.c
@@ -0,0 +1,59 @@
+#include <gint/gray.h>
+#include <gint/defs/types.h>
+
+/* gpixel(): Change a pixel's color */
+void gpixel(int x, int y, color_t color)
+{
+	if((uint)x >= 128 || (uint)y >= 64) return;
+
+	uint32_t *light, *dark;
+	gvram(&light, &dark);
+
+	int offset = (y << 2) + (x >> 5);
+	uint32_t mask = 1 << (~x & 31), tmp;
+
+	switch(color)
+	{
+	case C_WHITE:
+		light[offset] &= ~mask;
+		dark [offset] &= ~mask;
+		break;
+
+	case C_LIGHT:
+		light[offset] |= mask;
+		dark [offset] &= ~mask;
+		break;
+
+	case C_DARK:
+		light[offset] &= ~mask;
+		dark [offset] |= mask;
+		break;
+
+	case C_BLACK:
+		light[offset] |= mask;
+		dark [offset] |= mask;
+		break;
+
+	case C_NONE:
+		break;
+
+	case C_INVERT:
+		light[offset] ^= mask;
+		dark [offset] ^= mask;
+		break;
+
+	case C_LIGHTEN:
+		tmp = dark[offset];
+
+		dark[offset] &= light[offset] | ~mask;
+		light[offset] = (light[offset] ^ mask) & (tmp | ~mask);
+		break;
+
+	case C_DARKEN:
+		tmp = dark[offset];
+
+		dark[offset] |= light[offset] & mask;
+		light[offset] = (light[offset] ^ mask) | (tmp & mask);
+		break;
+	}
+}
diff --git a/src/render/dline.c b/src/render/dline.c
index 2a2c016..c9f9134 100644
--- a/src/render/dline.c
+++ b/src/render/dline.c
@@ -6,7 +6,7 @@
    Remotely adapted from MonochromeLib code by Pierre "PerriotLL" Le Gall.
    Relies on platform-dependent dhline() and dvline() for optimized situations.
    @x1 @y1 @x2 @y2  Coordinates of endpoints of line (included)
-   @color           Any R5G6B5 color */
+   @color           Any color accepted by dpixel() on the platform */
 void dline(int x1, int y1, int x2, int y2, color_t color)
 {
 	/* Possible optimizations */