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


#define SPRITE_TYPE_COLOR 0

#define SPRITE_TYPE_MONO 1

typedef struct {
  unsigned char sprite_num;
  unsigned char width;
  unsigned char height;
} viewtube_4bit_color_sprite_t;

typedef struct {
  unsigned char sprite_num;
  unsigned char red;
  unsigned char green;
  unsigned char blue;

} viewtube_mono_color_sprite_t;

typedef union {
  viewtube_4bit_color_sprite_t color;
  viewtube_mono_color_sprite_t mono;
} viewtube_sprite_obj_t;

typedef struct {
  unsigned char type;
  unsigned char jump;
  unsigned char table_index;
  unsigned short new_x;
  unsigned short new_y;
  viewtube_sprite_obj_t obj;
} viewtube_sprite_t;

viewtube_sprite_t sprite_letter_one = {
                                          .type = SPRITE_TYPE_MONO,
                                          .jump = 0,
                                          .table_index = 4,
                                          .new_x = 150,
                                          .new_y = 450,
                                          .obj = {.mono = {
                                            .sprite_num = 7,
                                            .red = 0xff,
                                            .green = 0xff,
                                            .blue = 0xff
                                          }}
                                        };
  viewtube_sprite_t sprite_letter_two = {
                                          .type = SPRITE_TYPE_MONO,
                                          .jump = 0,
                                          .table_index = 5,
                                          .new_x = 158,
                                          .new_y = 450,
                                          .obj = {.mono = {
                                            .sprite_num = 8,
                                            .red = 0xff,
                                            .green = 0xff,
                                            .blue = 0xff
                                          }}
                                        };

  viewtube_sprite_t sprite_car_one = {
                                          .type = SPRITE_TYPE_COLOR,
                                          .jump = 0,
                                          .table_index = 0,
                                          .new_x = 0,
                                          .new_y = 100,
                                          .obj = {.color = {
                                            .sprite_num = 0,
                                            .width = 17,
                                            .height = 26
                                          }}
                                        };
  viewtube_sprite_t sprite_car_two = {
                                          .type = SPRITE_TYPE_COLOR,
                                          .jump = 0,
                                          .table_index = 1,
                                          .new_x = 300,
                                          .new_y = 400,
                                          .obj = {.color = {
                                            .sprite_num = 0,
                                            .width = 17,
                                            .height = 26
                                          }}
                                        };
  viewtube_sprite_t sprite_car_three = {
                                          .type = SPRITE_TYPE_COLOR,
                                          .jump = 0,
                                          .table_index = 2,
                                          .new_x = 200,
                                          .new_y = 400,
                                          .obj = {.color = {
                                            .sprite_num = 0,
                                            .width = 17,
                                            .height = 26
                                          }}
                                        };
  viewtube_sprite_t sprite_car_four = {
                                          .type = SPRITE_TYPE_COLOR,
                                          .jump = 0,
                                          .table_index = 3,
                                          .new_x = 500,
                                          .new_y = 0,
                                          .obj = {.color = {
                                            .sprite_num = 0,
                                            .width = 17,
                                            .height = 26
                                          }}
                                        };
static void write_sprite_to_table(viewtube_sprite_t * sprite)
{
	uint32_t val = 0;
	val |= ((sprite->table_index << 24) & 0xFF000000);
	// set table offset value

	val |= ((sprite->type << 23) & 0x00800000); 
	// set table type; mask bit at offset 23


	if(SPRITE_TYPE_COLOR == sprite->type)
	{

		val |= ((sprite->obj.color.sprite_num << 16) & 0x001F0000); 
		//set new sprite #; mask 5 bits at offsets 20:16

		val |= ((sprite->obj.color.width << 8) & 0x00001F00); 
		// set width; mask 5 bits at offsets 12:8

		val |= ((sprite->obj.color.height) & 0x0000001F); 
		// set height; mask 5 bits at offsets 4:0

	} else { //mono
		val |= ((sprite->obj.color.sprite_num << 16) & 0x007F0000); 
		//set new sprite #; mask 5 bits at offsets 20:16

		val |= ((sprite->obj.mono.red << 7) & 0x00000F00); 
		// set red; mask 4 bits at offsets 11:8
		
		val |= ((sprite->obj.mono.green << 3) & 0x000000F0); 
		// set green; mask 4 bits at offsets 7:4

		val |= ((sprite->obj.mono.blue) & 0x0000000F); 
		// set blue; mask 4 bits at offsets 3:0
	}
	printf("0x%08x\n",val);
}

static void write_new_sprite_pos(viewtube_sprite_t * sprite)
{
	uint32_t val = 0;

	val |= ((sprite->table_index << 24) & 0xFF000000);
	// set table offset value

	val |= ((sprite->jump<< 23) & 0x00800000); 
	// set whether to jump to position or slide; mask bit at offset 23

	val |= ((sprite->new_y << 11 ) & 0x003FF800); 
	// set y_pos; mask 11 bits at offset 21:11

	val |= ((sprite->new_x ) & 0x000007FF); 
	// set x_pos; mask 11 bits at offset 10:0

	printf("0x%08x\n",val);
}


void main()
{
	sprite_letter_two.obj.mono.sprite_num = 0;
  printf("make I A: ");
	write_sprite_to_table(&sprite_letter_two);
  printf("hide train 1: ");
  sprite_car_one.obj.color.sprite_num = 1;
  write_sprite_to_table(&sprite_car_one);
  printf("jump train 2 to 100,100: ");
  sprite_car_two.new_x = 100;
  sprite_car_two.new_y = 100;
  sprite_car_two.jump = 1;
  write_new_sprite_pos(&sprite_car_two);
  printf("slide train 3 to 600,400: ");
  sprite_car_three.new_x = 600;
  sprite_car_three.new_y = 400;
  sprite_car_three.jump = 0;
  write_new_sprite_pos(&sprite_car_three);
}
