LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
		coord_t		sy, ey;
		coord_t		sx, ex;
		coord_t		col;
		unsigned	spage, zpages;
		uint8_t *	base;
		uint8_t		mask;

		switch(g->g.Orientation) {
		default:
		case GDISP_ROTATE_0:
			sx = g->p.x;
			ex = g->p.x + g->p.cx - 1;
			sy = g->p.y;
			ey = sy + g->p.cy - 1;
			break;
		case GDISP_ROTATE_90:
			sx = g->p.y;
			ex = g->p.y + g->p.cy - 1;
			sy = GDISP_SCREEN_HEIGHT - g->p.x - g->p.cx;
			ey = GDISP_SCREEN_HEIGHT-1 - g->p.x;
			break;
		case GDISP_ROTATE_180:
			sx = GDISP_SCREEN_WIDTH - g->p.x - g->p.cx;
			ex = GDISP_SCREEN_WIDTH-1 - g->p.x;
			sy = GDISP_SCREEN_HEIGHT - g->p.y - g->p.cy;
			ey = GDISP_SCREEN_HEIGHT-1 - g->p.y;
			break;
		case GDISP_ROTATE_270:
			sx = GDISP_SCREEN_WIDTH - g->p.y - g->p.cy;
			ex = GDISP_SCREEN_WIDTH-1 - g->p.y;
			sy = g->p.x;
			ey = g->p.x + g->p.cx - 1;
			break;
		}

		spage = sy / 8;
		base = RAM(g) + SSD1306_PAGE_OFFSET + SSD1306_PAGE_WIDTH * spage;
		mask = 0xff << (sy&7);
		zpages = (ey / 8) - spage;

		if (gdispColor2Native(g->p.color) == gdispColor2Native(Black)) {
			while (zpages--) {
				for (col = sx; col <= ex; col++)
					base[col] &= ~mask;
				mask = 0xff;
				base += SSD1306_PAGE_WIDTH;
			}
			mask &= (0xff >> (7 - (ey&7)));
			for (col = sx; col <= ex; col++)
				base[col] &= ~mask;
		} else {
			while (zpages--) {
	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
		LLDCOLOR_TYPE	c;

		c = gdispColor2Native(g->p.color);
		write_data(g, c >> 8);
		write_data(g, c & 0xFF);
	}
Example #3
0
LLDSPEC void gdisp_lld_draw_pixel(GDisplay* g) {
	unsigned	pos;

	#if GDISP_NEED_CONTROL
		switch(g->g.Orientation) {
		case GDISP_ROTATE_0:
		default:
			pos = PIXIL_POS(g, g->p.x, g->p.y);
			break;
		case GDISP_ROTATE_90:
			pos = PIXIL_POS(g, g->p.y, g->g.Width-g->p.x-1);
			break;
		case GDISP_ROTATE_180:
			pos = PIXIL_POS(g, g->g.Width-g->p.x-1, g->g.Height-g->p.y-1);
			break;
		case GDISP_ROTATE_270:
			pos = PIXIL_POS(g, g->g.Height-g->p.y-1, g->p.x);
			break;
		}
	#else
		pos = PIXIL_POS(g, g->p.x, g->p.y);
	#endif

	#if LTDC_USE_DMA2D
		while(DMA2D->CR & DMA2D_CR_START);
	#endif

	PIXEL_ADDR(g, pos)[0] = gdispColor2Native(g->p.color);
}
Example #4
0
	LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
		netPriv	*	priv;
		pixel_t	*	buffer;
		uint16_t	buf[5];
		coord_t		x, y;

		#if GDISP_DONT_WAIT_FOR_NET_DISPLAY
			if (!(g->flags & GDISP_FLG_CONNECTED))
				return;
		#else
			while(!(g->flags & GDISP_FLG_CONNECTED))
				gfxSleepMilliseconds(200);
		#endif

		// Make everything relative to the start of the line
		buffer = g->p.ptr;
		buffer += g->p.x2*g->p.y1;

		priv = g->priv;
		buf[0] = GNETCODE_BLIT;
		buf[1] = g->p.x;
		buf[2] = g->p.y;
		buf[3] = g->p.cx;
		buf[4] = g->p.cy;
		MUTEX_ENTER;
		sendpkt(priv->netfd, buf, 5);

		for(y = 0; y < g->p.cy; y++, buffer += g->p.x2 - g->p.cx) {
			for(x = 0; x < g->p.cx; x++, buffer++) {
				buf[0] = gdispColor2Native(buffer[0]);
				sendpkt(priv->netfd, buf, 1);
			}
		}
		MUTEX_EXIT;
	}
Example #5
0
	LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
		uint16_t	c;

		c = gdispColor2Native(g->p.color);
		acquire_bus(g);
		set_viewport(g);
		set_cursor(g);
		dma_with_noinc(g, &c, g->p.cx*g->p.cy);
		release_bus(g);
	}
	LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
		winPriv	*	priv;
		int			x, y;
		COLORREF	color;

		priv = g->priv;
		color = gdispColor2Native(g->p.color);

		#if GDISP_NEED_CONTROL
			switch(g->g.Orientation) {
			case GDISP_ROTATE_0:
			default:
				x = g->p.x;
				y = g->p.y;
				break;
			case GDISP_ROTATE_90:
				x = g->p.y;
				y = g->g.Width - 1 - g->p.x;
				break;
			case GDISP_ROTATE_180:
				x = g->g.Width - 1 - g->p.x;
				y = g->g.Height - 1 - g->p.y;
				break;
			case GDISP_ROTATE_270:
				x = g->g.Height - 1 - g->p.y;
				y = g->p.x;
				break;
			}
		#else
			x = g->p.x;
			y = g->p.y;
		#endif

		// Draw the pixel on the screen and in the buffer.
		WaitForSingleObject(drawMutex, INFINITE);
		SetPixel(priv->dcBuffer, x, y, color);
		#if GDISP_WIN32_USE_INDIRECT_UPDATE
			ReleaseMutex(drawMutex);
			{
				RECT	r;
				r.left = x; r.right = x+1;
				r.top = y; r.bottom = y+1;
				InvalidateRect(priv->hwnd, &r, FALSE);
			}
		#else
			{
				HDC		dc;
				dc = GetDC(priv->hwnd);
				SetPixel(dc, x, y, color);
				ReleaseDC(priv->hwnd, dc);
				ReleaseMutex(drawMutex);
			}
		#endif
	}
Example #7
0
	LLDSPEC void gdisp_lld_fill_area(GDisplay* g) {
		#if GDISP_NO_DMA_FROM_STACK
			static LLDCOLOR_TYPE	c;
		#else
			LLDCOLOR_TYPE	c;
		#endif

		c = gdispColor2Native(g->p.color);
		acquire_bus(g);
		set_viewport(g);
		set_cursor(g);	
		dma_with_noinc(g, &c, g->p.cx * g->p.cy);
		release_bus(g);
	}
Example #8
0
	// Uses p.x,p.y  p.cx,p.cy  p.color
	LLDSPEC void gdisp_lld_fill_area(GDisplay* g)
	{	
		uint32_t pos;
		uint32_t lineadd;
		uint32_t shape;

		// Wait until DMA2D is ready
		while(DMA2D->CR & DMA2D_CR_START);

		#if GDISP_NEED_CONTROL
			switch(g->g.Orientation) {
			case GDISP_ROTATE_0:
			default:
				pos = PIXIL_POS(g, g->p.x, g->p.y);
				lineadd = g->g.Width - g->p.cx;
				shape = (g->p.cx << 16) | (g->p.cy);
				break;
			case GDISP_ROTATE_90:
				pos = PIXIL_POS(g, g->p.y, g->g.Width-g->p.x-g->p.cx);
				lineadd = g->g.Height - g->p.cy;
				shape = (g->p.cy << 16) | (g->p.cx);
				break;
			case GDISP_ROTATE_180:
				pos = PIXIL_POS(g, g->g.Width-g->p.x-g->p.cx, g->g.Height-g->p.y-g->p.cy);
				lineadd = g->g.Width - g->p.cx;
				shape = (g->p.cx << 16) | (g->p.cy);
				break;
			case GDISP_ROTATE_270:
				pos = PIXIL_POS(g, g->g.Height-g->p.y-g->p.cy, g->p.x);
				lineadd = g->g.Height - g->p.cy;
				shape = (g->p.cy << 16) | (g->p.cx);
				break;
			}
		#else
			pos = PIXIL_POS(g, g->p.x, g->p.y);
			lineadd = g->g.Width - g->p.cx;
			shape = (g->p.cx << 16) | (g->p.cy);
		#endif
		
		// Start the DMA2D
		DMA2D->OMAR = (uint32_t)PIXEL_ADDR(g, pos);
		DMA2D->OOR = lineadd;
		DMA2D->NLR = shape;
		DMA2D->OCOLR = (uint32_t)(gdispColor2Native(g->p.color));
		DMA2D->CR = DMA2D_CR_MODE_R2M | DMA2D_CR_START;	
	}
 LLDSPEC void gdisp_lld_clear(GDisplay *g) {
   acquire_bus(g);
   write_cmd(g, SSD1327_SET_COLUMN_ADDRESS);
   write_data(g, 0);
   write_data(g, GDISP_SCREEN_WIDTH - 1);
   write_cmd(g, SSD1327_SET_ROW_ADDRESS);
   write_data(g, 0);
   write_data(g, GDISP_SCREEN_HEIGHT - 1);
   write_cmd(g, SSD1327_WRITE_RAM);
   LLDCOLOR_TYPE c;
   c = gdispColor2Native(g->p.color);
   uint16_t i = 0;
   for (i = 0; i < GDISP_SCREEN_WIDTH*GDISP_SCREEN_HEIGHT; i++)
   {
     write_data(g, c >> 8);
     write_data(g, c & 0xFF);
   }
   release_bus(g);
 }
Example #10
0
	LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
		netPriv	*	priv;
		uint16_t	buf[4];

		#if GDISP_DONT_WAIT_FOR_NET_DISPLAY
			if (!(g->flags & GDISP_FLG_CONNECTED))
				return;
		#else
			while(!(g->flags & GDISP_FLG_CONNECTED))
				gfxSleepMilliseconds(200);
		#endif

		priv = g->priv;
		buf[0] = GNETCODE_PIXEL;
		buf[1] = g->p.x;
		buf[2] = g->p.y;
		buf[3] = gdispColor2Native(g->p.color);
		MUTEX_ENTER;
		sendpkt(priv->netfd, buf, 4);
		MUTEX_EXIT;
	}
Example #11
0
LLDSPEC	void gdisp_lld_write_color(GDisplay *g)
{
	write_data(g, gdispColor2Native(g->p.color));
}
	LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
		winPriv	*	priv;
		RECT		rect;
		HBRUSH		hbr;
		COLORREF	color;

		priv = g->priv;
		color = gdispColor2Native(g->p.color);
		hbr = CreateSolidBrush(color);

		#if GDISP_NEED_CONTROL
			switch(g->g.Orientation) {
			case GDISP_ROTATE_0:
			default:
				rect.top = g->p.y;
				rect.bottom = rect.top + g->p.cy;
				rect.left = g->p.x;
				rect.right = rect.left + g->p.cx;
				break;
			case GDISP_ROTATE_90:
				rect.bottom = g->g.Width - g->p.x;
				rect.top = rect.bottom - g->p.cx;
				rect.left = g->p.y;
				rect.right = rect.left + g->p.cy;
				break;
			case GDISP_ROTATE_180:
				rect.bottom = g->g.Height - g->p.y;
				rect.top = rect.bottom - g->p.cy;
				rect.right = g->g.Width - g->p.x;
				rect.left = rect.right - g->p.cx;
				break;
			case GDISP_ROTATE_270:
				rect.top = g->p.x;
				rect.bottom = rect.top + g->p.cx;
				rect.right = g->g.Height - g->p.y;
				rect.left = rect.right - g->p.cy;
				break;
			}
		#else
			rect.top = g->p.y;
			rect.bottom = rect.top + g->p.cy;
			rect.left = g->p.x;
			rect.right = rect.left + g->p.cx;
		#endif


		WaitForSingleObject(drawMutex, INFINITE);
		FillRect(priv->dcBuffer, &rect, hbr);
		#if GDISP_WIN32_USE_INDIRECT_UPDATE
			ReleaseMutex(drawMutex);
			InvalidateRect(priv->hwnd, &rect, FALSE);
		#else
			{
				HDC		dc;
				dc = GetDC(priv->hwnd);
				FillRect(dc, &rect, hbr);
				ReleaseDC(priv->hwnd, dc);
				ReleaseMutex(drawMutex);
			}
		#endif

		DeleteObject(hbr);
	}
	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
		winPriv	*	priv;
		int			x, y;
		COLORREF	color;

		priv = g->priv;
		color = gdispColor2Native(g->p.color);

		if (!(g->flags & GDISP_FLG_WSTREAM))
			BAD_PARAMETER("write_color: not in streaming mode");
		if (priv->x < priv->x0 || priv->x > priv->x1 || priv->y < priv->y0 || priv->y > priv->y1)
			BAD_PARAMETER("write_color: cursor outside streaming area");
		if (g->flags & GDISP_FLG_WRAPPED) {
			BAD_PARAMETER("write_color: Warning - Area wrapped.");
			g->flags &= ~GDISP_FLG_WRAPPED;
		}

		#if GDISP_NEED_CONTROL
			switch(g->g.Orientation) {
			case GDISP_ROTATE_0:
			default:
				x = priv->x;
				y = priv->y;
				break;
			case GDISP_ROTATE_90:
				x = priv->y;
				y = g->g.Width - 1 - priv->x;
				break;
			case GDISP_ROTATE_180:
				x = g->g.Width - 1 - priv->x;
				y = g->g.Height - 1 - priv->y;
				break;
			case GDISP_ROTATE_270:
				x = g->g.Height - 1 - priv->y;
				y = priv->x;
				break;
			}
		#else
			x = priv->x;
			y = priv->y;
		#endif

		// Draw the pixel on the screen and in the buffer.
		WaitForSingleObject(drawMutex, INFINITE);
		SetPixel(priv->dcBuffer, x, y, color);
		#if GDISP_WIN32_USE_INDIRECT_UPDATE
			ReleaseMutex(drawMutex);
			{
				RECT	r;
				r.left = x; r.right = x+1;
				r.top = y; r.bottom = y+1;
				InvalidateRect(priv->hwnd, &r, FALSE);
			}
		#else
			{
				HDC		dc;
				dc = GetDC(priv->hwnd);
				SetPixel(dc, x, y, color);
				ReleaseDC(priv->hwnd, dc);
				ReleaseMutex(drawMutex);
			}
		#endif

		// Update the cursor
		if (++priv->x > priv->x1) {
			priv->x = priv->x0;
			if (++priv->y > priv->y1) {
				g->flags |= GDISP_FLG_WRAPPED;
				priv->y = priv->y0;
			}
		}
	}
static LRESULT myWindowProc(HWND hWnd,	UINT Msg, WPARAM wParam, LPARAM lParam)
{
	HDC				dc;
	PAINTSTRUCT		ps;
	GDisplay *		g;
	winPriv *		priv;
	#if GINPUT_NEED_TOGGLE
		HBRUSH		hbrOn, hbrOff;
		HPEN		pen;
		RECT		rect;
		HGDIOBJ		old;
		POINT 		p;
		coord_t		pos;
		uint8_t		bit;
	#endif

	switch (Msg) {
	case WM_CREATE:
		// Get our GDisplay structure and attach it to the window
		g = (GDisplay *)((LPCREATESTRUCT)lParam)->lpCreateParams;
		priv = (winPriv *)g->priv;
		SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)g);

		// Fill in the private area
		priv->hwnd = hWnd;
		dc = GetDC(hWnd);
		priv->dcBitmap = CreateCompatibleBitmap(dc, g->g.Width, g->g.Height);
		priv->dcBuffer = CreateCompatibleDC(dc);
		ReleaseDC(hWnd, dc);
		priv->dcOldBitmap = SelectObject(priv->dcBuffer, priv->dcBitmap);

		// Mark the window as ready to go
		g->flags |= GDISP_FLG_READY;
		break;

	#if GINPUT_NEED_MOUSE || GINPUT_NEED_TOGGLE
		case WM_LBUTTONDOWN:
			// Get our GDisplay structure
			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
			priv = (winPriv *)g->priv;

			// Handle mouse down on the window
			#if GINPUT_NEED_MOUSE
				if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT) {
					priv->mousebuttons |= GINPUT_MOUSE_BTN_LEFT;
					goto mousemove;
				}
			#endif

			// Handle mouse down on the toggle area
			#if GINPUT_NEED_TOGGLE
				if ((coord_t)HIWORD(lParam) >= GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASTOGGLE)) {
					bit = 1 << ((coord_t)LOWORD(lParam)*8/g->g.Width);
					priv->toggles ^= bit;
					rect.left = 0;
					rect.right = GDISP_SCREEN_WIDTH;
					rect.top = GDISP_SCREEN_HEIGHT;
					rect.bottom = GDISP_SCREEN_HEIGHT + WIN32_BUTTON_AREA;
					InvalidateRect(hWnd, &rect, FALSE);
					UpdateWindow(hWnd);
					#if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE
						ginputToggleWakeup();
					#endif
				}
			#endif
			break;

		case WM_LBUTTONUP:
			// Get our GDisplay structure
			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
			priv = (winPriv *)g->priv;

			// Handle mouse up on the toggle area
			#if GINPUT_NEED_TOGGLE
				if ((g->flags & GDISP_FLG_HASTOGGLE)) {
					if ((priv->toggles & 0x0F)) {
						priv->toggles &= ~0x0F;
						rect.left = 0;
						rect.right = GDISP_SCREEN_WIDTH;
						rect.top = GDISP_SCREEN_HEIGHT;
						rect.bottom = GDISP_SCREEN_HEIGHT + WIN32_BUTTON_AREA;
						InvalidateRect(hWnd, &rect, FALSE);
						UpdateWindow(hWnd);
						#if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE
							ginputToggleWakeup();
						#endif
					}
				}
			#endif

			// Handle mouse up on the window
			#if GINPUT_NEED_MOUSE
				if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT) {
					priv->mousebuttons &= ~GINPUT_MOUSE_BTN_LEFT;
					goto mousemove;
				}
			#endif
			break;
	#endif

	#if GINPUT_NEED_MOUSE
		case WM_MBUTTONDOWN:
			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
			priv = (winPriv *)g->priv;
			if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT) {
				priv->mousebuttons |= GINPUT_MOUSE_BTN_MIDDLE;
				goto mousemove;
			}
			break;
		case WM_MBUTTONUP:
			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
			priv = (winPriv *)g->priv;
			if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT) {
				priv->mousebuttons &= ~GINPUT_MOUSE_BTN_MIDDLE;
				goto mousemove;
			}
			break;
		case WM_RBUTTONDOWN:
			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
			priv = (winPriv *)g->priv;
			if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT) {
				priv->mousebuttons |= GINPUT_MOUSE_BTN_RIGHT;
				goto mousemove;
			}
			break;
		case WM_RBUTTONUP:
			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
			priv = (winPriv *)g->priv;
			if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT) {
				priv->mousebuttons &= ~GINPUT_MOUSE_BTN_RIGHT;
				goto mousemove;
			}
			break;
		case WM_MOUSEMOVE:
			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
			priv = (winPriv *)g->priv;
			if ((coord_t)HIWORD(lParam) >= GDISP_SCREEN_HEIGHT)
				break;
		mousemove:
			priv->mousex = (coord_t)LOWORD(lParam);
			priv->mousey = (coord_t)HIWORD(lParam);
			if ((gmvmt(priv->mouse)->d.flags & GMOUSE_VFLG_NOPOLL))		// For normal setup this is always TRUE
				_gmouseWakeup(priv->mouse);
			break;
	#endif

	case WM_SYSKEYDOWN:
	case WM_KEYDOWN:
	case WM_SYSKEYUP:
	case WM_KEYUP:
		break;
	case WM_CHAR:
	case WM_DEADCHAR:
	case WM_SYSCHAR:
	case WM_SYSDEADCHAR:
		break;

	case WM_ERASEBKGND:
		// Pretend we have erased the background.
		// We know we don't really need to do this as we
		// redraw the entire surface in the WM_PAINT handler.
		return TRUE;

	case WM_PAINT:
		// Get our GDisplay structure
		g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
		priv = (winPriv *)g->priv;

		// Paint the main window area
		WaitForSingleObject(drawMutex, INFINITE);
		dc = BeginPaint(hWnd, &ps);
		BitBlt(dc, ps.rcPaint.left, ps.rcPaint.top,
			ps.rcPaint.right - ps.rcPaint.left,
			(ps.rcPaint.bottom > GDISP_SCREEN_HEIGHT ? GDISP_SCREEN_HEIGHT : ps.rcPaint.bottom) - ps.rcPaint.top,
			priv->dcBuffer, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);

		// Paint the toggle area
		#if GINPUT_NEED_TOGGLE
			if (ps.rcPaint.bottom >= GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASTOGGLE)) {
				pen = CreatePen(PS_SOLID, 1, gdispColor2Native(Black));
				hbrOn = CreateSolidBrush(gdispColor2Native(Blue));
				hbrOff = CreateSolidBrush(gdispColor2Native(Gray));
				old = SelectObject(dc, pen);
				MoveToEx(dc, 0, GDISP_SCREEN_HEIGHT, &p);
				LineTo(dc, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT);
				for(pos = 0, bit=1; pos < wWidth; pos=rect.right, bit <<= 1) {
					rect.left = pos;
					rect.right = pos + GDISP_SCREEN_WIDTH/8;
					rect.top = GDISP_SCREEN_HEIGHT;
					rect.bottom = GDISP_SCREEN_HEIGHT + WIN32_BUTTON_AREA;
					FillRect(dc, &rect, (priv->toggles & bit) ? hbrOn : hbrOff);
					if (pos > 0) {
						MoveToEx(dc, rect.left, rect.top, &p);
						LineTo(dc, rect.left, rect.bottom);
					}
				}
				DeleteObject(hbrOn);
				DeleteObject(hbrOff);
				SelectObject(dc, old);
			}
		#endif
		EndPaint(hWnd, &ps);
		ReleaseMutex(drawMutex);
		break;

	case WM_DESTROY:
		// Get our GDisplay structure
		g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
		priv = (winPriv *)g->priv;

		// Restore the window and free our bitmaps
		SelectObject(priv->dcBuffer, priv->dcOldBitmap);
		DeleteDC(priv->dcBuffer);
		DeleteObject(priv->dcBitmap);

		// Cleanup the private area
		gfxFree(priv);

		// Quit the application
		PostQuitMessage(0);

		// Actually the above doesn't work (who knows why)
		ExitProcess(0);
		break;

	default:
		return DefWindowProc(hWnd, Msg, wParam, lParam);
	}
	return 0;
}
 LLDSPEC void gdisp_lld_write_color(GDisplay *g) {
         color_t color = gdispColor2Native(g->p.color);
         write_cmd(g, color >> 8);
         write_cmd(g, color & 0xff);
 }