Index: emu/lcd.c
===================================================================
--- emu/lcd.c	(revision a86b3ab447e9d7063ef73c8b47bd525253aa0348)
+++ emu/lcd.c	(revision 18e37d6b1462414e9ab922d0c90c363051c24772)
@@ -22,4 +22,6 @@
 #define ver3(...) _ver(lcd_verbose, 2, __VA_ARGS__)
 
+int32_t lcd_verbose = 0;
+
 #define WIN_W (510 * 2)
 #define WIN_H (64 * 2)
@@ -29,4 +31,8 @@
 #define CON_FGR ((SDL_Color){ .r = 255, .b = 255, .g = 255, .a = 255 })
 
+#define REG_ARG 0
+#define REG_COM 1
+
+#define G_NONE		0x00
 #define	G_INIT		0x40
 #define	G_MWRITE	0x42
@@ -57,4 +63,8 @@
 #define BASE_GFX 0x2000
 
+#define DIR_UP -85
+#define DIR_DOWN 85
+#define DIR_RIGHT 1
+
 static uint8_t mem_txt[TXT_H * TXT_W];
 static uint8_t mem_gfx[GFX_H * GFX_W];
@@ -63,7 +73,5 @@
 static SDL_Renderer *ren;
 static SDL_atomic_t frame;
-static SDL_atomic_t clear;
-
-static uint32_t render = 0;
+static SDL_atomic_t ena;
 
 static TTF_Font *fon;
@@ -74,34 +82,12 @@
 static SDL_Surface *gfx_sur;
 
-static int32_t cur = 0;
-static int32_t cur_c = 0;
-static int32_t dir = 1;
-
-static int32_t current_op = 0x00;
-
-static uint32_t last_val = 0x00;
-static uint32_t last_off = 0;
-static int32_t last_sz = -1;
-static int32_t mult_val_c = 0;
-
-int32_t lcd_verbose = 0;
+static int32_t com;
+static int32_t n_arg;
+static int32_t cur = BASE_TXT;
+static int32_t dir = DIR_RIGHT;
 
 void lcd_sdl(void)
 {
 	ver3("lcd_sdl()");
-
-	if (SDL_AtomicGet(&clear)) {
-		if (SDL_SetRenderDrawColor(ren, 0x00, 0x00, 0x00, 0xff) < 0) {
-			fail("SDL_SetRenderDrawColor() failed: %s", SDL_GetError());
-		}
-
-		if (SDL_RenderClear(ren) < 0) {
-			fail("SDL_RenderClear() failed: %s", SDL_GetError());
-		}
-
-		SDL_RenderPresent(ren);
-		SDL_AtomicSet(&clear, 0);
-		return;
-	}
 
 	static int32_t last = 0;
@@ -119,4 +105,8 @@
 	}
 
+	if (SDL_AtomicGet(&ena) == 0) {
+		return;
+	}
+
 	for (int32_t y = 0; y < TXT_H; ++y) {
 		char line[TXT_W + 1];
@@ -126,5 +116,9 @@
 		}
 
-		memcpy(line, mem_txt + y * TXT_W, TXT_W);
+		for (int32_t x = 0; x < TXT_W; ++x) {
+			uint8_t c = mem_txt[y * TXT_W + x];
+			line[x] = (char)(c == 0x00 ? ' ' : c);
+		}
+
 		line[TXT_W] = 0;
 
@@ -215,7 +209,6 @@
 	}
 
-	SDL_AtomicSet(&clear, 0);
-
 	SDL_AtomicSet(&frame, 1);
+	SDL_AtomicSet(&ena, 0);
 
 	SDL_RWops *ops = SDL_RWFromFile(font, "rb");
@@ -279,139 +272,122 @@
 	ver2("lcd rd %u:%d", off, sz * 8);
 
-	uint32_t rv;
-
-	switch (current_op) {
-		case G_MREAD:
-			if (cur >= BASE_TXT && cur < BASE_TXT + TXT_W * TXT_H) {
-				rv = mem_txt[cur - BASE_TXT];
+	if (sz != 1 || off > 0) {
+		fail("invalid lcd rd %u:%d", off, sz * 8);
+	}
+
+	switch (com) {
+	case G_MREAD:
+		if (cur >= BASE_TXT && cur < BASE_TXT + TXT_W * TXT_H) {
+			return mem_txt[cur - BASE_TXT];
+		}
+
+		if (cur >= BASE_GFX && cur < BASE_GFX + GFX_W * GFX_H) {
+			return mem_gfx[cur - BASE_GFX];
+		}
+
+		return 0x00;
+
+	default:
+		return 0x00;
+	}
+}
+
+static void proc_arg(int32_t val)
+{
+	switch (com) {
+	case G_MWRITE:
+		if (cur >= BASE_TXT && cur < BASE_TXT + TXT_W * TXT_H) {
+			mem_txt[cur - BASE_TXT] = (uint8_t)val;
+		}
+		else if (cur >= BASE_GFX && cur < BASE_GFX + GFX_W * GFX_H) {
+			mem_gfx[cur - BASE_GFX] = (uint8_t)val;
+		}
+
+		cur += dir;
+		SDL_AtomicAdd(&frame, 1);
+		break;
+
+	case G_CRSWR:
+		if (n_arg == 0) {
+			cur = val;
+		}
+		else if (n_arg == 1) {
+			cur |= val << 8;
+
+			if (cur < BASE_TXT ||
+					(cur >= BASE_TXT + TXT_W * TXT_H && cur < BASE_GFX) ||
+					cur >= BASE_GFX + GFX_W * GFX_H) {
+				fail("invalid address 0x%04x", cur);
 			}
-			else if (cur >= BASE_GFX && cur < BASE_GFX + GFX_W * GFX_H) {
-				rv = mem_gfx[cur - BASE_GFX];
-			}
-			else {
-				rv = 0x00;
-			}
-			break;
-
-		default:
-			rv = 0x00;
-			break;
-	}
-	return rv;
+		}
+
+		break;
+
+	default:
+		break;
+	}
+}
+
+static void proc_com(int32_t val)
+{
+	switch (val) {
+	case G_CRSWR:
+	case G_MREAD:
+	case G_MWRITE:
+		com = val;
+		break;
+
+	case G_CRSMRT:
+		dir = DIR_RIGHT;
+		com = G_NONE;
+		break;
+
+	case G_CRSMUP:
+		dir = DIR_UP;
+		com = G_NONE;
+		break;
+
+	case G_CRSMDN:
+		dir = DIR_DOWN;
+		com = G_NONE;
+		break;
+
+	case G_DSPOFF:
+		SDL_AtomicSet(&ena, 0);
+		com = G_NONE;
+		break;
+
+	case G_DSPON:
+		SDL_AtomicSet(&ena, 1);
+		com = G_NONE;
+		break;
+
+	default:
+		com = G_NONE;
+		break;
+	}
 }
 
 void lcd_write(uint32_t off, int32_t sz, uint32_t val)
 {
-	if (last_val != val && mult_val_c > 0) {
-		if (mult_val_c > 1) {
-			ver2("lcd wr %u:%d 0x%0*x was called %u more times", last_off, last_sz * 8, last_sz * 2, last_val, mult_val_c);
-		}
-		else {
-			ver2("lcd wr %u:%d 0x%0*x", last_off, last_sz * 8, last_sz * 2, last_val);
-		}
-
-		ver2("lcd wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val);
-		mult_val_c = 0;
-	}
-	else if (last_val == val && mult_val_c >= 0) {
-		++mult_val_c;
-	}
-	else {
-		ver2("lcd wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val);
-	}
-
-	last_val = val;
-	last_off = off;
-	last_sz = sz;
-
-	if (off == 0) {
-		switch (current_op) {
-			case G_MWRITE:
-					if (cur >= BASE_TXT && cur < BASE_TXT + TXT_W * TXT_H) {
-						if (val == 0) {
-							mem_txt[cur - BASE_TXT] = ' ';
-						}
-						else {
-							mem_txt[cur - BASE_TXT] = (uint8_t) val;
-						}
-
-						cur += dir;
-
-						if (render) {
-							SDL_AtomicAdd(&frame, 1);
-						}
-					}
-					else if (cur >= BASE_GFX && cur < BASE_GFX + GFX_W * GFX_H) {
-						mem_gfx[cur - BASE_GFX] = (uint8_t) val;
-						cur += dir;
-
-						if (render) {
-							SDL_AtomicAdd(&frame, 1);
-						}
-					}
-				break;
-
-			case G_CRSWR:
-				if (cur_c == 0) {
-					cur = (int32_t) val;
-					cur_c++;
-				}
-				else if (cur_c == 1) {
-					cur = cur | ((int32_t) val << 8);
-					if (cur < BASE_TXT || (cur >= BASE_TXT + TXT_W * TXT_H && cur < BASE_GFX) || cur >= BASE_GFX + GFX_W * GFX_H) {
-						err("Invalid cur value %d", cur);
-					}
-					cur_c = 0;
-				}
-				break;
-
-			default:
-				break;
-		}
-	}
-	else {
-		switch (val) {
-			case G_MWRITE:
-				current_op = G_MWRITE;
-				break;
-
-			case G_CRSMRT:
-				dir = 1;
-				current_op = G_CRSMRT;
-				break;
-
-			case G_CRSMUP:
-				dir = -85;
-				current_op = G_CRSMUP;
-				break;
-
-			case G_CRSMDN:
-				dir = 85;
-				current_op = G_CRSMDN;
-				break;
-
-			case G_CRSWR:
-				current_op = G_CRSWR;
-				break;
-
-			case G_MREAD:
-				current_op = G_MREAD;
-				break;
-
-			case G_DSPOFF:
-				SDL_AtomicSet(&clear, 1);
-				render = 0;
-				current_op = G_DSPOFF;
-				break;
-
-			case G_DSPON:
-				render = 1;
-				current_op = G_DSPON;
-				break;
-
-			default:
-				current_op = 0x00;
-				break;
-		}
-	}
-}
+	ver2("lcd wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val);
+
+	if (sz != 1 || off > 1) {
+		fail("invalid lcd wr %u:%d", off, sz * 8);
+	}
+
+	switch (off) {
+	case REG_ARG:
+		proc_arg((int32_t)val);
+		++n_arg;
+		break;
+
+	case REG_COM:
+		proc_com((int32_t)val);
+		n_arg = 0;
+		break;
+
+	default:
+		break;
+	}
+}
