/*
 * hd200icon.c
 *
 *  Created on: 2009-10-15
 *      Author: wodz
 *
 *  compile: CC -Wall -O2 -o hd200icon hd200icon.c -I/usr/include/SDL -lSDL
 */

#include <SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>

void DrawPixel(SDL_Surface *screen, Uint8 R, Uint8 G, Uint8 B, Uint16 x, Uint16 y)
{
	Uint32 color = SDL_MapRGB(screen->format, R, G, B);

	if ( SDL_MUSTLOCK(screen) ) 
	{
        	if ( SDL_LockSurface(screen) < 0 ) 
		{
            		return;
        	}
    	}

	switch (screen->format->BytesPerPixel) 
	{
		case 1: 
		{ 
		/* Assuming 8-bpp */
            		Uint8 *bufp;

            		bufp = (Uint8 *)screen->pixels + y*screen->pitch + x;
            		*bufp = color;
        	}
        	break;

		case 2: 
		{ 
		/* Probably 15-bpp or 16-bpp */
            		Uint16 *bufp;

            		bufp = (Uint16 *)screen->pixels + y*screen->pitch/2 + x;
            		*bufp = color;
        	}
        	break;

		case 3: 
		{ 
		/* Slow 24-bpp mode, usually not used */
            		Uint8 *bufp;

            		bufp = (Uint8 *)screen->pixels + y*screen->pitch + x;
            		*(bufp+screen->format->Rshift/8) = R;
            		*(bufp+screen->format->Gshift/8) = G;
            		*(bufp+screen->format->Bshift/8) = B;
        	}
        	break;

		case 4: 
		{ 
		/* Probably 32-bpp */
            		Uint32 *bufp;

            		bufp = (Uint32 *)screen->pixels + y*screen->pitch/4 + x;
            		*bufp = color;
        	}
        	break;

	} /* screen->format->BytesPerPixel */

	if ( SDL_MUSTLOCK(screen) ) 
	{
        	SDL_UnlockSurface(screen);
    	}
}

void DrawPixelColumnPageLine(SDL_Surface *screen, Uint16 column, Uint16 page, Uint16 line, Uint8 color)
{
	Uint16 x;
	Uint16 y;

	/* page 0-0x0f
	 * line 0-0x07
	 * column 0-0x7f
         */

	if (page > 0x0f || column > 0x7f || line > 0x07)
	{
		printf("page,column,line out of range\n");
		return;
	}

	y = 2*((0x0f-page)*8+line);
	x = 2*column;

switch (color)
{
	case 0:
		/* white */
		DrawPixel(screen,0xff,0xff,0xff,x,y);
		DrawPixel(screen,0xff,0xff,0xff,x+1,y);
		DrawPixel(screen,0xff,0xff,0xff,x,y+1);
		DrawPixel(screen,0xff,0xff,0xff,x+1,y+1);
		break;
	case 1:
		/* light gray */
		DrawPixel(screen,0xe5,0xe5,0xe5,x,y);
		DrawPixel(screen,0xe5,0xe5,0xe5,x+1,y);
		DrawPixel(screen,0xe5,0xe5,0xe5,x,y+1);
		DrawPixel(screen,0xe5,0xe5,0xe5,x+1,y+1);
		break;
	case 2:
		/* dark gray */
		DrawPixel(screen,0x7f,0x7f,0x7f,x,y);
		DrawPixel(screen,0x7f,0x7f,0x7f,x+1,y);
		DrawPixel(screen,0x7f,0x7f,0x7f,x,y+1);
		DrawPixel(screen,0x7f,0x7f,0x7f,x+1,y+1);
		break;
	case 3:
		/* black */
		DrawPixel(screen,0x00,0x00,0x00,x,y);
		DrawPixel(screen,0x00,0x00,0x00,x+1,y);
		DrawPixel(screen,0x00,0x00,0x00,x,y+1);
		DrawPixel(screen,0x00,0x00,0x00,x+1,y+1);
		break;
}

}

void DrawPixmap(SDL_Surface *screen,Uint16 *data)
{
	Uint16 column,page,line;
	Uint8 color,tmpH,tmpL;
	Uint16 cnt;

	column = 0;
	page = 0x0f;

	/* first 8 bits */
	/* second 8 bits */
	for (cnt=0;cnt<0x800;cnt++)
	{
		tmpL = *data & 0x00ff;
		tmpH = ((*data>>8) & 0x00ff);
		for (line=0; line<8; line++)
		{
			color = (Uint8)( ((tmpL>>line) & 0x01)<<1 | ((tmpH>>line) & 0x01) );
			DrawPixelColumnPageLine(screen,column,page,7-line,color);
		}

		data++;
		column++;

		if (column > 0x7f)
		{
			column = 0;
			page--;
		}

	}
}


void ClearScreen(SDL_Surface *screen)
{
	Uint8 color = SDL_MapRGB(screen->format,0xff,0xff,0xff);
	SDL_Rect r;
	r.x = 0;
	r.y = 0;
	r.w = screen->w;
	r.h = screen->h;

	SDL_FillRect(screen,&r,color);
}

void UpdateScreen(SDL_Surface *screen)
{
	SDL_UpdateRect(screen,0,0,screen->w,screen->h);
}

int main(int argc, char *argv[])
{
	SDL_Surface *screen;

	SDL_Event event;
	Uint32 i=0;
	Uint32 start = 0x00;
	Uint16 dat[0x800];
	char s[256];

	FILE *fp;

	if ( argc < 2 )
        {
		printf("Usage: %s <HD200 icon file>\n",argv[0]);
		printf("Use arrows, PgUP/PgDown to move\n");
		printf("Press 's' to save screenshot\n");
                return -1;
        }

	fp = fopen(argv[1],"r");

	if (fp == NULL)
	{
		printf("Can't open MPIO HD200 icon file\n");
		return 1;
	}

	if(SDL_Init(SDL_INIT_VIDEO)<0)
	{
		printf("Can not initialize SDL: %s\n",SDL_GetError());
		return 1;
	}

	atexit(SDL_Quit);

	screen = SDL_SetVideoMode(256, 256, 8, SDL_ANYFORMAT);

	for(;;)
	{
		if(SDL_PollEvent(&event))
		{
			if(event.type==SDL_QUIT)
			{
				/* We are finished */
				fclose(fp);
				return 0;
			}

			if(event.type==SDL_KEYDOWN)
			{
				switch (event.key.keysym.sym)
				{
				case SDLK_s:
					snprintf(s,256,"%s-%x.bmp","IconDump",start+0x800*i);
					printf("saved offset 0x%x to file %s\n",start+0x800*i,s);
					SDL_SaveBMP(screen,s);
					break;

				case SDLK_RIGHT:
					start = start-1;
					ClearScreen(screen);
					fseek(fp,start*2+0x1000*i,SEEK_SET);
					fread(dat,sizeof(Uint16),0x800,fp);
					printf("offset: 0x%x frame %d\n",start+0x800*i,i);
					DrawPixmap(screen,dat);
					UpdateScreen(screen);
					break;

				case SDLK_LEFT:
					start = start+1;
					ClearScreen(screen);
					fseek(fp,start*2+0x1000*i,SEEK_SET);
					fread(dat,sizeof(Uint16),0x800,fp);
					printf("offset: 0x%x frame %d\n",start+0x800*i,i);
					DrawPixmap(screen,dat);
					UpdateScreen(screen);
					break;

				case SDLK_PAGEDOWN:
					start = start-16;
					ClearScreen(screen);
					fseek(fp,start*2+0x1000*i,SEEK_SET);
					fread(dat,sizeof(Uint16),0x800,fp);
					printf("offset: 0x%x frame %d\n",start+0x800*i,i);
					DrawPixmap(screen,dat);
					UpdateScreen(screen);
					break;

				case SDLK_PAGEUP:
					start = start+16;
					ClearScreen(screen);
					fseek(fp,start*2+0x1000*i,SEEK_SET);
					fread(dat,sizeof(Uint16),0x800,fp);
					printf("offset: 0x%x frame %d\n",start+0x800*i,i);
					DrawPixmap(screen,dat);
					UpdateScreen(screen);
					break;

				case SDLK_DOWN:
					i++;
					ClearScreen(screen);
					fseek(fp,start*2+0x1000*i,SEEK_SET);
					fread(dat,sizeof(Uint16),0x800,fp);
					printf("offset: 0x%x frame %d\n",start+0x800*i,i);
					DrawPixmap(screen,dat);
					UpdateScreen(screen);
					break;

				case SDLK_UP:
					i--;
					ClearScreen(screen);
					fseek(fp,start*2+0x1000*i,SEEK_SET);
					fread(dat,sizeof(Uint16),0x800,fp);
					printf("offset: 0x%x frame %d\n",start+0x800*i,i);
					DrawPixmap(screen,dat);
					UpdateScreen(screen);
					break;

				default:
					break;
				}
			}

		}
		SDL_Delay(10);
	}


return 0;
}
