/* Here's a little "demo" with a new DC effect -- grayscale VMU! This
   uses a pretty common technique to get more than 2 colors out of a
   1 bit display -- page flipping. Basically you setup real refresh frames
   and a pixel should stay dark an amount of time proportional to its
   intended grayscale. Anyway, this implements that on the VMU. Thanks
   to Jordan for the idea =). If you don't believe your eyes, then hit
   the start button to stop the demo and you'll see what's left =).
*/

#include <kos.h>

/* This is really more complicated than it needs to be in this particular
   case, but it's nice and verbose. */
int check_start() {
	uint8 mcont;
	cont_cond_t cond;

	mcont = maple_first_controller();
	if (!mcont)
		return 0;

	/* Check for start on the controller */
	if (cont_get_cond(mcont, &cond) < 0) {
		return 0;
	}
		
	if (!(cond.buttons & CONT_START)) {
		printf("Pressed start\n");
		return 1;
	}

	return 0;
}

/* Only this XPM will work with this code.. it's too cheap to actually
   do any parsing =) */
#include "graphic.xpm"

/* LCD Test: this will do a grayscale seperation into several "frames" and
   flip through them quickly to give the illusion of grayscale on the LCD
   display. */
uint8 lcd_disp[8][48*32/8];
void lcd_gs_pixel(int x, int y, int amt) {
	int i;

	for (i=0; i<amt; i++)
		lcd_disp[i][(y*48+x)/8] |= 0x80 >> (x&7);
}
void lcd_gs_setup() {
	char **xpm = graphic_xpm + 12;	/* Skip header */
	int x, y;

	memset(lcd_disp, 0, sizeof(lcd_disp));

	for (y=0; y<32; y++) {
		for (x=0; x<48; x++) {
			/* Note that LCD images must be flipped! */
			int pixel = xpm[31 - y][47 - x];
			switch(pixel) {
				case '.':	/* White */
					lcd_gs_pixel(x, y, 0); break;
				case '#':	/* #e3e3e3 */
					lcd_gs_pixel(x, y, 1); break;
				case '+':	/* #c7c7c7 */
					lcd_gs_pixel(x, y, 2); break;
				case '@':	/* #aaaaaa */
					lcd_gs_pixel(x, y, 3); break;
				case '=':	/* #8e8e8e */
				case '-':	/* #727272 */
					lcd_gs_pixel(x, y, 4); break;
				case '$':	/* #555555 */
					lcd_gs_pixel(x, y, 5); break;
				case '*':	/* #393939 */
					lcd_gs_pixel(x, y, 6); break;
				case '&':	/* #1d1d1d */
				case '%':	/* #000000 */
					lcd_gs_pixel(x, y, 7); break;
			}
		}
	}
}

/* This performs the actual magic */
void lcd_test() {
	int frame = 0;

	lcd_gs_setup();

	while (!check_start()) {
		maple_device_t *addr = maple_enum_type(0, MAPLE_FUNC_LCD);
		if (addr) {
			int rv = vmu_draw_lcd(addr, lcd_disp+frame);
			if (rv < 0)
				printf("got error %d\n", rv);
			else {
				frame++; if (frame>=8) frame=0;
			}
		}
		// usleep(5 * 1000);
	}
}

int main(int argc, char **argv) {
	lcd_test();

	return 0;
}
