diff -u -r -N pce-0.1.7/src/arch/ibmpc/ibmpc.c pce-new/src/arch/ibmpc/ibmpc.c
--- pce-0.1.7/src/arch/ibmpc/ibmpc.c	2006-07-03 07:48:47.000000000 +0100
+++ pce-new/src/arch/ibmpc/ibmpc.c	2008-10-14 23:06:25.000000000 +0100
@@ -5,8 +5,9 @@
 /*****************************************************************************
  * File name:     src/arch/ibmpc/ibmpc.c                                     *
  * Created:       1999-04-16 by Hampa Hug <hampa@hampa.ch>                   *
- * Last modified: 2006-07-03 by Hampa Hug <hampa@hampa.ch>                   *
+ * Last modified: 2008-10-13 by John Elliott <jce@seasip.demon.co.uk>        *
  * Copyright:     (C) 1999-2006 Hampa Hug <hampa@hampa.ch>                   *
+ *                (C) 2008 John Elliott <jce@seasip.demon.co.uk>             *
  *****************************************************************************/
 
 /*****************************************************************************
@@ -386,6 +387,42 @@
 }
 
 static
+int pc_setup_plantronics (ibmpc_t *pc, ini_sct_t *sct)
+{
+	pc->video = plantronics_new (pc->trm, sct);
+	if (pc->video == NULL) {
+		return (1);
+	}
+
+	mem_add_blk (pc->mem, pce_video_get_mem (pc->video), 0);
+	mem_add_blk (pc->prt, pce_video_get_reg (pc->video), 0);
+
+	pc->ppi_port_a[0] &= ~0x30;
+	pc->ppi_port_a[0] |= 0x20;
+
+	return (0);
+}
+
+
+static
+int pc_setup_wy700 (ibmpc_t *pc, ini_sct_t *sct)
+{
+	pc->video = wy700_new (pc->trm, sct);
+	if (pc->video == NULL) {
+		return (1);
+	}
+
+	mem_add_blk (pc->mem, pce_video_get_mem (pc->video), 0);
+	mem_add_blk (pc->prt, pce_video_get_reg (pc->video), 0);
+
+	pc->ppi_port_a[0] &= ~0x30;
+	pc->ppi_port_a[0] |= 0x20;
+
+	return (0);
+}
+
+
+static
 int pc_setup_cga (ibmpc_t *pc, ini_sct_t *sct)
 {
 	pc->video = cga_new (pc->trm, sct);
@@ -469,6 +506,12 @@
 	else if (strcmp (dev, "cga") == 0) {
 		pc_setup_cga (pc, sct);
 	}
+	else if (strcmp (dev, "plantronics") == 0) {
+		pc_setup_plantronics (pc, sct);
+	}
+	else if (strcmp (dev, "wyse") == 0 || strcmp (dev, "wy700") == 0) {
+		pc_setup_wy700 (pc, sct);
+	}
 	else if (strcmp (dev, "hgc") == 0) {
 		pc_setup_hgc (pc, sct);
 	}
diff -u -r -N pce-0.1.7/src/arch/ibmpc/main.h pce-new/src/arch/ibmpc/main.h
--- pce-0.1.7/src/arch/ibmpc/main.h	2006-06-19 08:56:15.000000000 +0100
+++ pce-new/src/arch/ibmpc/main.h	2008-10-14 23:01:18.000000000 +0100
@@ -5,8 +5,9 @@
 /*****************************************************************************
  * File name:     src/arch/ibmpc/main.h                                      *
  * Created:       2001-05-01 by Hampa Hug <hampa@hampa.ch>                   *
- * Last modified: 2006-06-19 by Hampa Hug <hampa@hampa.ch>                   *
+ * Last modified: 2008-10-13 by John Elliott <jce@seasip.demon.co.uk>        *
  * Copyright:     (C) 1996-2006 Hampa Hug <hampa@hampa.ch>                   *
+ *                (C) 2008 John Elliott <jce@seasip.demon.co.uk>             *
  *****************************************************************************/
 
 /*****************************************************************************
@@ -111,6 +112,8 @@
 #include <devices/video/mda.h>
 #include <devices/video/hgc.h>
 #include <devices/video/cga.h>
+#include <devices/video/plantronics.h>
+#include <devices/video/wy700.h>
 #include <devices/video/ega.h>
 #include <devices/video/vga.h>
 
diff -u -r -N pce-0.1.7/src/arch/ibmpc/Makefile.in pce-new/src/arch/ibmpc/Makefile.in
--- pce-0.1.7/src/arch/ibmpc/Makefile.in	2006-06-19 08:56:15.000000000 +0100
+++ pce-new/src/arch/ibmpc/Makefile.in	2008-10-14 23:04:34.000000000 +0100
@@ -28,6 +28,8 @@
 	$(pcedst)/cpu/e8086/e8086.a \
 	$(pcedst)/chipset/82xx/chipset.a \
 	$(pcedst)/devices/video/cga.o \
+	$(pcedst)/devices/video/plantronics.o \
+	$(pcedst)/devices/video/wy700.o \
 	$(pcedst)/devices/video/vga.o \
 	$(pcedst)/devices/video/ega.o \
 	$(pcedst)/devices/video/hgc.o \
diff -u -r -N pce-0.1.7/src/devices/video/cga.c pce-new/src/devices/video/cga.c
--- pce-0.1.7/src/devices/video/cga.c	2005-12-28 21:42:53.000000000 +0000
+++ pce-new/src/devices/video/cga.c	2008-10-14 21:57:00.000000000 +0100
@@ -5,8 +5,9 @@
 /*****************************************************************************
  * File name:     src/devices/video/cga.c                                    *
  * Created:       2003-04-18 by Hampa Hug <hampa@hampa.ch>                   *
- * Last modified: 2005-04-20 by Hampa Hug <hampa@hampa.ch>                   *
+ * Last modified: 2008-10-13 by John Elliott <jce@seasip.demon.co.uk>        *
  * Copyright:     (C) 2003-2005 Hampa Hug <hampa@hampa.ch>                   *
+ *                (C) 2008 John Elliott <jce@seasip.demon.co.uk>             *
  *****************************************************************************/
 
 /*****************************************************************************
@@ -130,6 +131,8 @@
 	cga->palette[1] = 11;
 	cga->palette[2] = 13;
 	cga->palette[3] = 15;
+	cga->modereg = 0;
+	cga->colreg = 0;
 
 	cga->mode = 0;
 	trm_set_mode (trm, TERM_MODE_TEXT, 80, 25);
@@ -472,11 +475,12 @@
 int cga_mode2_screenshot (cga_t *cga, FILE *fp)
 {
 	unsigned      x, y, i;
-	unsigned      val;
+	unsigned      val, col;
 	unsigned char *mem;
 
-	fputs ("P5\n640 200\n255 ", fp);
+	fputs ("P6\n640 200\n255 ", fp);
 
+	col = cga->palette[0];
 	for (y = 0; y < 200; y++) {
 		mem = cga->mem->data + 80 * (y / 2);
 
@@ -489,10 +493,14 @@
 
 			for (i = 0; i < 8; i++) {
 				if (val & (0x80 >> i)) {
-					fputc (0xff, fp);
+					fputc (cga_col[col].r >> 8, fp);
+					fputc (cga_col[col].g >> 8, fp);
+					fputc (cga_col[col].b >> 8, fp);
 				}
 				else {
 					fputc (0x00, fp);
+					fputc (0x00, fp);
+					fputc (0x00, fp);
 				}
 			}
 		}
@@ -517,10 +525,10 @@
 			val1 = mem1[x];
 
 			for (i = 0; i < 8; i++) {
-				trm_set_col (cga->trm, (val0 & 0x80) ? 15 : 0, 0);
+				trm_set_col (cga->trm, (val0 & 0x80) ? cga->palette[0] : 0, 0);
 				trm_set_pxl (cga->trm, 8 * x + i, 2 * y);
 
-				trm_set_col (cga->trm, (val1 & 0x80) ? 15 : 0, 0);
+				trm_set_col (cga->trm, (val1 & 0x80) ? cga->palette[0] : 0, 0);
 				trm_set_pxl (cga->trm, 8 * x + i, 2 * y + 1);
 
 				val0 <<= 1;
@@ -561,7 +569,7 @@
 
 		if ((old ^ val) & 0x80) {
 			col = (val >> 7) & 0x01;
-			trm_set_col (cga->trm, col ? 15 : 0, 0);
+			trm_set_col (cga->trm, col ? cga->palette[0] : 0, 0);
 			trm_set_pxl (cga->trm, x + i, y);
 		}
 
@@ -654,38 +662,73 @@
 	}
 }
 
-void cga_set_palette (cga_t *cga, unsigned pal, unsigned char bg)
+void cga_set_palette (cga_t *cga)
 {
-	pal &= 1;
+	unsigned pal, bg;
+	
+	pal = ((cga->colreg >> 4) & 3) | (cga->modereg & 4);
+	bg  = cga->colreg & 0x0F;
 
-	if (pal == cga->pal) {
+	if (pal == cga->pal && bg == cga->palette[0]) {
 		return;
 	}
 
 	cga->pal = pal;
 
-	switch (pal & 1) {
+	switch (pal) {
 		case 0:
 			cga->palette[0] = bg;
-			cga->palette[1] = 8;
+			cga->palette[1] = 3;
+			cga->palette[2] = 5;
+			cga->palette[3] = 7;
+			break;
+
+		case 1:
+			cga->palette[0] = bg;
+			cga->palette[1] = 11;
 			cga->palette[2] = 13;
 			cga->palette[3] = 15;
 			break;
 
-		case 1:
+		case 2:
+			cga->palette[0] = bg;
+			cga->palette[1] = 2;
+			cga->palette[2] = 4;
+			cga->palette[3] = 6;
+			break;
+
+		case 3:
 			cga->palette[0] = bg;
 			cga->palette[1] = 10;
 			cga->palette[2] = 12;
 			cga->palette[3] = 14;
 			break;
+
+		case 4:
+		case 6:
+			cga->palette[0] = bg;
+			cga->palette[1] = 3;
+			cga->palette[2] = 4;
+			cga->palette[3] = 7;
+			break;
+	
+		case 5:
+		case 7:
+			cga->palette[0] = bg;
+			cga->palette[1] = 11;
+			cga->palette[2] = 12;
+			cga->palette[3] = 15;
+			break;
 	}
 
 	cga_update (cga);
 }
 
-void cga_set_mode (cga_t *cga, unsigned char mode)
+void cga_set_mode (cga_t *cga)
 {
-	unsigned newmode;
+	unsigned newmode, mode;
+
+	mode = cga->modereg;
 
 	if ((mode & 0x02) == 0) {
 		newmode = 0;
@@ -723,6 +766,9 @@
 	cga_update (cga);
 }
 
+
+
+
 void cga_mem_set_uint8 (cga_t *cga, unsigned long addr, unsigned char val)
 {
 	switch (cga->mode) {
@@ -810,11 +856,15 @@
 			break;
 
 		case 0x04:
-			cga_set_mode (cga, val);
+			cga->modereg = val;
+			cga_set_mode (cga);
+/* Mode register can affect palette */
+			cga_set_palette (cga);
 			break;
 
 		case 0x05:
-			cga_set_palette (cga, (val >> 5) ^ 1, val & 0x0f);
+			cga->colreg = val;
+			cga_set_palette (cga);
 			break;
 	}
 }
diff -u -r -N pce-0.1.7/src/devices/video/cga.h pce-new/src/devices/video/cga.h
--- pce-0.1.7/src/devices/video/cga.h	2005-12-28 21:42:53.000000000 +0000
+++ pce-new/src/devices/video/cga.h	2008-10-14 21:53:59.000000000 +0100
@@ -5,8 +5,9 @@
 /*****************************************************************************
  * File name:     src/devices/video/cga.h                                    *
  * Created:       2003-04-18 by Hampa Hug <hampa@hampa.ch>                   *
- * Last modified: 2005-04-18 by Hampa Hug <hampa@hampa.ch>                   *
+ * Last modified: 2008-10-13 by John Elliott <jce@seasip.demon.co.uk>        *
  * Copyright:     (C) 2003-2005 Hampa Hug <hampa@hampa.ch>                   *
+ *                (C) 2008 John Elliott <jce@seasip.demon.co.uk>             *
  *****************************************************************************/
 
 /*****************************************************************************
@@ -55,6 +56,9 @@
 	unsigned char pal;
 	unsigned char palette[4];
 
+	unsigned char modereg;
+	unsigned char colreg;
+	
 	int           crs_on;
 
 	unsigned      mode;
diff -u -r -N pce-0.1.7/src/devices/video/Makefile.in pce-new/src/devices/video/Makefile.in
--- pce-0.1.7/src/devices/video/Makefile.in	2005-04-18 10:43:52.000000000 +0100
+++ pce-new/src/devices/video/Makefile.in	2008-10-14 22:55:30.000000000 +0100
@@ -10,7 +10,7 @@
 include $(reldir)/config.inc
 
 
-FILES := cga ega hgc mda vga video
+FILES := cga ega hgc mda vga plantronics wy700 video
 
 SRC := $(foreach f,$(FILES),$(f).c)
 OBJ := $(foreach f,$(FILES),$(f).o)
@@ -27,6 +27,18 @@
 all: $(BIN) $(OBJ)
 
 
+plantronics.o:	plantronics.c plantronics.h video.h devices/memory.h \
+		libini/libini.h \
+		terminal/terminal.h \
+		lib/log.h \
+		lib/hexdump.h $(SDP)
+
+wy700.o:	wy700.c wy700.h video.h devices/memory.h \
+		libini/libini.h \
+		terminal/terminal.h \
+		lib/log.h \
+		lib/hexdump.h $(SDP)
+
 cga.o:		cga.c cga.h video.h devices/memory.h \
 		libini/libini.h \
 		terminal/terminal.h \
diff -u -r -N pce-0.1.7/src/devices/video/plantronics.c pce-new/src/devices/video/plantronics.c
--- pce-0.1.7/src/devices/video/plantronics.c	1970-01-01 01:00:00.000000000 +0100
+++ pce-new/src/devices/video/plantronics.c	2008-10-14 21:57:33.000000000 +0100
@@ -0,0 +1,1309 @@
+/*****************************************************************************
+ * pce                                                                       *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * File name:     src/devices/video/plantronics.c                            *
+ * Created:       2003-04-18 by Hampa Hug <hampa@hampa.ch>                   *
+ * Last modified: 2008-10-13 by John Elliott <jce@seasip.demon.co.uk>        *
+ * Copyright:     (C) 2003-2005 Hampa Hug <hampa@hampa.ch>                   *
+ *                (C) 2008 John Elliott <jce@seasip.demon.co.uk>             *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * This program is free software. You can redistribute it and / or modify it *
+ * under the terms of the GNU General Public License version 2 as  published *
+ * by the Free Software Foundation.                                          *
+ *                                                                           *
+ * This program is distributed in the hope  that  it  will  be  useful,  but *
+ * WITHOUT  ANY   WARRANTY,   without   even   the   implied   warranty   of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  General *
+ * Public License for more details.                                          *
+ *****************************************************************************/
+
+/* $Id: plantronics.c 619 2005-12-28 21:42:53Z hampa $ */
+
+
+#include <stdio.h>
+
+#include <lib/log.h>
+#include <lib/hexdump.h>
+
+#include "plantronics.h"
+
+
+static
+struct {  unsigned short r, g, b; } plantronics_col[16] = {
+	{ 0x0000, 0x0000, 0x0000 },
+	{ 0x0a0a, 0x0a0a, 0xb9b9 },
+	{ 0x0a0a, 0xc3c3, 0x0a0a },
+	{ 0x1414, 0xa0a0, 0xa0a0 },
+	{ 0xa7a7, 0x0a0a, 0x0a0a },
+	{ 0xa7a7, 0x0000, 0xa7a7 },
+	{ 0xa5a5, 0xa5a5, 0x2828 },
+	{ 0xc5c5, 0xc5c5, 0xc5c5 },
+	{ 0x6464, 0x6464, 0x6464 },
+	{ 0x0a0a, 0x0a0a, 0xffff },
+	{ 0x0a0a, 0xffff, 0x0a0a },
+	{ 0x0a0a, 0xffff, 0xffff },
+	{ 0xffff, 0x0a0a, 0x0a0a },
+	{ 0xffff, 0x0a0a, 0xffff },
+	{ 0xffff, 0xffff, 0x0000 },
+	{ 0xffff, 0xffff, 0xffff }
+};
+
+
+video_t *plantronics_new (terminal_t *trm, ini_sct_t *sct)
+{
+	unsigned      i;
+	unsigned long iobase, membase, memsize;
+	unsigned      w, h;
+	plantronics_t         *plantronics;
+
+	plantronics = (plantronics_t *) malloc (sizeof (plantronics_t));
+	if (plantronics == NULL) {
+		return (NULL);
+	}
+
+	pce_video_init (&plantronics->vid);
+
+	plantronics->vid.ext = plantronics;
+	plantronics->vid.del = (pce_video_del_f) plantronics_del;
+	plantronics->vid.get_mem = (pce_video_get_mem_f) plantronics_get_mem;
+	plantronics->vid.get_reg = (pce_video_get_reg_f) plantronics_get_reg;
+	plantronics->vid.prt_state = (pce_video_prt_state_f) plantronics_prt_state;
+	plantronics->vid.update = (pce_video_update_f) plantronics_update;
+	plantronics->vid.dump = (pce_video_dump_f) plantronics_dump;
+	plantronics->vid.screenshot = (pce_video_screenshot_f) plantronics_screenshot;
+	plantronics->vid.clock = (pce_video_clock_f) plantronics_clock;
+
+	for (i = 0; i < 16; i++) {
+		plantronics->crtc_reg[i] = 0;
+	}
+
+	w = ini_get_lng_def (sct, "w", 640);
+	h = ini_get_lng_def (sct, "h", 400);
+
+	plantronics->mode_80x25_w = ini_get_lng_def (sct, "mode_80x25_w", w);
+	plantronics->mode_80x25_h = ini_get_lng_def (sct, "mode_80x25_h", h);
+	plantronics->mode_320x200_w = ini_get_lng_def (sct, "mode_320x200_w", w);
+	plantronics->mode_320x200_h = ini_get_lng_def (sct, "mode_320x200_h", h);
+	plantronics->mode_640x200_w = ini_get_lng_def (sct, "mode_640x200_w", w);
+	plantronics->mode_640x200_h = ini_get_lng_def (sct, "mode_640x200_h", h);
+	iobase = ini_get_lng_def (sct, "io", 0x3d4L);
+	membase = ini_get_lng_def (sct, "membase", 0xb8000L);
+	memsize = ini_get_lng_def (sct, "memsize", 32768L);
+
+	if (memsize < 32768) {
+		memsize = 32768;
+	}
+
+	pce_log (MSG_INF, "video:\tPlantronics io=0x%04lx membase=0x%05lx memsize=0x%05lx\n",
+		iobase, membase, memsize
+	);
+
+	plantronics->mem = mem_blk_new (membase, memsize, 1);
+	plantronics->mem->ext = plantronics;
+	plantronics->mem->set_uint8 = (mem_set_uint8_f) &plantronics_mem_set_uint8;
+	plantronics->mem->set_uint16 = (mem_set_uint16_f) &plantronics_mem_set_uint16;
+	mem_blk_clear (plantronics->mem, 0x00);
+
+	plantronics->reg = mem_blk_new (iobase, 16, 1);
+	plantronics->reg->ext = plantronics;
+	plantronics->reg->set_uint8 = (mem_set_uint8_f) &plantronics_reg_set_uint8;
+	plantronics->reg->set_uint16 = (mem_set_uint16_f) &plantronics_reg_set_uint16;
+	plantronics->reg->get_uint8 = (mem_get_uint8_f) &plantronics_reg_get_uint8;
+	plantronics->reg->get_uint16 = (mem_get_uint16_f) &plantronics_reg_get_uint16;
+	mem_blk_clear (plantronics->reg, 0x00);
+
+	plantronics->trm = trm;
+
+	plantronics->crtc_pos = 0;
+	plantronics->crtc_ofs = 0;
+
+	plantronics->clkcnt = 0;
+
+	plantronics->crs_on = 1;
+
+	plantronics->pal = 0;
+	plantronics->palette[0] = 0;
+	plantronics->palette[1] = 11;
+	plantronics->palette[2] = 13;
+	plantronics->palette[3] = 15;
+	plantronics->special = 0;
+	plantronics->modereg = 0;
+	plantronics->colreg = 0;
+
+	plantronics->mode = 0;
+	trm_set_mode (trm, TERM_MODE_TEXT, 80, 25);
+	trm_set_size (trm, plantronics->mode_80x25_w, plantronics->mode_80x25_h);
+
+	return (&plantronics->vid);
+}
+
+void plantronics_del (plantronics_t *plantronics)
+{
+	if (plantronics != NULL) {
+		mem_blk_del (plantronics->mem);
+		mem_blk_del (plantronics->reg);
+		free (plantronics);
+	}
+}
+
+void plantronics_clock (plantronics_t *plantronics, unsigned long cnt)
+{
+	plantronics->clkcnt += cnt;
+}
+
+void plantronics_prt_state (plantronics_t *plantronics, FILE *fp)
+{
+	unsigned i;
+	unsigned x, y;
+
+	if (plantronics->crtc_pos < plantronics->crtc_ofs) {
+		x = 0;
+		y = 0;
+	}
+	else {
+		x = (plantronics->crtc_pos - plantronics->crtc_ofs) % 80;
+		y = (plantronics->crtc_pos - plantronics->crtc_ofs) / 80;
+	}
+
+	fprintf (fp, "Plantronics: MODE=%u  OFS=%04X  POS=%04X[%u/%u]  CRS=%s  BG=%02X  PAL=%u\n",
+		plantronics->mode, plantronics->crtc_ofs, plantronics->crtc_pos, x, y,
+		(plantronics->crs_on) ? "ON" : "OFF",
+		plantronics->reg->data[5] & 0x0f, (plantronics->reg->data[5] >> 5) & 1
+	);
+
+	fprintf (fp, "REG: 3D8=%02X  3D9=%02X  3DA=%02X  3DD=%02X  PAL=%u:[%02X %02X %02X %02X]\n",
+		plantronics->reg->data[4], plantronics->reg->data[5], plantronics->reg->data[6], plantronics->reg->data[9],
+		plantronics->pal, plantronics->palette[0], plantronics->palette[1], plantronics->palette[2], plantronics->palette[3]
+	);
+
+	fprintf (fp, "CRTC=[%02X", plantronics->crtc_reg[0]);
+	for (i = 1; i < 18; i++) {
+		if ((i & 7) == 0) {
+			fputs ("-", fp);
+		}
+		else {
+			fputs (" ", fp);
+		}
+		fprintf (fp, "%02X", plantronics->crtc_reg[i]);
+	}
+	fputs ("]\n", fp);
+
+	fflush (fp);
+}
+
+int plantronics_dump (plantronics_t *plantronics, FILE *fp)
+{
+	fprintf (fp, "# Plantronics dump\n");
+
+	fprintf (fp, "\n# REGS:\n");
+	pce_dump_hex (fp,
+		mem_blk_get_data (plantronics->reg),
+		mem_blk_get_size (plantronics->reg),
+		mem_blk_get_addr (plantronics->reg),
+		16, "# ", 0
+	);
+
+	fprintf (fp, "\n# CRTC:\n");
+	pce_dump_hex (fp, plantronics->crtc_reg, 18, 0, 16, "# ", 0);
+
+	fputs ("\n\n# RAM:\n", fp);
+	pce_dump_hex (fp,
+		mem_blk_get_data (plantronics->mem),
+		mem_blk_get_size (plantronics->mem),
+		mem_blk_get_addr (plantronics->mem),
+		16, "", 1
+	);
+
+	return (0);
+}
+
+mem_blk_t *plantronics_get_mem (plantronics_t *plantronics)
+{
+	return (plantronics->mem);
+}
+
+mem_blk_t *plantronics_get_reg (plantronics_t *plantronics)
+{
+	return (plantronics->reg);
+}
+
+
+/*****************************************************************************
+ * mode 0 (text 80 * 25)
+ *****************************************************************************/
+
+static
+int plantronics_mode0_screenshot (plantronics_t *plantronics, FILE *fp)
+{
+	unsigned i;
+	unsigned x, y;
+
+	i = (plantronics->crtc_ofs << 1) & 0x3fff;
+
+	for (y = 0; y < 25; y++) {
+		for (x = 0; x < 80; x++) {
+			fputc (plantronics->mem->data[i], fp);
+			i = (i + 2) & 0x7fff;
+		}
+
+		fputs ("\n", fp);
+	}
+
+	return (0);
+}
+
+static
+void plantronics_mode0_update (plantronics_t *plantronics)
+{
+	unsigned i;
+	unsigned x, y;
+	unsigned fg, bg;
+
+	i = (plantronics->crtc_ofs << 1) & 0x3fff;
+
+	for (y = 0; y < 25; y++) {
+		for (x = 0; x < 80; x++) {
+			fg = plantronics->mem->data[i + 1] & 0x0f;
+			bg = (plantronics->mem->data[i + 1] & 0xf0) >> 4;
+
+			trm_set_col (plantronics->trm, fg, bg);
+			trm_set_chr (plantronics->trm, x, y, plantronics->mem->data[i]);
+
+			i = (i + 2) & 0x3fff;
+		}
+	}
+}
+
+void plantronics_mode0_set_uint8 (plantronics_t *plantronics, unsigned long addr, unsigned char val)
+{
+	unsigned      x, y;
+	unsigned char c, a;
+
+	if (plantronics->mem->data[addr] == val) {
+		return;
+	}
+
+	plantronics->mem->data[addr] = val;
+
+	if (addr & 1) {
+		c = plantronics->mem->data[addr - 1];
+		a = val;
+	}
+	else {
+		c = val;
+		a = plantronics->mem->data[addr + 1];
+	}
+
+	if (addr < (plantronics->crtc_ofs << 1)) {
+		return;
+	}
+
+	addr -= (plantronics->crtc_ofs << 1);
+
+	if (addr >= 4000) {
+		return;
+	}
+
+	x = (addr >> 1) % 80;
+	y = (addr >> 1) / 80;
+
+	trm_set_col (plantronics->trm, a & 0x0f, (a & 0xf0) >> 4);
+	trm_set_chr (plantronics->trm, x, y, c);
+}
+
+void plantronics_mode0_set_uint16 (plantronics_t *plantronics, unsigned long addr, unsigned short val)
+{
+	unsigned      x, y;
+	unsigned char c, a;
+
+	if (addr & 1) {
+		plantronics_mem_set_uint8 (plantronics, addr, val & 0xff);
+		plantronics_mem_set_uint8 (plantronics, addr + 1, (val >> 8) & 0xff);
+		return;
+	}
+
+	c = val & 0xff;
+	a = (val >> 8) & 0xff;
+
+	if ((plantronics->mem->data[addr] == c) && (plantronics->mem->data[addr + 1] == a)) {
+		return;
+	}
+
+	plantronics->mem->data[addr] = c;
+	plantronics->mem->data[addr + 1] = a;
+
+	if (addr < (plantronics->crtc_ofs << 1)) {
+		return;
+	}
+
+	addr -= (plantronics->crtc_ofs << 1);
+
+	if (addr >= 4000) {
+		return;
+	}
+
+	x = (addr >> 1) % 80;
+	y = (addr >> 1) / 80;
+
+	trm_set_col (plantronics->trm, a & 0x0f, (a & 0xf0) >> 4);
+	trm_set_chr (plantronics->trm, x, y, c);
+}
+
+
+/*****************************************************************************
+ * mode 1 (graphics 320 * 200 * 4)
+ *****************************************************************************/
+
+static
+int plantronics_mode1_screenshot (plantronics_t *plantronics, FILE *fp)
+{
+	unsigned      x, y, i;
+	unsigned      val, idx;
+	unsigned char *mem;
+
+	fputs ("P6\n320 200\n255 ", fp);
+
+	for (y = 0; y < 200; y++) {
+		mem = plantronics->mem->data + 80 * (y / 2);
+
+		if (y & 1) {
+			mem += 8192;
+		}
+
+		for (x = 0; x < 80; x++) {
+			val = mem[x];
+
+			for (i = 0; i < 4; i++) {
+				idx = (val >> 6) & 0x03;
+				idx = plantronics->palette[idx];
+				fputc (plantronics_col[idx].r >> 8, fp);
+				fputc (plantronics_col[idx].g >> 8, fp);
+				fputc (plantronics_col[idx].b >> 8, fp);
+
+				val <<= 2;
+			}
+		}
+	}
+
+	return (0);
+}
+
+static
+void plantronics_mode1_update (plantronics_t *plantronics)
+{
+	unsigned      x, y, i;
+	unsigned      val0, val1;
+	unsigned char *mem0, *mem1;
+
+	mem0 = plantronics->mem->data;
+	mem1 = plantronics->mem->data + 8192;
+
+	for (y = 0; y < 100; y++) {
+		for (x = 0; x < 80; x++) {
+			val0 = mem0[x];
+			val1 = mem1[x];
+
+			for (i = 0; i < 4; i++) {
+				trm_set_col (plantronics->trm, plantronics->palette[(val0 >> 6) & 0x03], 0);
+				trm_set_pxl (plantronics->trm, 4 * x + i, 2 * y);
+
+				trm_set_col (plantronics->trm, plantronics->palette[(val1 >> 6) & 0x03], 0);
+				trm_set_pxl (plantronics->trm, 4 * x + i, 2 * y + 1);
+
+				val0 <<= 2;
+				val1 <<= 2;
+			}
+		}
+
+		mem0 += 80;
+		mem1 += 80;
+	}
+}
+
+void plantronics_mode1_set_uint8 (plantronics_t *plantronics, unsigned long addr, unsigned char val)
+{
+	unsigned      i;
+	unsigned      x, y;
+	unsigned char old;
+
+	old = plantronics->mem->data[addr];
+
+	if (old == val) {
+		return;
+	}
+
+	plantronics->mem->data[addr] = val;
+
+	if (addr < 8192) {
+		x = 4 * (addr % 80);
+		y = 2 * (addr / 80);
+	}
+	else {
+		x = 4 * ((addr - 8192) % 80);
+		y = 2 * ((addr - 8192) / 80) + 1;
+	}
+
+	if (y >= 200) {
+		return;
+	}
+
+	for (i = 0; i < 4; i++) {
+		unsigned col;
+
+		if ((old ^ val) & 0xc0) {
+			col = (val >> 6) & 0x03;
+			trm_set_col (plantronics->trm, plantronics->palette[col], 0);
+
+			trm_set_pxl (plantronics->trm, x + i, y);
+		}
+
+		old <<= 2;
+		val <<= 2;
+	}
+}
+
+
+/*****************************************************************************
+ * mode 2 (graphics 620 * 200 * 2)
+ *****************************************************************************/
+
+static
+int plantronics_mode2_screenshot (plantronics_t *plantronics, FILE *fp)
+{
+	unsigned      x, y, i;
+	unsigned      val, col;
+	unsigned char *mem;
+
+	fputs ("P6\n640 200\n255 ", fp);
+
+	col = plantronics->palette[0];
+	for (y = 0; y < 200; y++) {
+		mem = plantronics->mem->data + 80 * (y / 2);
+
+		if (y & 1) {
+			mem += 8192;
+		}
+
+		for (x = 0; x < 80; x++) {
+			val = mem[x];
+
+			for (i = 0; i < 8; i++) {
+				if (val & (0x80 >> i)) {
+					fputc (plantronics_col[col].r >> 8, fp);
+					fputc (plantronics_col[col].g >> 8, fp);
+					fputc (plantronics_col[col].b >> 8, fp);
+				}
+				else {
+					fputc (0x00, fp);
+					fputc (0x00, fp);
+					fputc (0x00, fp);
+				}
+			}
+		}
+	}
+
+	return (0);
+}
+
+static
+void plantronics_mode2_update (plantronics_t *plantronics)
+{
+	unsigned      x, y, i;
+	unsigned      val0, val1;
+	unsigned char *mem0, *mem1;
+
+	mem0 = plantronics->mem->data;
+	mem1 = plantronics->mem->data + 8192;
+
+	for (y = 0; y < 100; y++) {
+		for (x = 0; x < 80; x++) {
+			val0 = mem0[x];
+			val1 = mem1[x];
+
+			for (i = 0; i < 8; i++) {
+				trm_set_col (plantronics->trm, (val0 & 0x80) ? plantronics->palette[0] : 0, 0);
+				trm_set_pxl (plantronics->trm, 8 * x + i, 2 * y);
+
+				trm_set_col (plantronics->trm, (val1 & 0x80) ? plantronics->palette[0] : 0, 0);
+				trm_set_pxl (plantronics->trm, 8 * x + i, 2 * y + 1);
+
+				val0 <<= 1;
+				val1 <<= 1;
+			}
+		}
+
+		mem0 += 80;
+		mem1 += 80;
+	}
+}
+
+void plantronics_mode2_set_uint8 (plantronics_t *plantronics, unsigned long addr, unsigned char val)
+{
+	unsigned      i;
+	unsigned      x, y;
+	unsigned char old;
+
+	old = plantronics->mem->data[addr];
+
+	if (old == val) {
+		return;
+	}
+
+	plantronics->mem->data[addr] = val;
+
+	if (addr < 8192) {
+		x = 8 * (addr % 80);
+		y = 2 * (addr / 80);
+	}
+	else {
+		x = 8 * ((addr - 8192) % 80);
+		y = 2 * ((addr - 8192) / 80) + 1;
+	}
+
+	for (i = 0; i < 8; i++) {
+		unsigned col;
+
+		if ((old ^ val) & 0x80) {
+			col = (val >> 7) & 0x01;
+			trm_set_col (plantronics->trm, col ? plantronics->palette[0] : 0, 0);
+			trm_set_pxl (plantronics->trm, x + i, y);
+		}
+
+		old <<= 1;
+		val <<= 1;
+	}
+}
+
+
+
+/*****************************************************************************
+ * mode 3 (graphics 320 * 200 * 16)
+ *****************************************************************************/
+
+static
+int plantronics_mode3_screenshot (plantronics_t *plantronics, FILE *fp)
+{
+	unsigned      x, y, i;
+	unsigned      val0, val1, idx;
+	unsigned char *mem0, *mem1, *plane0, *plane1;
+
+	fputs ("P6\n320 200\n255 ", fp);
+
+	if (plantronics->special & 0x40) {
+		plane0 = plantronics->mem->data;
+		plane1 = plantronics->mem->data + 0x4000;
+	} else {
+		plane0 = plantronics->mem->data + 0x4000;
+		plane1 = plantronics->mem->data;
+	}
+
+	for (y = 0; y < 200; y++) {
+		mem0 = plane0 + 80 * (y / 2);
+		mem1 = plane1 + 80 * (y / 2);
+
+		if (y & 1) {
+			mem0 += 8192;
+			mem1 += 8192;
+		}
+
+		for (x = 0; x < 80; x++) {
+			val0 = mem0[x];
+			val1 = mem1[x];
+
+			for (i = 0; i < 4; i++) {
+				idx =	(( val0 >> 6) & 3) | 
+					(((val1 >> 6) & 3) << 2);
+				fputc (plantronics_col[idx].r >> 8, fp);
+				fputc (plantronics_col[idx].g >> 8, fp);
+				fputc (plantronics_col[idx].b >> 8, fp);
+
+				val0 <<= 2;
+				val1 <<= 2;
+			}
+		}
+	}
+
+	return (0);
+}
+
+static
+void plantronics_mode3_update (plantronics_t *plantronics)
+{
+	unsigned      x, y, i, col;
+	unsigned      val0, val1, val2, val3;
+	unsigned char *mem0, *mem1, *mem2, *mem3, *plane0, *plane1;
+
+	if (plantronics->special & 0x40) {
+		plane0 = plantronics->mem->data;
+		plane1 = plantronics->mem->data + 0x4000;
+	} else {
+		plane0 = plantronics->mem->data + 0x4000;
+		plane1 = plantronics->mem->data;
+	}
+
+	mem0 = plane0;
+	mem1 = plane0 + 8192;
+	mem2 = plane1;
+	mem3 = plane1 + 8192;
+
+	for (y = 0; y < 100; y++) {
+		for (x = 0; x < 80; x++) {
+			val0 = mem0[x];
+			val1 = mem1[x];
+			val2 = mem2[x];
+			val3 = mem3[x];
+
+			for (i = 0; i < 4; i++) {
+				col = ((val0 >> 6) & 3) | ((val2 >> 4) & 0x0c);
+				trm_set_col (plantronics->trm, col, 0);
+				trm_set_pxl (plantronics->trm, 4 * x + i, 2 * y);
+
+				col = ((val1 >> 6) & 3) | ((val3 >> 4) & 0x0c);
+				trm_set_col (plantronics->trm, col, 0);
+				trm_set_pxl (plantronics->trm, 4 * x + i, 2 * y + 1);
+
+				val0 <<= 2;
+				val1 <<= 2;
+				val2 <<= 2;
+				val3 <<= 2;
+			}
+		}
+
+		mem0 += 80;
+		mem1 += 80;
+		mem2 += 80;
+		mem3 += 80;
+	}
+}
+
+void plantronics_mode3_set_uint8 (plantronics_t *plantronics, unsigned long addr, unsigned char val)
+{
+	unsigned      i;
+	unsigned      x, y;
+	unsigned char old, *plane0, *plane1, val0, val1;
+	unsigned      offset;
+
+	old = plantronics->mem->data[addr];
+
+	if (old == val) {
+		return;
+	}
+
+	plantronics->mem->data[addr] = val;
+
+	offset = addr & 0x3FFF;
+	if (offset < 8192) {
+		x = 4 * (offset % 80);
+		y = 2 * (offset / 80);
+	}
+	else {
+		x = 4 * ((offset - 8192) % 80);
+		y = 2 * ((offset - 8192) / 80) + 1;
+	}
+	if (plantronics->special & 0x40) {
+		plane0 = plantronics->mem->data;
+		plane1 = plantronics->mem->data + 0x4000;
+	} else {
+		plane0 = plantronics->mem->data + 0x4000;
+		plane1 = plantronics->mem->data;
+	}
+
+	val0 = plane0[offset];
+	val1 = plane1[offset];
+	for (i = 0; i < 4; i++) {
+		unsigned col;
+
+		col = ((val0 >> 6) & 3) | ((val1 >> 4) & 0x0c);
+		if ((old ^ val) & 0xC0) {
+			trm_set_col (plantronics->trm, col, 0);
+			trm_set_pxl (plantronics->trm, x + i, y);
+		}
+
+		old <<= 2;
+		val <<= 2;
+		val0 <<= 2;
+		val1 <<= 2;
+	}
+}
+
+
+/*****************************************************************************
+ * mode 4 (graphics 620 * 200 * 4)
+ *****************************************************************************/
+
+static
+int plantronics_mode4_screenshot (plantronics_t *plantronics, FILE *fp)
+{
+	unsigned      x, y, i;
+	unsigned      val0, val1, idx;
+	unsigned char *mem0, *mem1, *plane0, *plane1;
+
+	fputs ("P6\n640 200\n255 ", fp);
+
+	if (plantronics->special & 0x40) {
+		plane0 = plantronics->mem->data;
+		plane1 = plantronics->mem->data + 0x4000;
+	} else {
+		plane0 = plantronics->mem->data + 0x4000;
+		plane1 = plantronics->mem->data;
+	}
+
+	for (y = 0; y < 200; y++) {
+		mem0 = plane0 + 80 * (y / 2);
+		mem1 = plane1 + 80 * (y / 2);
+
+		if (y & 1) {
+			mem0 += 8192;
+			mem1 += 8192;
+		}
+
+		for (x = 0; x < 80; x++) {
+			val0 = mem0[x];
+			val1 = mem1[x];
+
+			for (i = 0; i < 8; i++) {
+				idx =	(( val0 >> 7) & 1) | 
+					(((val1 >> 7) & 1) << 1);
+				idx = plantronics->palette[idx];
+				fputc (plantronics_col[idx].r >> 8, fp);
+				fputc (plantronics_col[idx].g >> 8, fp);
+				fputc (plantronics_col[idx].b >> 8, fp);
+
+				val0 <<= 1;
+				val1 <<= 1;
+			}
+		}
+	}
+
+	return (0);
+}
+
+static
+void plantronics_mode4_update (plantronics_t *plantronics)
+{
+	unsigned      x, y, i, col;
+	unsigned      val0, val1, val2, val3;
+	unsigned char *mem0, *mem1, *mem2, *mem3, *plane0, *plane1;
+
+	if (plantronics->special & 0x40) {
+		plane0 = plantronics->mem->data;
+		plane1 = plantronics->mem->data + 0x4000;
+	} else {
+		plane0 = plantronics->mem->data + 0x4000;
+		plane1 = plantronics->mem->data;
+	}
+
+	mem0 = plane0;
+	mem1 = plane0 + 8192;
+	mem2 = plane1;
+	mem3 = plane1 + 8192;
+
+	for (y = 0; y < 100; y++) {
+		for (x = 0; x < 80; x++) {
+			val0 = mem0[x];
+			val1 = mem1[x];
+			val2 = mem2[x];
+			val3 = mem3[x];
+
+			for (i = 0; i < 8; i++) {
+				col = ((val0 >> 7) & 1) | ((val2 >> 6) & 2);
+				trm_set_col (plantronics->trm, plantronics->palette[col], 0);
+				trm_set_pxl (plantronics->trm, 8 * x + i, 2 * y);
+
+				col = ((val1 >> 7) & 1) | ((val3 >> 6) & 2);
+				trm_set_col (plantronics->trm, plantronics->palette[col], 0);
+				trm_set_pxl (plantronics->trm, 8 * x + i, 2 * y + 1);
+
+				val0 <<= 1;
+				val1 <<= 1;
+				val2 <<= 1;
+				val3 <<= 1;
+			}
+		}
+
+		mem0 += 80;
+		mem1 += 80;
+		mem2 += 80;
+		mem3 += 80;
+	}
+}
+
+void plantronics_mode4_set_uint8 (plantronics_t *plantronics, unsigned long addr, unsigned char val)
+{
+	unsigned      i;
+	unsigned      x, y;
+	unsigned char old, *plane0, *plane1, val0, val1;
+	unsigned      offset;
+
+	old = plantronics->mem->data[addr];
+
+	if (old == val) {
+		return;
+	}
+
+	plantronics->mem->data[addr] = val;
+
+	offset = addr & 0x3FFF;
+	if (offset < 8192) {
+		x = 8 * (offset % 80);
+		y = 2 * (offset / 80);
+	}
+	else {
+		x = 8 * ((offset - 8192) % 80);
+		y = 2 * ((offset - 8192) / 80) + 1;
+	}
+	if (plantronics->special & 0x40) {
+		plane0 = plantronics->mem->data;
+		plane1 = plantronics->mem->data + 0x4000;
+	} else {
+		plane0 = plantronics->mem->data + 0x4000;
+		plane1 = plantronics->mem->data;
+	}
+
+	val0 = plane0[offset];
+	val1 = plane1[offset];
+	for (i = 0; i < 8; i++) {
+		unsigned col;
+
+		col = ((val0 >> 7) & 1) | ((val1 >> 6) & 2);
+		if ((old ^ val) & 0x80) {
+			trm_set_col (plantronics->trm, plantronics->palette[col], 0);
+			trm_set_pxl (plantronics->trm, x + i, y);
+		}
+
+		old <<= 1;
+		val <<= 1;
+		val0 <<= 1;
+		val1 <<= 1;
+	}
+}
+
+
+int plantronics_screenshot (plantronics_t *plantronics, FILE *fp, unsigned mode)
+{
+	if ((plantronics->mode == 0) && ((mode == 1) || (mode == 0))) {
+		return (plantronics_mode0_screenshot (plantronics, fp));
+	}
+	else if ((plantronics->mode == 1) && ((mode == 2) || (mode == 0))) {
+		return (plantronics_mode1_screenshot (plantronics, fp));
+	}
+	else if ((plantronics->mode == 2) && ((mode == 2) || (mode == 0))) {
+		return (plantronics_mode2_screenshot (plantronics, fp));
+	}
+	else if ((plantronics->mode == 3) && ((mode == 2) || (mode == 0))) {
+		return (plantronics_mode3_screenshot (plantronics, fp));
+	}
+	else if ((plantronics->mode == 4) && ((mode == 2) || (mode == 0))) {
+		return (plantronics_mode4_screenshot (plantronics, fp));
+	}
+
+	return (1);
+}
+
+
+
+void plantronics_update (plantronics_t *plantronics)
+{
+	switch (plantronics->mode) {
+		case 0:
+			plantronics_mode0_update (plantronics);
+			break;
+
+		case 1:
+			plantronics_mode1_update (plantronics);
+			break;
+
+		case 2:
+			plantronics_mode2_update (plantronics);
+			break;
+
+		case 3:
+			plantronics_mode3_update (plantronics);
+			break;
+
+		case 4:
+			plantronics_mode4_update (plantronics);
+			break;
+	}
+}
+
+void plantronics_set_pos (plantronics_t *plantronics, unsigned pos)
+{
+	plantronics->crtc_pos = pos;
+
+	if (plantronics->mode == 0) {
+		if (pos < plantronics->crtc_ofs) {
+			return;
+		}
+
+		pos -= plantronics->crtc_ofs;
+
+		if (pos >= 2000) {
+			return;
+		}
+
+		trm_set_pos (plantronics->trm, pos % 80, pos / 80);
+	}
+}
+
+void plantronics_set_crs (plantronics_t *plantronics, unsigned y1, unsigned y2)
+{
+	if (plantronics->mode == 0) {
+		if (y1 > 7) {
+			trm_set_crs (plantronics->trm, 0, 0, 0);
+			return;
+		}
+
+		if ((y2 < y1) || (y2 > 7)) {
+			y2 = 7;
+		}
+
+		y1 = (y1 << 5) | (y1 << 2) | (y1 >> 1);
+		y2 = (y2 << 5) | (y2 << 2) | (y2 >> 1);
+
+		trm_set_crs (plantronics->trm, y1, y2, 1);
+	}
+}
+
+void plantronics_set_page_ofs (plantronics_t *plantronics, unsigned ofs)
+{
+	if (plantronics->crtc_ofs == ofs) {
+		return;
+	}
+
+	plantronics->crtc_ofs = ofs;
+
+	if (plantronics->mode == 0) {
+		plantronics_update (plantronics);
+	}
+}
+
+void plantronics_set_palette (plantronics_t *plantronics)
+{
+	unsigned pal, bg;
+	
+	pal = ((plantronics->colreg >> 4) & 3) | (plantronics->modereg & 4);
+	bg  = plantronics->colreg & 0x0F;
+
+	if (pal == plantronics->pal && bg == plantronics->palette[0]) {
+		return;
+	}
+
+	plantronics->pal = pal;
+
+	switch (pal) {
+		case 0:
+			plantronics->palette[0] = bg;
+			plantronics->palette[1] = 3;
+			plantronics->palette[2] = 5;
+			plantronics->palette[3] = 7;
+			break;
+
+		case 1:
+			plantronics->palette[0] = bg;
+			plantronics->palette[1] = 11;
+			plantronics->palette[2] = 13;
+			plantronics->palette[3] = 15;
+			break;
+
+		case 2:
+			plantronics->palette[0] = bg;
+			plantronics->palette[1] = 2;
+			plantronics->palette[2] = 4;
+			plantronics->palette[3] = 6;
+			break;
+
+		case 3:
+			plantronics->palette[0] = bg;
+			plantronics->palette[1] = 10;
+			plantronics->palette[2] = 12;
+			plantronics->palette[3] = 14;
+			break;
+
+		case 4:
+		case 6:
+			plantronics->palette[0] = bg;
+			plantronics->palette[1] = 3;
+			plantronics->palette[2] = 4;
+			plantronics->palette[3] = 7;
+			break;
+	
+		case 5:
+		case 7:
+			plantronics->palette[0] = bg;
+			plantronics->palette[1] = 11;
+			plantronics->palette[2] = 12;
+			plantronics->palette[3] = 15;
+			break;
+	}
+
+	plantronics_update (plantronics);
+}
+
+
+
+void plantronics_set_mode (plantronics_t *plantronics)
+{
+	unsigned newmode, mode;
+
+	mode = plantronics->modereg;
+
+	if ((mode & 0x02) == 0) {
+		newmode = 0;
+	}
+	else if ((mode & 0x10) == 0) {
+		newmode = 1;
+	}
+	else {
+		newmode = 2;
+	}
+	if (newmode != 0 && (plantronics->special & 0x30)) {
+		if (plantronics->special & 0x10) {
+			newmode = 3;
+		}
+		else {
+			newmode = 4;
+		}
+	}
+
+	if (newmode == plantronics->mode) {
+		return;
+	}
+
+	plantronics->mode = newmode;
+
+	switch (newmode) {
+		case 0:
+			trm_set_mode (plantronics->trm, TERM_MODE_TEXT, 80, 25);
+			trm_set_size (plantronics->trm, plantronics->mode_80x25_w, plantronics->mode_80x25_h);
+			break;
+
+		case 1:
+		case 3:
+			trm_set_mode (plantronics->trm, TERM_MODE_GRAPH, 320, 200);
+			trm_set_size (plantronics->trm, plantronics->mode_320x200_w, plantronics->mode_320x200_h);
+			break;
+
+		case 2:
+		case 4:
+			trm_set_mode (plantronics->trm, TERM_MODE_GRAPH, 640, 200);
+			trm_set_size (plantronics->trm, plantronics->mode_640x200_w, plantronics->mode_640x200_h);
+			break;
+	}
+
+	plantronics_update (plantronics);
+}
+
+
+
+void plantronics_set_special (plantronics_t *plantronics, unsigned char spl)
+{
+	if (plantronics->special == spl) {
+		return;
+	}
+/* Depending on what bits change, this may force a mode change */
+	if ((plantronics->special ^ spl) & 0x30) {
+		plantronics->special = spl;
+		plantronics_set_mode(plantronics);
+	}
+/* Or a screen repaint */
+	else if ((plantronics->special ^ spl) & 0x40) {
+		plantronics->special = spl;
+		plantronics_update(plantronics);
+	}
+/* Or nothing */
+	else {
+		plantronics->special = spl;
+	}
+}
+
+
+
+
+void plantronics_mem_set_uint8 (plantronics_t *plantronics, unsigned long addr, unsigned char val)
+{
+	switch (plantronics->mode) {
+		case 0:
+			plantronics_mode0_set_uint8 (plantronics, addr, val);
+			break;
+
+		case 1:
+			plantronics_mode1_set_uint8 (plantronics, addr, val);
+			break;
+
+		case 2:
+			plantronics_mode2_set_uint8 (plantronics, addr, val);
+			break;
+
+		case 3:
+			plantronics_mode3_set_uint8 (plantronics, addr, val);
+			break;
+
+		case 4:
+			plantronics_mode4_set_uint8 (plantronics, addr, val);
+			break;
+	}
+}
+
+void plantronics_mem_set_uint16 (plantronics_t *plantronics, unsigned long addr, unsigned short val)
+{
+	switch (plantronics->mode) {
+		case 0:
+			plantronics_mode0_set_uint16 (plantronics, addr, val);
+			break;
+
+		case 1:
+			plantronics_mode1_set_uint8 (plantronics, addr, val);
+			plantronics_mode1_set_uint8 (plantronics, addr + 1, val >> 8);
+			break;
+
+		case 2:
+			plantronics_mode2_set_uint8 (plantronics, addr, val);
+			plantronics_mode2_set_uint8 (plantronics, addr + 1, val >> 8);
+			break;
+
+		case 3:
+			plantronics_mode3_set_uint8 (plantronics, addr, val);
+			plantronics_mode3_set_uint8 (plantronics, addr + 1, val >> 8);
+			break;
+
+		case 4:
+			plantronics_mode4_set_uint8 (plantronics, addr, val);
+			plantronics_mode4_set_uint8 (plantronics, addr + 1, val >> 8);
+			break;
+	}
+}
+
+void plantronics_crtc_set_reg (plantronics_t *plantronics, unsigned reg, unsigned char val)
+{
+	if (reg > 17) {
+		return;
+	}
+
+	plantronics->crtc_reg[reg] = val;
+
+	switch (reg) {
+		case 0x0a:
+		case 0x0b:
+			plantronics_set_crs (plantronics, plantronics->crtc_reg[0x0a], plantronics->crtc_reg[0x0b]);
+			break;
+
+		case 0x0c:
+			plantronics_set_page_ofs (plantronics, (plantronics->crtc_reg[0x0c] << 8) | val);
+			break;
+
+		case 0x0d:
+			plantronics_set_page_ofs (plantronics, (plantronics->crtc_reg[0x0c] << 8) | val);
+			break;
+
+		case 0x0e:
+/*      plantronics_set_pos (plantronics, (val << 8) | (plantronics->crtc_reg[0x0f] & 0xff)); */
+			break;
+
+		case 0x0f:
+			plantronics_set_pos (plantronics, (plantronics->crtc_reg[0x0e] << 8) | val);
+			break;
+	}
+}
+
+unsigned char plantronics_crtc_get_reg (plantronics_t *plantronics, unsigned reg)
+{
+	if (reg > 15) {
+		return (0xff);
+	}
+
+	return (plantronics->crtc_reg[reg]);
+}
+
+void plantronics_reg_set_uint8 (plantronics_t *plantronics, unsigned long addr, unsigned char val)
+{
+	plantronics->reg->data[addr] = val;
+
+	switch (addr) {
+		case 0x01:
+			plantronics_crtc_set_reg (plantronics, plantronics->reg->data[0], val);
+			break;
+
+		case 0x04:
+			plantronics->modereg = val;
+			plantronics_set_mode (plantronics);
+/* Mode register can affect palette */
+			plantronics_set_palette (plantronics);
+			break;
+
+		case 0x05:
+			plantronics->colreg = val;
+			plantronics_set_palette (plantronics);
+			break;
+
+		case 0x09:
+			plantronics_set_special (plantronics, val);
+			break;
+	}
+}
+
+void plantronics_reg_set_uint16 (plantronics_t *plantronics, unsigned long addr, unsigned short val)
+{
+	plantronics_reg_set_uint8 (plantronics, addr, val & 0xff);
+
+	if ((addr + 1) < plantronics->reg->size) {
+		plantronics_reg_set_uint8 (plantronics, addr + 1, val >> 8);
+	}
+}
+
+unsigned char plantronics_reg_get_uint8 (plantronics_t *plantronics, unsigned long addr)
+{
+	switch (addr) {
+		case 0x00:
+			return (plantronics->reg->data[0]);
+
+		case 0x01:
+			return (plantronics_crtc_get_reg (plantronics, plantronics->reg->data[0]));
+
+		case 0x06:
+			/* p freq: 14.31818 MHz
+				 h freq: 15.750 KHz
+				 v freq: 60 Hz
+				 912 / 14.31818e6 * 1e6 = 63.6952
+				 640 / 14.31818e6 * 1e6 = 44.6984
+				 262 / 15.75e3 * 1e6 = 16634.9206
+				 200 / 15.75e3 * 1e6 = 12698.4127
+			 */
+			if ((plantronics->clkcnt % 16635) < 12699) {
+				plantronics->reg->data[6] &= ~0x08;
+
+				if ((plantronics->clkcnt % 64) < 45) {
+					plantronics->reg->data[6] |= 0x01;
+				}
+				else {
+					plantronics->reg->data[6] &= ~0x01;
+				}
+			}
+			else {
+				plantronics->reg->data[6] |= 0x08;
+				plantronics->reg->data[6] |= 0x01;
+			}
+
+			return (plantronics->reg->data[6]);
+
+		default:
+			return (0xff);
+	}
+}
+
+unsigned short plantronics_reg_get_uint16 (plantronics_t *plantronics, unsigned long addr)
+{
+	unsigned short ret;
+
+	ret = plantronics_reg_get_uint8 (plantronics, addr);
+
+	if ((addr + 1) < plantronics->reg->size) {
+		ret |= plantronics_reg_get_uint8 (plantronics, addr + 1) << 8;
+	}
+
+	return (ret);
+}
diff -u -r -N pce-0.1.7/src/devices/video/plantronics.h pce-new/src/devices/video/plantronics.h
--- pce-0.1.7/src/devices/video/plantronics.h	1970-01-01 01:00:00.000000000 +0100
+++ pce-new/src/devices/video/plantronics.h	2008-10-14 21:06:47.000000000 +0100
@@ -0,0 +1,99 @@
+/*****************************************************************************
+ * pce                                                                       *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * File name:     src/devices/video/platronics.h                             *
+ * Created:       2003-04-18 by Hampa Hug <hampa@hampa.ch>                   *
+ * Last modified: 2008-10-12 by John Elliott <jce@seasip.demon.co.uk>        *
+ * Copyright:     (C) 2003-2005 Hampa Hug <hampa@hampa.ch>                   *
+ *                (C) 2008 John Elliott <jce@seasip.demon.co.uk>             *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * This program is free software. You can redistribute it and / or modify it *
+ * under the terms of the GNU General Public License version 2 as  published *
+ * by the Free Software Foundation.                                          *
+ *                                                                           *
+ * This program is distributed in the hope  that  it  will  be  useful,  but *
+ * WITHOUT  ANY   WARRANTY,   without   even   the   implied   warranty   of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  General *
+ * Public License for more details.                                          *
+ *****************************************************************************/
+
+/* $Id: plantronics.h 619 2005-12-28 21:42:53Z hampa $ */
+
+
+#ifndef PCE_PLANTRONICS_H
+#define PCE_PLANTRONICS_H 1
+
+
+#include <libini/libini.h>
+#include <terminal/terminal.h>
+#include <devices/video/video.h>
+
+
+typedef struct {
+	video_t       vid;
+
+	mem_blk_t     *mem;
+	mem_blk_t     *reg;
+
+	unsigned      mode_80x25_w;
+	unsigned      mode_80x25_h;
+	unsigned      mode_320x200_w;
+	unsigned      mode_320x200_h;
+	unsigned      mode_640x200_w;
+	unsigned      mode_640x200_h;
+
+	unsigned char crtc_reg[18];
+
+	unsigned      crtc_pos;
+	unsigned      crtc_ofs;
+
+	unsigned long clkcnt;
+
+	unsigned char pal;
+	unsigned char palette[4];
+
+	unsigned char modereg;
+	unsigned char colreg;
+	unsigned char special;
+
+	int           crs_on;
+
+	unsigned      mode;
+
+	terminal_t    *trm;
+} plantronics_t;
+
+
+video_t *plantronics_new (terminal_t *trm, ini_sct_t *sct);
+
+void plantronics_del (plantronics_t *plantronics);
+
+void plantronics_clock (plantronics_t *plantronics, unsigned long cnt);
+
+void plantronics_prt_state (plantronics_t *plantronics, FILE *fp);
+
+int plantronics_dump (plantronics_t *plantronics, FILE *fp);
+
+mem_blk_t *plantronics_get_mem (plantronics_t *plantronics);
+mem_blk_t *plantronics_get_reg (plantronics_t *plantronics);
+
+int plantronics_screenshot (plantronics_t *plantronics, FILE *fp, unsigned mode);
+
+void plantronics_update (plantronics_t *plantronics);
+
+void plantronics_set_pos (plantronics_t *plantronics, unsigned pos);
+
+void plantronics_mem_set_uint8 (plantronics_t *plantronics, unsigned long addr, unsigned char val);
+void plantronics_mem_set_uint16 (plantronics_t *plantronics, unsigned long addr, unsigned short val);
+
+void plantronics_reg_set_uint8 (plantronics_t *plantronics, unsigned long addr, unsigned char val);
+void plantronics_reg_set_uint16 (plantronics_t *plantronics, unsigned long addr, unsigned short val);
+unsigned char plantronics_reg_get_uint8 (plantronics_t *plantronics, unsigned long addr);
+unsigned short plantronics_reg_get_uint16 (plantronics_t *plantronics, unsigned long addr);
+
+
+#endif
diff -u -r -N pce-0.1.7/src/devices/video/video.h pce-new/src/devices/video/video.h
--- pce-0.1.7/src/devices/video/video.h	2005-12-28 21:42:53.000000000 +0000
+++ pce-new/src/devices/video/video.h	2008-10-14 21:48:38.000000000 +0100
@@ -6,7 +6,9 @@
  * File name:     src/devices/video.h                                        *
  * Created:       2003-08-30 by Hampa Hug <hampa@hampa.ch>                   *
  * Last modified: 2004-08-01 by Hampa Hug <hampa@hampa.ch>                   *
+ * Last modified: 2008-10-13 by John Elliott <jce@seasip.demon.co.uk>        *
  * Copyright:     (C) 2003-2004 Hampa Hug <hampa@hampa.ch>                   *
+ *                (C) 2008 John Elliott <jce@seasip.demon.co.uk>             *
  *****************************************************************************/
 
 /*****************************************************************************
@@ -37,6 +39,7 @@
 #define PCE_VIDEO_CGA  2
 #define PCE_VIDEO_HGC  3
 #define PCE_VIDEO_EGA  4
+#define PCE_VIDEO_PLANTRONICS 5
 
 
 typedef void (*pce_video_del_f) (void *ext);
diff -u -r -N pce-0.1.7/src/devices/video/wy700.c pce-new/src/devices/video/wy700.c
--- pce-0.1.7/src/devices/video/wy700.c	1970-01-01 01:00:00.000000000 +0100
+++ pce-new/src/devices/video/wy700.c	2008-10-15 19:12:44.000000000 +0100
@@ -0,0 +1,1118 @@
+/*****************************************************************************
+ * pce                                                                       *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * File name:     src/devices/video/wy700.c                                  *
+ * Created:       2003-04-18 by Hampa Hug <hampa@hampa.ch>                   *
+ * Last modified: 2008-10-13 by John Elliott <jce@seasip.demon.co.uk>        *
+ * Copyright:     (C) 2003-2005 Hampa Hug <hampa@hampa.ch>                   *
+ *                (C) 2008 John Elliott <jce@seasip.demon.co.uk>             *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * This program is free software. You can redistribute it and / or modify it *
+ * under the terms of the GNU General Public License version 2 as  published *
+ * by the Free Software Foundation.                                          *
+ *                                                                           *
+ * This program is distributed in the hope  that  it  will  be  useful,  but *
+ * WITHOUT  ANY   WARRANTY,   without   even   the   implied   warranty   of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  General *
+ * Public License for more details.                                          *
+ *****************************************************************************/
+
+/* $Id: wy700.c 619 2005-12-28 21:42:53Z hampa $ */
+
+
+#include <stdio.h>
+
+#include <lib/log.h>
+#include <lib/hexdump.h>
+
+#include "wy700.h"
+
+
+static
+struct {  unsigned short r, g, b; } wy700_col[16] = {
+	{ 0x0000, 0x0000, 0x0000 },
+	{ 0x0a0a, 0x0a0a, 0xb9b9 },
+	{ 0x0a0a, 0xc3c3, 0x0a0a },
+	{ 0x1414, 0xa0a0, 0xa0a0 },
+	{ 0xa7a7, 0x0a0a, 0x0a0a },
+	{ 0xa7a7, 0x0000, 0xa7a7 },
+	{ 0xa5a5, 0xa5a5, 0x2828 },
+	{ 0xc5c5, 0xc5c5, 0xc5c5 },
+	{ 0x6464, 0x6464, 0x6464 },
+	{ 0x0a0a, 0x0a0a, 0xffff },
+	{ 0x0a0a, 0xffff, 0x0a0a },
+	{ 0x0a0a, 0xffff, 0xffff },
+	{ 0xffff, 0x0a0a, 0x0a0a },
+	{ 0xffff, 0x0a0a, 0xffff },
+	{ 0xffff, 0xffff, 0x0000 },
+	{ 0xffff, 0xffff, 0xffff }
+};
+
+
+video_t *wy700_new (terminal_t *trm, ini_sct_t *sct)
+{
+	unsigned      i;
+	unsigned long iobase, membase, memsize;
+	unsigned      w, h;
+	wy700_t         *wy700;
+
+	wy700 = (wy700_t *) malloc (sizeof (wy700_t));
+	if (wy700 == NULL) {
+		return (NULL);
+	}
+
+	pce_video_init (&wy700->vid);
+
+	wy700->vid.ext = wy700;
+	wy700->vid.del = (pce_video_del_f) wy700_del;
+	wy700->vid.get_mem = (pce_video_get_mem_f) wy700_get_mem;
+	wy700->vid.get_reg = (pce_video_get_reg_f) wy700_get_reg;
+	wy700->vid.prt_state = (pce_video_prt_state_f) wy700_prt_state;
+	wy700->vid.update = (pce_video_update_f) wy700_update;
+	wy700->vid.dump = (pce_video_dump_f) wy700_dump;
+	wy700->vid.screenshot = (pce_video_screenshot_f) wy700_screenshot;
+	wy700->vid.clock = (pce_video_clock_f) wy700_clock;
+
+	for (i = 0; i < 16; i++) {
+		wy700->crtc_reg[i] = 0;
+	}
+
+	w = ini_get_lng_def (sct, "w", 1280);
+	h = ini_get_lng_def (sct, "h", 800);
+
+	wy700->mode_80x25_w = ini_get_lng_def (sct, "mode_80x25_w", w);
+	wy700->mode_80x25_h = ini_get_lng_def (sct, "mode_80x25_h", h);
+	wy700->mode_320x200_w = ini_get_lng_def (sct, "mode_320x200_w", w);
+	wy700->mode_320x200_h = ini_get_lng_def (sct, "mode_320x200_h", h);
+	wy700->mode_640x200_w = ini_get_lng_def (sct, "mode_640x200_w", w);
+	wy700->mode_640x200_h = ini_get_lng_def (sct, "mode_640x200_h", h);
+	wy700->mode_1280x800_w = ini_get_lng_def (sct, "mode_1280x800_w", w);
+	wy700->mode_1280x800_h = ini_get_lng_def (sct, "mode_1280x800_h", h);
+
+	iobase = ini_get_lng_def (sct, "io", 0x3d4L);
+	membase = ini_get_lng_def (sct, "membase", 0xa0000L);
+	memsize = ini_get_lng_def (sct, "memsize", 131072L);
+
+	if (memsize < 131072) {
+		memsize = 131072;
+	}
+
+	pce_log (MSG_INF, "video:\tWY700 io=0x%04lx membase=0x%05lx memsize=0x%05lx\n",
+		iobase, membase, memsize
+	);
+
+	wy700->mem = mem_blk_new (membase, memsize, 1);
+	wy700->mem->ext = wy700;
+	wy700->mem->set_uint8 = (mem_set_uint8_f) &wy700_mem_set_uint8;
+	wy700->mem->set_uint16 = (mem_set_uint16_f) &wy700_mem_set_uint16;
+	wy700->mem->get_uint8 = (mem_get_uint8_f) &wy700_mem_get_uint8;
+	wy700->mem->get_uint16 = (mem_get_uint16_f) &wy700_mem_get_uint16;
+	mem_blk_clear (wy700->mem, 0x00);
+
+	wy700->reg = mem_blk_new (iobase, 16, 1);
+	wy700->reg->ext = wy700;
+	wy700->reg->set_uint8 = (mem_set_uint8_f) &wy700_reg_set_uint8;
+	wy700->reg->set_uint16 = (mem_set_uint16_f) &wy700_reg_set_uint16;
+	wy700->reg->get_uint8 = (mem_get_uint8_f) &wy700_reg_get_uint8;
+	wy700->reg->get_uint16 = (mem_get_uint16_f) &wy700_reg_get_uint16;
+	mem_blk_clear (wy700->reg, 0x00);
+
+	wy700->trm = trm;
+
+	wy700->crtc_pos = 0;
+	wy700->crtc_ofs = 0;
+
+	wy700->clkcnt = 0;
+
+	wy700->crs_on = 1;
+
+	wy700->pal = 0;
+	wy700->palette[0] = 0;
+	wy700->palette[1] = 11;
+	wy700->palette[2] = 13;
+	wy700->palette[3] = 15;
+	wy700->modereg = 0;
+	wy700->colreg = 0;
+	wy700->control = 0;
+
+	wy700->mode = 0;
+	trm_set_mode (trm, TERM_MODE_TEXT, 80, 25);
+	trm_set_size (trm, wy700->mode_80x25_w, wy700->mode_80x25_h);
+
+	return (&wy700->vid);
+}
+
+void wy700_del (wy700_t *wy700)
+{
+	if (wy700 != NULL) {
+		mem_blk_del (wy700->mem);
+		mem_blk_del (wy700->reg);
+		free (wy700);
+	}
+}
+
+void wy700_clock (wy700_t *wy700, unsigned long cnt)
+{
+	wy700->clkcnt += cnt;
+}
+
+void wy700_prt_state (wy700_t *wy700, FILE *fp)
+{
+	unsigned i;
+	unsigned x, y;
+
+	if (wy700->crtc_pos < wy700->crtc_ofs) {
+		x = 0;
+		y = 0;
+	}
+	else {
+		x = (wy700->crtc_pos - wy700->crtc_ofs) % 80;
+		y = (wy700->crtc_pos - wy700->crtc_ofs) / 80;
+	}
+
+	fprintf (fp, "WY700: MODE=%u  OFS=%04X  POS=%04X[%u/%u]  CRS=%s  BG=%02X  PAL=%u\n",
+		wy700->mode, wy700->crtc_ofs, wy700->crtc_pos, x, y,
+		(wy700->crs_on) ? "ON" : "OFF",
+		wy700->reg->data[5] & 0x0f, (wy700->reg->data[5] >> 5) & 1
+	);
+
+	fprintf (fp, "REG: 3D8=%02X  3D9=%02X  3DA=%02X  PAL=%u:[%02X %02X %02X %02X]\n",
+		wy700->reg->data[4], wy700->reg->data[5], wy700->reg->data[6],
+		wy700->pal, wy700->palette[0], wy700->palette[1], wy700->palette[2], wy700->palette[3]
+	);
+
+	fprintf (fp, "CRTC=[%02X", wy700->crtc_reg[0]);
+	for (i = 1; i < 18; i++) {
+		if ((i & 7) == 0) {
+			fputs ("-", fp);
+		}
+		else {
+			fputs (" ", fp);
+		}
+		fprintf (fp, "%02X", wy700->crtc_reg[i]);
+	}
+	fputs ("]\n", fp);
+
+	fflush (fp);
+}
+
+int wy700_dump (wy700_t *wy700, FILE *fp)
+{
+	fprintf (fp, "# WY700 dump\n");
+
+	fprintf (fp, "\n# REGS:\n");
+	pce_dump_hex (fp,
+		mem_blk_get_data (wy700->reg),
+		mem_blk_get_size (wy700->reg),
+		mem_blk_get_addr (wy700->reg),
+		16, "# ", 0
+	);
+
+	fprintf (fp, "\n# CRTC:\n");
+	pce_dump_hex (fp, wy700->crtc_reg, 18, 0, 16, "# ", 0);
+
+	fputs ("\n\n# RAM:\n", fp);
+	pce_dump_hex (fp,
+		mem_blk_get_data (wy700->mem),
+		mem_blk_get_size (wy700->mem),
+		mem_blk_get_addr (wy700->mem),
+		16, "", 1
+	);
+
+	return (0);
+}
+
+mem_blk_t *wy700_get_mem (wy700_t *wy700)
+{
+	return (wy700->mem);
+}
+
+mem_blk_t *wy700_get_reg (wy700_t *wy700)
+{
+	return (wy700->reg);
+}
+
+
+/*****************************************************************************
+ * mode 0 (text 80 * 25)
+ *****************************************************************************/
+
+static
+int wy700_mode0_screenshot (wy700_t *wy700, FILE *fp)
+{
+	unsigned i;
+	unsigned x, y;
+
+	i = (wy700->crtc_ofs << 1) & 0x3fff;
+
+	for (y = 0; y < 25; y++) {
+		for (x = 0; x < 80; x++) {
+			fputc (wy700->mem->data[i], fp);
+			i = (i + 2) & 0x7fff;
+		}
+
+		fputs ("\n", fp);
+	}
+
+	return (0);
+}
+
+static
+void wy700_mode0_update (wy700_t *wy700)
+{
+	unsigned i;
+	unsigned x, y;
+	unsigned fg, bg;
+
+	i = (wy700->crtc_ofs << 1) & 0x3fff;
+
+	for (y = 0; y < 25; y++) {
+		for (x = 0; x < 80; x++) {
+			fg = wy700->mem->data[i + 1] & 0x0f;
+			bg = (wy700->mem->data[i + 1] & 0xf0) >> 4;
+
+			trm_set_col (wy700->trm, fg, bg);
+			trm_set_chr (wy700->trm, x, y, wy700->mem->data[i]);
+
+			i = (i + 2) & 0x3fff;
+		}
+	}
+}
+
+void wy700_mode0_set_uint8 (wy700_t *wy700, unsigned long addr, unsigned char val)
+{
+	unsigned      x, y;
+	unsigned char c, a;
+
+	if (wy700->mem->data[addr] == val) {
+		return;
+	}
+
+	wy700->mem->data[addr] = val;
+
+	if (addr & 1) {
+		c = wy700->mem->data[addr - 1];
+		a = val;
+	}
+	else {
+		c = val;
+		a = wy700->mem->data[addr + 1];
+	}
+
+	if (addr < (wy700->crtc_ofs << 1)) {
+		return;
+	}
+
+	addr -= (wy700->crtc_ofs << 1);
+
+	if (addr >= 4000) {
+		return;
+	}
+
+	x = (addr >> 1) % 80;
+	y = (addr >> 1) / 80;
+
+	trm_set_col (wy700->trm, a & 0x0f, (a & 0xf0) >> 4);
+	trm_set_chr (wy700->trm, x, y, c);
+}
+
+void wy700_mode0_set_uint16 (wy700_t *wy700, unsigned long addr, unsigned short val)
+{
+	unsigned      x, y;
+	unsigned char c, a;
+
+	if (addr & 1) {
+		wy700_mem_set_uint8 (wy700, addr, val & 0xff);
+		wy700_mem_set_uint8 (wy700, addr + 1, (val >> 8) & 0xff);
+		return;
+	}
+
+	c = val & 0xff;
+	a = (val >> 8) & 0xff;
+
+	if ((wy700->mem->data[addr] == c) && (wy700->mem->data[addr + 1] == a)) {
+		return;
+	}
+
+	wy700->mem->data[addr] = c;
+	wy700->mem->data[addr + 1] = a;
+
+	if (addr < (wy700->crtc_ofs << 1)) {
+		return;
+	}
+
+	addr -= (wy700->crtc_ofs << 1);
+
+	if (addr >= 4000) {
+		return;
+	}
+
+	x = (addr >> 1) % 80;
+	y = (addr >> 1) / 80;
+
+	trm_set_col (wy700->trm, a & 0x0f, (a & 0xf0) >> 4);
+	trm_set_chr (wy700->trm, x, y, c);
+}
+
+
+/*****************************************************************************
+ * mode 1 (graphics 320 * 200 * 4)
+ *****************************************************************************/
+
+static
+int wy700_mode1_screenshot (wy700_t *wy700, FILE *fp)
+{
+	unsigned      x, y, i;
+	unsigned      val, idx;
+	unsigned char *mem;
+
+	fputs ("P6\n320 200\n255 ", fp);
+
+	for (y = 0; y < 200; y++) {
+		mem = wy700->mem->data + 80 * (y / 2);
+
+		if (y & 1) {
+			mem += 8192;
+		}
+
+		for (x = 0; x < 80; x++) {
+			val = mem[x];
+
+			for (i = 0; i < 4; i++) {
+				idx = (val >> 6) & 0x03;
+				idx = wy700->palette[idx];
+				fputc (wy700_col[idx].r >> 8, fp);
+				fputc (wy700_col[idx].g >> 8, fp);
+				fputc (wy700_col[idx].b >> 8, fp);
+
+				val <<= 2;
+			}
+		}
+	}
+
+	return (0);
+}
+
+static
+void wy700_mode1_update (wy700_t *wy700)
+{
+	unsigned      x, y, i;
+	unsigned      val0, val1;
+	unsigned char *mem0, *mem1;
+
+	mem0 = wy700->mem->data;
+	mem1 = wy700->mem->data + 8192;
+
+	for (y = 0; y < 100; y++) {
+		for (x = 0; x < 80; x++) {
+			val0 = mem0[x];
+			val1 = mem1[x];
+
+			for (i = 0; i < 4; i++) {
+				trm_set_col (wy700->trm, wy700->palette[(val0 >> 6) & 0x03], 0);
+				trm_set_pxl (wy700->trm, 4 * x + i, 2 * y);
+
+				trm_set_col (wy700->trm, wy700->palette[(val1 >> 6) & 0x03], 0);
+				trm_set_pxl (wy700->trm, 4 * x + i, 2 * y + 1);
+
+				val0 <<= 2;
+				val1 <<= 2;
+			}
+		}
+
+		mem0 += 80;
+		mem1 += 80;
+	}
+}
+
+void wy700_mode1_set_uint8 (wy700_t *wy700, unsigned long addr, unsigned char val)
+{
+	unsigned      i;
+	unsigned      x, y;
+	unsigned char old;
+
+	old = wy700->mem->data[addr];
+
+	if (old == val) {
+		return;
+	}
+
+	wy700->mem->data[addr] = val;
+
+	if (addr < 8192) {
+		x = 4 * (addr % 80);
+		y = 2 * (addr / 80);
+	}
+	else {
+		x = 4 * ((addr - 8192) % 80);
+		y = 2 * ((addr - 8192) / 80) + 1;
+	}
+
+	if (y >= 200) {
+		return;
+	}
+
+	for (i = 0; i < 4; i++) {
+		unsigned col;
+
+		if ((old ^ val) & 0xc0) {
+			col = (val >> 6) & 0x03;
+			trm_set_col (wy700->trm, wy700->palette[col], 0);
+
+			trm_set_pxl (wy700->trm, x + i, y);
+		}
+
+		old <<= 2;
+		val <<= 2;
+	}
+}
+
+
+/*****************************************************************************
+ * mode 2 (graphics 620 * 200 * 2)
+ *****************************************************************************/
+
+static
+int wy700_mode2_screenshot (wy700_t *wy700, FILE *fp)
+{
+	unsigned      x, y, i;
+	unsigned      val, col;
+	unsigned char *mem;
+
+	fputs ("P6\n640 200\n255 ", fp);
+
+	col = wy700->palette[0];
+	for (y = 0; y < 200; y++) {
+		mem = wy700->mem->data + 80 * (y / 2);
+
+		if (y & 1) {
+			mem += 8192;
+		}
+
+		for (x = 0; x < 80; x++) {
+			val = mem[x];
+
+			for (i = 0; i < 8; i++) {
+				if (val & (0x80 >> i)) {
+					fputc (wy700_col[col].r >> 8, fp);
+					fputc (wy700_col[col].g >> 8, fp);
+					fputc (wy700_col[col].b >> 8, fp);
+				}
+				else {
+					fputc (0x00, fp);
+					fputc (0x00, fp);
+					fputc (0x00, fp);
+				}
+			}
+		}
+	}
+
+	return (0);
+}
+
+static
+void wy700_mode2_update (wy700_t *wy700)
+{
+	unsigned      x, y, i;
+	unsigned      val0, val1;
+	unsigned char *mem0, *mem1;
+
+	mem0 = wy700->mem->data;
+	mem1 = wy700->mem->data + 8192;
+
+	for (y = 0; y < 100; y++) {
+		for (x = 0; x < 80; x++) {
+			val0 = mem0[x];
+			val1 = mem1[x];
+
+			for (i = 0; i < 8; i++) {
+				trm_set_col (wy700->trm, (val0 & 0x80) ? wy700->palette[0] : 0, 0);
+				trm_set_pxl (wy700->trm, 8 * x + i, 2 * y);
+
+				trm_set_col (wy700->trm, (val1 & 0x80) ? wy700->palette[0] : 0, 0);
+				trm_set_pxl (wy700->trm, 8 * x + i, 2 * y + 1);
+
+				val0 <<= 1;
+				val1 <<= 1;
+			}
+		}
+
+		mem0 += 80;
+		mem1 += 80;
+	}
+}
+
+void wy700_mode2_set_uint8 (wy700_t *wy700, unsigned long addr, unsigned char val)
+{
+	unsigned      i;
+	unsigned      x, y;
+	unsigned char old;
+
+	old = wy700->mem->data[addr];
+
+	if (old == val) {
+		return;
+	}
+
+	wy700->mem->data[addr] = val;
+
+	if (addr < 8192) {
+		x = 8 * (addr % 80);
+		y = 2 * (addr / 80);
+	}
+	else {
+		x = 8 * ((addr - 8192) % 80);
+		y = 2 * ((addr - 8192) / 80) + 1;
+	}
+
+	for (i = 0; i < 8; i++) {
+		unsigned col;
+
+		if ((old ^ val) & 0x80) {
+			col = (val >> 7) & 0x01;
+			trm_set_col (wy700->trm, col ? wy700->palette[0] : 0, 0);
+			trm_set_pxl (wy700->trm, x + i, y);
+		}
+
+		old <<= 1;
+		val <<= 1;
+	}
+}
+
+/*****************************************************************************
+ * mode 3 (graphics 1280 * 800 * 2)
+ *****************************************************************************/
+
+static
+int wy700_mode3_screenshot (wy700_t *wy700, FILE *fp)
+{
+	unsigned      x, y, i;
+	unsigned      val, col;
+	unsigned char *mem;
+
+	fputs ("P6\n1280 800\n255 ", fp);
+
+	col = 15; //wy700->palette[0];
+	for (y = 0; y < 800; y++) {
+		mem = wy700->mem->data + 160 * (y / 2);
+
+		if (y & 1) {
+			mem += 0x10000L;
+		}
+
+		for (x = 0; x < 160; x++) {
+			val = mem[x];
+
+			for (i = 0; i < 8; i++) {
+				if (val & (0x80 >> i)) {
+					fputc (wy700_col[col].r >> 8, fp);
+					fputc (wy700_col[col].g >> 8, fp);
+					fputc (wy700_col[col].b >> 8, fp);
+				}
+				else {
+					fputc (0x00, fp);
+					fputc (0x00, fp);
+					fputc (0x00, fp);
+				}
+			}
+		}
+	}
+
+	return (0);
+}
+
+static
+void wy700_mode3_update (wy700_t *wy700)
+{
+	unsigned      x, y, i;
+	unsigned      val0, val1;
+	unsigned char *mem0, *mem1;
+
+	mem0 = wy700->mem->data;
+	mem1 = wy700->mem->data + 0x10000L;
+
+	for (y = 0; y < 400; y++) {
+		for (x = 0; x < 160; x++) {
+			val0 = mem0[x];
+			val1 = mem1[x];
+
+			for (i = 0; i < 8; i++) {
+				trm_set_col (wy700->trm, (val0 & 0x80) ? 15/*wy700->palette[0]*/ : 0, 0);
+				trm_set_pxl (wy700->trm, 8 * x + i, 2 * y);
+
+				trm_set_col (wy700->trm, (val1 & 0x80) ? 15/*wy700->palette[0]*/ : 0, 0);
+				trm_set_pxl (wy700->trm, 8 * x + i, 2 * y + 1);
+
+				val0 <<= 1;
+				val1 <<= 1;
+			}
+		}
+
+		mem0 += 160;
+		mem1 += 160;
+	}
+}
+
+/* XXX The mapping of read/write like this is sheer guesswork. */
+unsigned char wy700_mode3_get_uint8(wy700_t *wy700, unsigned long addr)
+{
+	addr &= 0xFFFF;
+	if (wy700->control & 1) {
+		addr += 0x10000L;
+	}
+
+	return wy700->mem->data[addr];
+}
+
+void wy700_mode3_set_uint8 (wy700_t *wy700, unsigned long addr, unsigned char val)
+{
+	unsigned      i;
+	unsigned      x, y;
+	unsigned char old;
+
+	addr &= 0xFFFF;
+	if (wy700->control & 2) {
+		addr += 0x10000L;
+	}
+
+	old = wy700->mem->data[addr];
+
+	if (old == val) {
+		return;
+	}
+
+	wy700->mem->data[addr] = val;
+
+	if (addr < 0x10000L) {
+		x = 8 * (addr % 160);
+		y = 2 * (addr / 160);
+	}
+	else {
+		x = 8 * ((addr - 0x10000L) % 160);
+		y = 2 * ((addr - 0x10000L) / 160) + 1;
+	}
+
+	for (i = 0; i < 8; i++) {
+		unsigned col;
+
+		if ((old ^ val) & 0x80) {
+			col = (val >> 7) & 0x01;
+			trm_set_col (wy700->trm, col ? 15 /*wy700->palette[0]*/ : 0, 0);
+			trm_set_pxl (wy700->trm, x + i, y);
+		}
+
+		old <<= 1;
+		val <<= 1;
+	}
+}
+
+
+
+
+int wy700_screenshot (wy700_t *wy700, FILE *fp, unsigned mode)
+{
+	if ((wy700->mode == 0) && ((mode == 1) || (mode == 0))) {
+		return (wy700_mode0_screenshot (wy700, fp));
+	}
+	else if ((wy700->mode == 1) && ((mode == 2) || (mode == 0))) {
+		return (wy700_mode1_screenshot (wy700, fp));
+	}
+	else if ((wy700->mode == 2) && ((mode == 2) || (mode == 0))) {
+		return (wy700_mode2_screenshot (wy700, fp));
+	}
+	else if ((wy700->mode == 3) && ((mode == 2) || (mode == 0))) {
+		return (wy700_mode3_screenshot (wy700, fp));
+	}
+
+	return (1);
+}
+
+void wy700_update (wy700_t *wy700)
+{
+	switch (wy700->mode) {
+		case 0:
+			wy700_mode0_update (wy700);
+			break;
+
+		case 1:
+			wy700_mode1_update (wy700);
+			break;
+
+		case 2:
+			wy700_mode2_update (wy700);
+			break;
+
+		case 3:
+			wy700_mode3_update (wy700);
+			break;
+	}
+}
+
+void wy700_set_pos (wy700_t *wy700, unsigned pos)
+{
+	wy700->crtc_pos = pos;
+
+	if (wy700->mode == 0) {
+		if (pos < wy700->crtc_ofs) {
+			return;
+		}
+
+		pos -= wy700->crtc_ofs;
+
+		if (pos >= 2000) {
+			return;
+		}
+
+		trm_set_pos (wy700->trm, pos % 80, pos / 80);
+	}
+}
+
+void wy700_set_crs (wy700_t *wy700, unsigned y1, unsigned y2)
+{
+	if (wy700->mode == 0) {
+		if (y1 > 7) {
+			trm_set_crs (wy700->trm, 0, 0, 0);
+			return;
+		}
+
+		if ((y2 < y1) || (y2 > 7)) {
+			y2 = 7;
+		}
+
+		y1 = (y1 << 5) | (y1 << 2) | (y1 >> 1);
+		y2 = (y2 << 5) | (y2 << 2) | (y2 >> 1);
+
+		trm_set_crs (wy700->trm, y1, y2, 1);
+	}
+}
+
+void wy700_set_page_ofs (wy700_t *wy700, unsigned ofs)
+{
+	if (wy700->crtc_ofs == ofs) {
+		return;
+	}
+
+	wy700->crtc_ofs = ofs;
+
+	if (wy700->mode == 0) {
+		wy700_update (wy700);
+	}
+}
+
+void wy700_set_palette (wy700_t *wy700)
+{
+	unsigned pal, bg;
+	
+	pal = ((wy700->colreg >> 4) & 3) | (wy700->modereg & 4);
+	bg  = wy700->colreg & 0x0F;
+
+	if (pal == wy700->pal && bg == wy700->palette[0]) {
+		return;
+	}
+
+	wy700->pal = pal;
+
+	switch (pal) {
+		case 0:
+			wy700->palette[0] = bg;
+			wy700->palette[1] = 3;
+			wy700->palette[2] = 5;
+			wy700->palette[3] = 7;
+			break;
+
+		case 1:
+			wy700->palette[0] = bg;
+			wy700->palette[1] = 11;
+			wy700->palette[2] = 13;
+			wy700->palette[3] = 15;
+			break;
+
+		case 2:
+			wy700->palette[0] = bg;
+			wy700->palette[1] = 2;
+			wy700->palette[2] = 4;
+			wy700->palette[3] = 6;
+			break;
+
+		case 3:
+			wy700->palette[0] = bg;
+			wy700->palette[1] = 10;
+			wy700->palette[2] = 12;
+			wy700->palette[3] = 14;
+			break;
+
+		case 4:
+		case 6:
+			wy700->palette[0] = bg;
+			wy700->palette[1] = 3;
+			wy700->palette[2] = 4;
+			wy700->palette[3] = 7;
+			break;
+	
+		case 5:
+		case 7:
+			wy700->palette[0] = bg;
+			wy700->palette[1] = 11;
+			wy700->palette[2] = 12;
+			wy700->palette[3] = 15;
+			break;
+	}
+
+	wy700_update (wy700);
+}
+
+void wy700_set_mode (wy700_t *wy700)
+{
+	unsigned newmode, mode;
+
+	mode = wy700->modereg;
+
+	if ((mode & 0x02) == 0) {
+		newmode = 0;
+	}
+	else if ((mode & 0x10) == 0) {
+		newmode = 1;
+	}
+	else {
+		newmode = 2;
+	}
+	if (wy700->control & 8)
+	{
+		newmode = 3;	/* 1280x800 mode */
+	}
+
+	if (newmode == wy700->mode) {
+		return;
+	}
+
+	wy700->mode = newmode;
+
+	switch (newmode) {
+		case 0:
+			trm_set_mode (wy700->trm, TERM_MODE_TEXT, 80, 25);
+			trm_set_size (wy700->trm, wy700->mode_80x25_w, wy700->mode_80x25_h);
+			break;
+
+		case 1:
+			trm_set_mode (wy700->trm, TERM_MODE_GRAPH, 320, 200);
+			trm_set_size (wy700->trm, wy700->mode_320x200_w, wy700->mode_320x200_h);
+			break;
+
+		case 2:
+			trm_set_mode (wy700->trm, TERM_MODE_GRAPH, 640, 200);
+			trm_set_size (wy700->trm, wy700->mode_640x200_w, wy700->mode_640x200_h);
+			break;
+
+		case 3:
+			trm_set_mode (wy700->trm, TERM_MODE_GRAPH, 1280, 800);
+			trm_set_size (wy700->trm, wy700->mode_1280x800_w, wy700->mode_1280x800_h);
+			break;
+	}
+
+	wy700_update (wy700);
+}
+
+
+unsigned char wy700_mem_get_uint8 (wy700_t *wy700, unsigned long addr)
+{
+	switch (wy700->mode) {
+		case 0:
+		case 1:
+		case 2:
+			return wy700->mem->data[addr & 0x3FFF];
+		case 3:	
+			return wy700_mode3_get_uint8 (wy700, addr & 0xFFFF);
+	}
+}
+
+unsigned short wy700_mem_get_uint16 (wy700_t *wy700, unsigned long addr)
+{
+	unsigned short l = wy700_mem_get_uint8(wy700, addr);
+	unsigned short h = wy700_mem_get_uint8(wy700, addr + 1);
+	return (h << 8) | l;
+}
+
+void wy700_mem_set_uint8 (wy700_t *wy700, unsigned long addr, unsigned char val)
+{
+	switch (wy700->mode) {
+		case 0:
+			wy700_mode0_set_uint8 (wy700, addr & 0x3FFF, val);
+			break;
+
+		case 1:
+			wy700_mode1_set_uint8 (wy700, addr & 0x3FFF, val);
+			break;
+
+		case 2:
+			wy700_mode2_set_uint8 (wy700, addr & 0x3FFF, val);
+			break;
+
+		case 3:
+			wy700_mode3_set_uint8 (wy700, addr & 0xFFFF, val);
+			break;
+	}
+}
+
+void wy700_mem_set_uint16 (wy700_t *wy700, unsigned long addr, unsigned short val)
+{
+	switch (wy700->mode) {
+		case 0:
+			wy700_mode0_set_uint16 (wy700, addr & 0x3FFF, val);
+			break;
+
+		case 1:
+			wy700_mode1_set_uint8 (wy700, addr & 0x3FFF, val);
+			wy700_mode1_set_uint8 (wy700, (addr + 1) & 0x3FFF, val >> 8);
+			break;
+
+		case 2:
+			wy700_mode2_set_uint8 (wy700, addr & 0x3FFF, val);
+			wy700_mode2_set_uint8 (wy700, (addr + 1) & 0x3FFF, val >> 8);
+			break;
+
+		case 3:
+			wy700_mode3_set_uint8 (wy700, addr & 0xFFFF, val);
+			wy700_mode3_set_uint8 (wy700, (addr + 1) & 0xFFFF, val >> 8);
+			break;
+	}
+}
+
+void wy700_crtc_set_reg (wy700_t *wy700, unsigned reg, unsigned char val)
+{
+	if (reg > 17) {
+		return;
+	}
+
+	wy700->crtc_reg[reg] = val;
+
+	switch (reg) {
+		case 0x0a:
+		case 0x0b:
+			wy700_set_crs (wy700, wy700->crtc_reg[0x0a], wy700->crtc_reg[0x0b]);
+			break;
+
+		case 0x0c:
+			wy700_set_page_ofs (wy700, (wy700->crtc_reg[0x0c] << 8) | val);
+			break;
+
+		case 0x0d:
+			wy700_set_page_ofs (wy700, (wy700->crtc_reg[0x0c] << 8) | val);
+			break;
+
+		case 0x0e:
+/*      wy700_set_pos (wy700, (val << 8) | (wy700->crtc_reg[0x0f] & 0xff)); */
+			break;
+
+		case 0x0f:
+			wy700_set_pos (wy700, (wy700->crtc_reg[0x0e] << 8) | val);
+			break;
+	}
+}
+
+unsigned char wy700_crtc_get_reg (wy700_t *wy700, unsigned reg)
+{
+	if (reg > 15) {
+		return (0xff);
+	}
+
+	return (wy700->crtc_reg[reg]);
+}
+
+void wy700_reg_set_uint8 (wy700_t *wy700, unsigned long addr, unsigned char val)
+{
+	wy700->reg->data[addr] = val;
+
+	switch (addr) {
+		case 0x01:
+			wy700_crtc_set_reg (wy700, wy700->reg->data[0], val);
+			break;
+
+		case 0x04:
+/* HACK If the video mode is changed, take us out of 1280x800 */
+			if (wy700->modereg != val)
+			{
+				wy700->control = 0;
+			}
+			wy700->modereg = val;
+			wy700_set_mode (wy700);
+/* Mode register can affect palette */
+			wy700_set_palette (wy700);
+			break;
+
+		case 0x05:
+			wy700->colreg = val;
+			wy700_set_palette (wy700);
+			break;
+
+		case 0x0B:
+			wy700->control = val;
+			wy700_set_mode (wy700);
+			break;
+	}
+}
+
+void wy700_reg_set_uint16 (wy700_t *wy700, unsigned long addr, unsigned short val)
+{
+	wy700_reg_set_uint8 (wy700, addr, val & 0xff);
+
+	if ((addr + 1) < wy700->reg->size) {
+		wy700_reg_set_uint8 (wy700, addr + 1, val >> 8);
+	}
+}
+
+unsigned char wy700_reg_get_uint8 (wy700_t *wy700, unsigned long addr)
+{
+	switch (addr) {
+		case 0x00:
+			return (wy700->reg->data[0]);
+
+		case 0x01:
+			return (wy700_crtc_get_reg (wy700, wy700->reg->data[0]));
+
+		case 0x06:
+			/* p freq: 14.31818 MHz
+				 h freq: 15.750 KHz
+				 v freq: 60 Hz
+				 912 / 14.31818e6 * 1e6 = 63.6952
+				 640 / 14.31818e6 * 1e6 = 44.6984
+				 262 / 15.75e3 * 1e6 = 16634.9206
+				 200 / 15.75e3 * 1e6 = 12698.4127
+			 */
+			if ((wy700->clkcnt % 16635) < 12699) {
+				wy700->reg->data[6] &= ~0x08;
+
+				if ((wy700->clkcnt % 64) < 45) {
+					wy700->reg->data[6] |= 0x01;
+				}
+				else {
+					wy700->reg->data[6] &= ~0x01;
+				}
+			}
+			else {
+				wy700->reg->data[6] |= 0x08;
+				wy700->reg->data[6] |= 0x01;
+			}
+
+			return (wy700->reg->data[6]);
+
+		default:
+			return (0xff);
+	}
+}
+
+unsigned short wy700_reg_get_uint16 (wy700_t *wy700, unsigned long addr)
+{
+	unsigned short ret;
+
+	ret = wy700_reg_get_uint8 (wy700, addr);
+
+	if ((addr + 1) < wy700->reg->size) {
+		ret |= wy700_reg_get_uint8 (wy700, addr + 1) << 8;
+	}
+
+	return (ret);
+}
diff -u -r -N pce-0.1.7/src/devices/video/wy700.h pce-new/src/devices/video/wy700.h
--- pce-0.1.7/src/devices/video/wy700.h	1970-01-01 01:00:00.000000000 +0100
+++ pce-new/src/devices/video/wy700.h	2008-10-14 23:12:55.000000000 +0100
@@ -0,0 +1,103 @@
+/*****************************************************************************
+ * pce                                                                       *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * File name:     src/devices/video/wy700.h                                  *
+ * Created:       2003-04-18 by Hampa Hug <hampa@hampa.ch>                   *
+ * Last modified: 2008-10-13 by John Elliott <jce@seasip.demon.co.uk>        *
+ * Copyright:     (C) 2003-2005 Hampa Hug <hampa@hampa.ch>                   *
+ *                (C) 2008 John Elliott <jce@seasip.demon.co.uk>             *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * This program is free software. You can redistribute it and / or modify it *
+ * under the terms of the GNU General Public License version 2 as  published *
+ * by the Free Software Foundation.                                          *
+ *                                                                           *
+ * This program is distributed in the hope  that  it  will  be  useful,  but *
+ * WITHOUT  ANY   WARRANTY,   without   even   the   implied   warranty   of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  General *
+ * Public License for more details.                                          *
+ *****************************************************************************/
+
+/* $Id: wy700.h 619 2005-12-28 21:42:53Z hampa $ */
+
+
+#ifndef PCE_WY700_H
+#define PCE_WY700_H 1
+
+
+#include <libini/libini.h>
+#include <terminal/terminal.h>
+#include <devices/video/video.h>
+
+
+typedef struct {
+	video_t       vid;
+
+	mem_blk_t     *mem;
+	mem_blk_t     *reg;
+
+	unsigned      mode_80x25_w;
+	unsigned      mode_80x25_h;
+	unsigned      mode_320x200_w;
+	unsigned      mode_320x200_h;
+	unsigned      mode_640x200_w;
+	unsigned      mode_640x200_h;
+	unsigned      mode_1280x800_w;
+	unsigned      mode_1280x800_h;
+
+	unsigned char crtc_reg[18];
+
+	unsigned      crtc_pos;
+	unsigned      crtc_ofs;
+
+	unsigned long clkcnt;
+
+	unsigned char pal;
+	unsigned char palette[4];
+
+	unsigned char modereg;
+	unsigned char colreg;
+	unsigned      control;
+	
+	int           crs_on;
+
+	unsigned      mode;
+
+	terminal_t    *trm;
+} wy700_t;
+
+
+video_t *wy700_new (terminal_t *trm, ini_sct_t *sct);
+
+void wy700_del (wy700_t *wy700);
+
+void wy700_clock (wy700_t *wy700, unsigned long cnt);
+
+void wy700_prt_state (wy700_t *wy700, FILE *fp);
+
+int wy700_dump (wy700_t *wy700, FILE *fp);
+
+mem_blk_t *wy700_get_mem (wy700_t *wy700);
+mem_blk_t *wy700_get_reg (wy700_t *wy700);
+
+int wy700_screenshot (wy700_t *wy700, FILE *fp, unsigned mode);
+
+void wy700_update (wy700_t *wy700);
+
+void wy700_set_pos (wy700_t *wy700, unsigned pos);
+
+void wy700_mem_set_uint8 (wy700_t *wy700, unsigned long addr, unsigned char val);
+void wy700_mem_set_uint16 (wy700_t *wy700, unsigned long addr, unsigned short val);
+unsigned char wy700_mem_get_uint8 (wy700_t *wy700, unsigned long addr);
+unsigned short wy700_mem_get_uint16 (wy700_t *wy700, unsigned long addr);
+
+void wy700_reg_set_uint8 (wy700_t *wy700, unsigned long addr, unsigned char val);
+void wy700_reg_set_uint16 (wy700_t *wy700, unsigned long addr, unsigned short val);
+unsigned char wy700_reg_get_uint8 (wy700_t *wy700, unsigned long addr);
+unsigned short wy700_reg_get_uint16 (wy700_t *wy700, unsigned long addr);
+
+
+#endif
