Skip to content

Instantly share code, notes, and snippets.

@ao-kenji
Created August 27, 2014 12:56
Show Gist options
  • Save ao-kenji/d745589e227aff0732d3 to your computer and use it in GitHub Desktop.
Save ao-kenji/d745589e227aff0732d3 to your computer and use it in GitHub Desktop.
yaft ( http://uobikiemukot.github.io/yaft/ ) on OpenBSD/luna88k, take 5. Add getting back to original screen mode when exit, etc.
diff --git a/draw.h b/draw.h
index 541688d..afa3ef0 100644
--- a/draw.h
+++ b/draw.h
@@ -1,6 +1,49 @@
/* See LICENSE for licence details. */
+
+/*
+ * LUNA framebuffer support is based on:
+ * OpenBSD:src/sys/arch/luna88k/dev/omrasops.c
+ */
+/* $OpenBSD: omrasops.c,v 1.11 2014/01/02 15:30:34 aoyama Exp $ */
+/* $NetBSD: omrasops.c,v 1.1 2000/01/05 08:48:56 nisimura Exp $ */
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Tohru Nishimura.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define ALL1BITS (~0U)
+#define BLITWIDTH (32)
+#define ALIGNMASK (0x1f)
+#define BYTESDONE (4)
+#define PLANESIZE 0x40000
+
static inline void draw_sixel(struct framebuffer *fb, int line, int col, uint8_t *pixmap)
{
+#if 0
int h, w, src_offset, dst_offset;
uint32_t pixel, color = 0;
@@ -14,10 +57,55 @@ static inline void draw_sixel(struct framebuffer *fb, int line, int col, uint8_t
memcpy(fb->buf + dst_offset, &pixel, fb->bytes_per_pixel);
}
}
+#else
+ int h, w, src_offset;
+ uint32_t pixel, color = 0;
+ int x, y, i;
+ uint32_t *p0, *p;
+
+ for (h = 0; h < CELL_HEIGHT; h++) {
+ for (w = 0; w < CELL_WIDTH; w++) {
+ src_offset = BYTES_PER_PIXEL * (h * CELL_WIDTH + w);
+ memcpy(&color, pixmap + src_offset, BYTES_PER_PIXEL);
+
+ pixel = color2pixel(&fb->vinfo, color);
+
+ x = CELL_WIDTH * col + w;
+ y = CELL_HEIGHT * line + h;
+ p0 = (uint32_t *)((uint8_t *)fb->buf
+ + y * fb->line_length + ((x / 32) * 4));
+ x &= ALIGNMASK; /* x % 32 */
+
+ for (i = 0; i < DEPTH; i++) {
+ p = (uint32_t *)((uint8_t *)p0 + PLANESIZE * i);
+ if (pixel & (0x01 << i))
+ /* set */
+ *p |= (0x00000001 << (31 - x));
+ else
+ /* reset */
+ *p &= ~(0x00000001 << (31 - x));
+ }
+ }
+ }
+#endif
+}
+
+static inline void draw_glyph(uint32_t *p0, int plane, uint32_t glyph,
+ int fg, int bg, uint32_t mask)
+{
+ uint32_t glyphbg, fgpat, bgpat;
+ uint32_t *p;
+
+ glyphbg = glyph ^ ALL1BITS;
+ fgpat = (fg & (0x01 << plane)) ? glyph : 0;
+ bgpat = (bg & (0x01 << plane)) ? glyphbg : 0;
+ p = (uint32_t *)((uint8_t *)p0 + PLANESIZE * plane);
+ *p = (*p & ~mask) | ((fgpat | bgpat) & mask);
}
static inline void draw_line(struct framebuffer *fb, struct terminal *term, int line)
{
+#if 0
int pos, size, bdf_padding, glyph_width, margin_right;
int col, w, h;
uint32_t pixel;
@@ -81,7 +169,118 @@ static inline void draw_line(struct framebuffer *fb, struct terminal *term, int
pos = (line * CELL_HEIGHT) * fb->line_length;
size = CELL_HEIGHT * fb->line_length;
memcpy(fb->fp + pos, fb->buf + pos, size);
+#else
+ int pos, size, col, glyph_width, bdf_shift;
+ struct color_pair_t color_pair;
+ struct cell_t *cellp;
+
+ int x, y, width, height, align, fg, bg, plane;
+ u_int32_t lmask, rmask, glyph;
+ u_int8_t *p;
+
+ for (col = term->cols - 1; col >= 0; col--) {
+
+ /* target cell */
+ cellp = &term->cells[line][col];
+
+ /* draw sixel pixmap */
+ if (cellp->has_pixmap) {
+ draw_sixel(fb, line, col, cellp->pixmap);
+ continue;
+ }
+
+ /* copy current color_pair (maybe changed) */
+ color_pair = cellp->color_pair;
+
+ /* check wide character or not */
+ if (cellp->width == NEXT_TO_WIDE)
+ continue;
+
+ glyph_width = (cellp->width == HALF) ? CELL_WIDTH: CELL_WIDTH * 2;
+ bdf_shift = 32 - my_ceil(glyph_width, BITS_PER_BYTE) * BITS_PER_BYTE;
+ /* check cursor positon */
+ if ((term->mode & MODE_CURSOR && line == term->cursor.y)
+ && (col == term->cursor.x
+ || (cellp->width == WIDE && (col + 1) == term->cursor.x)
+ || (cellp->width == NEXT_TO_WIDE && (col - 1) == term->cursor.x))) {
+ color_pair.fg = DEFAULT_BG;
+ color_pair.bg = (!tty.visible && BACKGROUND_DRAW) ? PASSIVE_CURSOR_COLOR: ACTIVE_CURSOR_COLOR;
+ }
+ /* color palette */
+ fg = term->color_palette[color_pair.fg];
+ bg = term->color_palette[color_pair.bg];
+#if 0 /* Not yet on LUNA */
+ if (fb->wall && color_pair.bg == DEFAULT_BG) /* wallpaper */
+ memcpy(&pixel, fb->wall + pos, fb->bytes_per_pixel);
+#endif
+ x = CELL_WIDTH * col;
+ y = CELL_HEIGHT * line;
+
+ p = (u_int8_t *)fb->buf + y * fb->line_length + ((x / 32) * 4);
+ align = x & ALIGNMASK;
+ width = cellp->glyphp->width * CELL_WIDTH + align;
+ lmask = ALL1BITS >> align;
+ rmask = ALL1BITS << (-width & ALIGNMASK);
+ height = 0;
+
+ if (width <= BLITWIDTH) {
+ lmask &= rmask;
+ while (height < CELL_HEIGHT) {
+ /* if UNDERLINE attribute on, swap bg/fg */
+ if ((height == (CELL_HEIGHT - 1))
+ && (cellp->attribute & attr_mask[ATTR_UNDERLINE]))
+ bg = fg;
+ glyph = (uint32_t)cellp->glyphp->bitmap[height];
+ /* shift leftmost */
+ glyph <<= bdf_shift;
+ glyph = glyph >> align;
+
+ for (plane = 0; plane < DEPTH; plane++)
+ draw_glyph((uint32_t *)p, plane, glyph, fg, bg, lmask);
+
+ p += fb->line_length;
+ height++;
+ }
+ } else {
+ u_int8_t *q = p;
+ u_int32_t lhalf, rhalf;
+
+ while (height < CELL_HEIGHT) {
+ /* if UNDERLINE attribute on, swap bg/fg */
+ if ((height == (CELL_HEIGHT - 1))
+ && (cellp->attribute & attr_mask[ATTR_UNDERLINE]))
+ bg = fg;
+ glyph = (uint32_t)cellp->glyphp->bitmap[height];
+ /* shift leftmost */
+ glyph <<= bdf_shift;
+ lhalf = glyph >> align;
+
+ for (plane = 0; plane < DEPTH; plane++)
+ draw_glyph((uint32_t *)p, plane, lhalf, fg, bg, lmask);
+
+ p += BYTESDONE;
+ rhalf = glyph << (BLITWIDTH - align);
+
+ for (plane = 0; plane < DEPTH; plane++)
+ draw_glyph((uint32_t *)p, plane, rhalf, fg, bg, rmask);
+
+ p = (q += fb->line_length);
+ height++;
+ }
+ }
+ }
+
+ /* actual display update (bit blit) */
+ size = TERM_WIDTH / 8;
+ for (height = 0; height < CELL_HEIGHT; height++) {
+ for (plane = 0; plane < DEPTH; plane++) {
+ pos = (line * CELL_HEIGHT + height) * fb->line_length
+ + PLANESIZE * plane;
+ memcpy(fb->fp + pos, fb->buf + pos, size);
+ }
+ }
+#endif
/* TODO: page flip
if fb_fix_screeninfo.ypanstep > 0, we can use hardware panning.
set fb_fix_screeninfo.{yres_virtual,yoffset} and call ioctl(FBIOPAN_DISPLAY)
diff --git a/fb/openbsd.h b/fb/openbsd.h
index 05903c6..3796d8a 100644
--- a/fb/openbsd.h
+++ b/fb/openbsd.h
@@ -15,9 +15,15 @@ typedef unsigned long u_long;
/* some structs for OpenBSD */
enum term_size {
+#if 0
TERM_WIDTH = 640,
TERM_HEIGHT = 480,
DEPTH = 8,
+#else
+ TERM_WIDTH = 1280,
+ TERM_HEIGHT = 1024,
+ DEPTH = 8,
+#endif
};
enum fbtype_t {
@@ -45,6 +51,7 @@ struct fbinfo_t {
struct framebuffer {
uint8_t *fp; /* pointer of framebuffer(read only) */
+ uint8_t *fp_org; /* pointer of framebuffer(original) */
uint8_t *wall; /* buffer for wallpaper */
uint8_t *buf; /* copy of framebuffer */
int fd; /* file descriptor of framebuffer */
@@ -52,6 +59,7 @@ struct framebuffer {
long screen_size; /* screen data size (byte) */
int line_length; /* line length (byte) */
int bytes_per_pixel; /* BYTES per pixel */
+ int mode_org; /* original framebuffer mode */
struct wsdisplay_cmap /* cmap for legacy framebuffer (8bpp pseudocolor) */
*cmap, *cmap_org;
struct fbinfo_t vinfo;
@@ -169,7 +177,7 @@ static inline uint32_t color2pixel(struct fbinfo_t *vinfo, uint32_t color)
void fb_init(struct framebuffer *fb, uint32_t *color_palette)
{
- int i, orig_mode, mode;
+ int i, mode;
char *path, *env;
struct wsdisplay_fbinfo finfo;
struct wsdisplay_gfx_mode gfx_mode;
@@ -179,7 +187,7 @@ void fb_init(struct framebuffer *fb, uint32_t *color_palette)
else
fb->fd = eopen(fb_path, O_RDWR);
- ioctl(fb->fd, WSDISPLAYIO_GMODE, &orig_mode);
+ ioctl(fb->fd, WSDISPLAYIO_GMODE, &(fb->mode_org));
gfx_mode.width = TERM_WIDTH;
gfx_mode.height = TERM_HEIGHT;
@@ -197,12 +205,22 @@ void fb_init(struct framebuffer *fb, uint32_t *color_palette)
goto fb_init_error;
}
+ /* XXX: Should be check if WSDISPLAYIO_TYPE_LUNA ? */
+
fb->width = TERM_WIDTH;
fb->height = TERM_HEIGHT;
fb->bytes_per_pixel = my_ceil(DEPTH, BITS_PER_BYTE);
+#if 0
fb->line_length = fb->bytes_per_pixel * fb->width;
fb->screen_size = fb->height * fb->line_length;
+#else
+ if (ioctl(fb->fd, WSDISPLAYIO_LINEBYTES, &(fb->line_length))) {
+ fatal("ioctl: WSDISPLAYIO_LINEBYTES failed");
+ goto fb_init_error;
+ }
+ fb->screen_size = fb->height * fb->line_length * DEPTH;
+#endif
fb->vinfo = bpp_table[DEPTH];
if (DEBUG)
@@ -214,7 +232,7 @@ void fb_init(struct framebuffer *fb, uint32_t *color_palette)
fb->cmap = fb->cmap_org = NULL;
fb->vinfo.fbtype = FBTYPE_RGB;
}
- else if (DEPTH == 8) {
+ else if (DEPTH == 8 || DEPTH == 4 || DEPTH == 1 ) {
cmap_create(&fb->cmap, COLORS);
cmap_create(&fb->cmap_org, finfo.cmsize);
cmap_init(fb);
@@ -226,7 +244,10 @@ void fb_init(struct framebuffer *fb, uint32_t *color_palette)
for (i = 0; i < COLORS; i++) /* init color palette */
color_palette[i] = (fb->bytes_per_pixel == 1) ? (uint32_t) i: color2pixel(&fb->vinfo, color_list[i]);
- fb->fp = (uint8_t *) emmap(0, fb->screen_size, PROT_WRITE | PROT_READ, MAP_SHARED, fb->fd, 0);
+ fb->fp_org = (uint8_t *) emmap(0, fb->screen_size, PROT_WRITE | PROT_READ, MAP_SHARED, fb->fd, 0);
+
+ fb->fp = fb->fp_org + 8; /* XXX: LUNA quirk; need 8 byte offset */
+
fb->buf = (uint8_t *) ecalloc(1, fb->screen_size);
//fb->wall = (WALLPAPER && fb->bytes_per_pixel > 1) ? load_wallpaper(fb): NULL;
@@ -238,7 +259,7 @@ void fb_init(struct framebuffer *fb, uint32_t *color_palette)
return;
fb_init_error:
- ioctl(fb->fd, WSDISPLAYIO_SMODE, &orig_mode);
+ ioctl(fb->fd, WSDISPLAYIO_SMODE, &(fb->mode_org));
exit(EXIT_FAILURE);
}
@@ -251,6 +272,8 @@ void fb_die(struct framebuffer *fb)
}
free(fb->buf);
free(fb->wall);
- emunmap(fb->fp, fb->screen_size);
+ emunmap(fb->fp_org, fb->screen_size);
+ if (ioctl(fb->fd, WSDISPLAYIO_SMODE, &(fb->mode_org)))
+ fatal("ioctl: WSDISPLAYIO_SMODE failed");
eclose(fb->fd);
}
diff --git a/makefile b/makefile
index caf405f..8fc5679 100644
--- a/makefile
+++ b/makefile
@@ -1,7 +1,8 @@
CC ?= gcc
#CC ?= clang
-CFLAGS ?= -std=c99 -pedantic -Wall -Wextra -O3 -s -pipe
+#CFLAGS ?= -std=c99 -pedantic -Wall -Wextra -O3 -s -pipe
+CFLAGS = -std=c99 -pedantic -Wall -Wextra -O3 -s -pipe
LDFLAGS ?=
XCFLAGS ?= -std=c99 -pedantic -Wall -Wextra -I/usr/include/X11/ -O3 -s -pipe
diff --git a/yaft.c b/yaft.c
index 6068da2..a936c7b 100644
--- a/yaft.c
+++ b/yaft.c
@@ -75,11 +75,13 @@ void tty_init(struct termios *save_tm)
vtm.mode = VT_PROCESS;
vtm.waitv = 0;
vtm.relsig = vtm.acqsig = vtm.frsig = SIGUSR1;
+#if 0 /* XXX: LUNA currently does not supoort these ioctls */
if (ioctl(STDIN_FILENO, VT_SETMODE, &vtm))
fatal("ioctl: VT_SETMODE failed (maybe here is not console)");
if (ioctl(STDIN_FILENO, KDSETMODE, KD_GRAPHICS))
fatal("ioctl: KDSETMODE failed (maybe here is not console)");
+#endif
etcgetattr(STDIN_FILENO, save_tm);
set_rawmode(STDIN_FILENO, save_tm);
@@ -100,8 +102,10 @@ void tty_die(struct termios *save_tm)
vtm.mode = VT_AUTO;
vtm.waitv = 0;
vtm.relsig = vtm.acqsig = vtm.frsig = 0;
+#if 0 /* XXX: LUNA currently does not supoort these ioctls */
ioctl(STDIN_FILENO, VT_SETMODE, &vtm);
ioctl(STDIN_FILENO, KDSETMODE, KD_TEXT);
+#endif
tcsetattr(STDIN_FILENO, TCSAFLUSH, save_tm);
fflush(stdout);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment