//--------------------------------------------------------------
// File     : gameboy_ub.h
//--------------------------------------------------------------

#ifndef GAMEBOY_UB_H_
#define GAMEBOY_UB_H_


#include "stm32f7xx.h"
#include "stm32f7xx_hal.h"
#include "z80_ub.h"



#define GB_EMULATOR_VERSION		"1.23"
#define GB_EMULATOR_DATE		"2018-04-28"

#define GB_INI_FILE			"gb_ub.ini"			// ini-file from sdcard
#define SBUFFER_SIZE		50					// dont change this value


// gb lcd position (pixel pos on screen)
#define GB_LCD_START_X		20	// minimum 16
#define GB_LCD_START_Y		0	// max 2

// GUI color
#define GB_BGND_COLOR		0x7C7C			// color of background
#define GB_FONT_COLOR		RGB_COL_BLACK	// font color
#define GB_FONT_H_COLOR		RGB_COL_WHITE	// header font color
#define GB_LOAD_BG_COLOR	RGB_COL_WHITE	// color of load screen background



// gb lcd startadr
#define LCD_LINE_LENGTH		(LCD_MAXX*2) // lenght of a lcd line in bytes
#define BG_START_ADR	(LCD_FRAME_BUFFER+LCD_FRAME_OFFSET)+(GB_LCD_START_Y*LCD_LINE_LENGTH)+(GB_LCD_START_X*2)

// external sdram to load cartridge data
#define SDRAM_CARTRIDGE_START_ADR	(SDRAM_START_ADR + 0x00400000)
#define SDRAM_CARTRIDGE_SIZE		(1024 * 16 * 125)	// 125 Banks (each 16kByte)





// BACKGROUND_TILE_MAP (width=32 blocks x height=32 blocks = 1024 Blocks)
// each block is one byte which points to an index of the WINDOW_BACKGROUND_TILE_DATA
#define BGTM_START_ADR_0	0x9800
#define BGTM_START_ADR_1	0x9C00

// WINDOW_TILE_MAP (width=32 blocks x height=32 blocks = 1024 Blocks)
// each block is one byte which points to an index of the WINDOW_BACKGROUND_TILE_DATA
#define WINTM_START_ADR_0	0x9800
#define WINTM_START_ADR_1	0x9C00

// WINDOW_BACKGROUND_TILE_DATA (256 blocks x 8bytes x 2 = 4096bytes)
// each block is 8pixel x 8pixel x 2bit color
#define WBGTD_START_ADR_0	0x8800	// index[-128..0..+127]
#define WBGTD_START_ADR_1	0x8000	// index[0..255]

// OBJ_TILE_DATA (256 blocks x 8bytes x 2 = 4096bytes)
// each block is 8pixel x 8pixel x 2bit color
#define OBJTD_START_ADR_1	0x8000	// index[0..255]


//--------------------------------------------------------------
// ISR
//--------------------------------------------------------------
#define ISR_ADR_VBLANK		0x40	// vblank interrupt (fired with 60Hz)
#define ISR_ADR_LCDCS		0x48	// lcdc status interrupt
#define ISR_ADR_TIMER		0x50	// timer overflow interrupt
#define ISR_ADR_SER			0x58	// serial interrupt
#define ISR_ADR_EXTI		0x60	// exti interrupt

//--------------------------------------------------------------
// OAM
//--------------------------------------------------------------
#define OAM_SPRITE_ADR		0xFE00	// oam data start
#define OAM_SPRITE_SIZE		0xA0	// oam size
#define OAM_SPRITE_CNT		40		// sprites

#define SPRITE_ATR_PRIO		0x80	// bit7
#define SPRITE_ATR_FLIPY	0x40	// bit6
#define SPRITE_ATR_FLIPX	0x20	// bit5
#define SPRITE_ATR_COL		0x10	// bit4

//--------------------------------------------------------------
// IO
//--------------------------------------------------------------
#define IO_ADR				0xFF00	// io regsiter
#define IO_ADR_P15			0x20	// P15 out (A,B,start,select)
#define IO_ADR_P14			0x10	// P14 out (right,left,up,down)
#define IO_ADR_P13			0x08	// P13 in (down,start)
#define IO_ADR_P12			0x04	// P12 in (up, select)
#define IO_ADR_P11			0x02	// P11 in (left, B)
#define IO_ADR_P10			0x01	// P10 in (right, A)

#define KEYCODE_CURSOR_NONE		0xEF
#define KEYCODE_CURSOR_RIGHT	0xEE
#define KEYCODE_CURSOR_LEFT		0xED
#define KEYCODE_CURSOR_UP		0xEB
#define KEYCODE_CURSOR_DOWN		0xE7

#define KEYCODE_BTN_NONE		0xDF
#define KEYCODE_BTN_A			0xDE
#define KEYCODE_BTN_B			0xDD
#define KEYCODE_BTN_SELECT		0xDB
#define KEYCODE_BTN_START		0xD7

//--------------------------------------------------------------
// DIV
//--------------------------------------------------------------
#define DIV_ADR				0xFF04	// divider register (incremented with 16kHz)

//--------------------------------------------------------------
// TIMA, TMA, TAC
//--------------------------------------------------------------
#define TIMA_ADR			0xFF05	// timer register
#define TMA_ADR				0xFF06	// reload value
#define TAC_ADR				0xFF07	// timer control
#define TAC_ADR_ENABLE		0x04	// bit2 (0=disable, 1=enable)
#define TAC_ADR_MODE		0x03	// bit0..1 = frq settings

//--------------------------------------------------------------
// IF
//--------------------------------------------------------------
#define IF_ADR				0xFF0F  // interrupt flag register (0=disable, 1=enable)
#define IF_ADR_EXTI			0x10	// bit4 exti P10-P13 (Joypad) (ISR60)
#define IF_ADR_SER			0x08	// bit3 serial transfer (ISR58)
#define IF_ADR_TIMER		0x04	// bit2 timer (ISR50)
#define IF_ADR_LCDC			0x02	// bit1 LCDC (ISR48)
#define IF_ADR_VBLANK		0x01	// bit0 v-blank (ISR40)

//--------------------------------------------------------------
// LCDC
//--------------------------------------------------------------
#define LCDC_ADR			0xFF40	// lcd controll register
#define LCDC_ADR_LCD		0x80	// bit7 LCD (0=off, 1=On)
#define LCDC_ADR_WTM		0x40	// bit6 window tile map (0=9800-9BFF, 1=9C00-9FFF)
#define LCDC_ADR_WDE		0x20	// bit5 window display (0=off, 1=On)
#define LCDC_ADR_BGTD		0x10	// bit4 background tile data (0=8800-97ff, 1=8000-8fff)
#define LCDC_ADR_BGTM		0x08	// bit3 background tile map (0=9800-9bff, 1=9c00-9fff)
#define LCDC_ADR_OBJS		0x04	// bit2 sprite size (0=8x8, 1=8x16)
#define LCDC_ADR_OBJE		0x02	// bit1 sprite enable (0=off, 1=on)
#define LCDC_ADR_BGD		0x01	// bit0 background display (0=off, 1=on)

//--------------------------------------------------------------
// STAT
//--------------------------------------------------------------
#define STAT_ADR			0xFF41	// status register (0=disable, 1=enable)
#define STAT_ADR_B7_NC		0x80	// bit7 nc
#define STAT_ADR_LYC		0x40	// bit6 LYC == LY interrupt enable
#define STAT_ADR_OAM		0x20	// bit5 OAM interrupt enable
#define STAT_ADR_VBLANK		0x10	// bit4 V-blank interrupt enable
#define STAT_ADR_HBLANK		0x08	// bit3 H-blank interrupt enable
#define STAT_ADR_CONC		0x04	// bit2 (0: LYC<>LY, 1:LYC=LY)	[read only]
#define STAT_ADR_MODE1		0x02	// bit1 lcd_mode				[read only]
#define STAT_ADR_MODE0		0x01	// bit0 lcd_mode				[read only]

//--------------------------------------------------------------
// SCY, SCX
//--------------------------------------------------------------
#define SCY_ADR				0xFF42	// scroll-Y register
#define SCX_ADR				0xFF43	// scroll-X register

//--------------------------------------------------------------
// LY, LYC
//--------------------------------------------------------------
#define LY_ADR				0xFF44	// LY register (0..153)
#define LYC_ADR				0xFF45	// LY compare register

//--------------------------------------------------------------
// DMA
//--------------------------------------------------------------
#define DMA_ADR				0xFF46	// dma register


//--------------------------------------------------------------
// PAL
//--------------------------------------------------------------
#define BGRDPAL_ADR			0xFF47	// background palette
#define OBJ0PAL_ADR			0xFF48	// sprite palette 0
#define OBJ1PAL_ADR			0xFF49	// sprite palette 1

//--------------------------------------------------------------
// WINXP, WINYP
//--------------------------------------------------------------
#define WIN_YP_ADR			0xFF4A	// window ypos (0..143)
#define WIN_XP_ADR			0xFF4B	// window xpos (0..166)

//--------------------------------------------------------------
// IE
//--------------------------------------------------------------
#define IE_ADR				0xFFFF  // interrupt enable register (0=disable, 1=enable)
#define IE_ADR_EXTI			0x10	// bit4 exti P10-P13
#define IE_ADR_SER			0x08	// bit3 serial transfer
#define IE_ADR_TIMER		0x04	// bit2 timer
#define IE_ADR_LCDC			0x02	// bit1 LCDC
#define IE_ADR_VBLANK		0x01	// bit0 v-blank


//--------------------------------------------------------------
// cartridge
//--------------------------------------------------------------
#define CARTRIDGE_START_ADR		0x0100	// cartridge start
#define CARTRIDGE_LOGO_ADR		0x0104	// logo start
#define CARTRIDGE_LOGO_SIZE		48
#define CARTRIDGE_TITLE_ADR		0x0134	// title start
#define CARTRIDGE_TITLE_SIZE	16
#define CARTRIDGE_TYPE_ADR		0x0147	// cartridge type
#define CARTRIDGE_ROM_SIZE_ADR	0x0148	// rom size
#define CARTRIDGE_RAM_SIZE_ADR	0x0149	// ram size


//--------------------------------------------------------------
// Memory Controller defines
//--------------------------------------------------------------
#define SUPPORTED_MBC_VERSION	1		// [0=w/o MBC, 1=MBC1]
#define MBC0_INTERNAL_REGISTERS	0xFF00	// above this address are gameboy internal registers
#define MBC1_WR_RAM_EN			0x0000	// ram enable			[0x0000..0x1FFF]
#define MBC1_WR_BANK_LO			0x2000	// rom bank lo			[0x2000..0x3FFF]
#define MBC1_WR_BANK_HI			0x4000	// rom bank hi			[0x4000..0x5FFF]
#define MBC1_WR_MODE_SELECT		0x6000	// ram/rom mode select	[0x6000..0x7FFF]
#define MBC1_RD_BANKN			0x4000	// read bank [1..n]		[0x4000..0x7FFF]
#define MBC1_RD_BANK_SIZE		0x4000	// read bank size



//--------------------------------------------------------------
// other
//-------------------------------------------------------------

#define BOOTROM_LOGO_ADR		0x00A8	// logo start

#define WIN_DX					7		// windows x_offset

#define INFO_UART_MSG			1		// set 1 to enable info msg
#define ERROR_UART_MSG			1		// set 1 to enable error msg


//--------------------------------------------------------------
// tile tables to avoid converting tile index into tile nr
//--------------------------------------------------------------
// tile table unsigned nr [0..255]
static const uint8_t u8_tile_nr[256] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
};

// tile table signed nr [-128..+127]
static const uint8_t s8_tile_nr[256] = {
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
};


//--------------------------------------------------------------
// color
//--------------------------------------------------------------

// color table (bright to dark)
static const uint16_t col_tables[8][4]={
{0xa71f,0x4dbf,0x2b7e,0x281f}, // 0 blue
{0xdd9f,0x9b7e,0x693f,0x4817}, // 1 purple
{0xfd9f,0xfb7f,0xd019,0x9010}, // 2 violet
{0xf517,0xf2b2,0xe02b,0xa065}, // 3 red
{0xff14,0xfd09,0xe303,0x80e1}, // 4 orange
{0xf6cf,0xf5c3,0xabe2,0x51a1}, // 5 brown
{0xd7ef,0xb7e4,0x05c0,0x03c0}, // 6 green
{0x2fdf,0x2f3a,0x1c30,0x120b}  // 7 blue2
};

// default colors
#define DEFAULT_BG_COL_INDEX	4
#define DEFAULT_OBJ_COL_INDEX	6


// helper table for bit0 in color table
static const uint8_t col_index_l[129]={
0,1,1,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
};
// helper table for bit1 in color table
static const uint8_t col_index_h[129]={
0,2,2,0,2,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2
};
#define SPRITE_TRANSPARENT	0		// index for transparent color

// helper table for tile mask
static const uint8_t tile_mask[2][8] = {
{0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01},
{0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE},
};

//--------------------------------------------------------------
// display
//--------------------------------------------------------------


// display values (don't change)
#define VBLANK_START		144		// visible lines = 0..143
#define MAX_YPOS 			153		// vblank lines = 9
// visible size
#define GB_LCD_WIDTH		160				// width = 160pixel
#define GB_LCD_HEIGHT		VBLANK_START	// height = 144 pixel




//--------------------------------------------------------------
// sprites
//--------------------------------------------------------------

// sprite offset values
#define SPRITE_DX			8
#define SPRITE_DY			16

// sprite width
#define SPRITE_WIDTH		8

//--------------------------------------------------------------
// timings
//--------------------------------------------------------------

// timings from gameboy PDF
// info: gameboy quarz = 4,194304MHz
// 1 mcu cycle = 1/4194304 = 238ns
// all timings are related to this 238ns/CYCLE

#define LCD_MODE0_CYCLES	204		// duration about 48us (H-Blank period)
#define LCD_MODE1_CYCLES	4560	// duration about 1,08ms (V-Blank period)
#define LCD_MODE2_CYCLES	80		// duration about 19us (LCD is reading from AOM memory)
#define LCD_MODE3_CYCLES	172		// duration about 41us (LCD is reading from AOM and VRAM)
#define LCD_LINE_CYCLES		(LCD_MODE0_CYCLES + LCD_MODE2_CYCLES + LCD_MODE3_CYCLES)	// duration about 108us (single scanline)

#define DIV_COUNTER_CYCLES	256		// duration about 61us (16,384kHz)

#define TIM_MODE0_CYCLES	1024	// frq = 1 kHz
#define TIM_MODE1_CYCLES	16		// frq = 262 kHz
#define TIM_MODE2_CYCLES	64		// frq = 65 kHz
#define TIM_MODE3_CYCLES	256		// frq = 16 kHz

#define GB_EMULATION_FPS	60		// default emulation fps
#define DELAY_OFFSET		10000	// speed of fps regulation (higher means faster but inaccurate)
//--------------------------------------------------------------

//--------------------------------------------------------------
// default key bindings
//--------------------------------------------------------------
#define KEY_NR_UP			26	// 'w'
#define KEY_NR_DOWN			22	// 's'
#define KEY_NR_LEFT			4	// 'a'
#define KEY_NR_RIGHT		7	// 'd'
#define KEY_NR_A			18	// 'o'
#define KEY_NR_B			19	// 'p'
#define KEY_NR_START		40	// ENTER
#define KEY_NR_SELEC		44	// SPACE




//--------------------------------------------------------------
// BMP header
// (480x272 landscape)
//--------------------------------------------------------------
static const uint8_t BMP_HEADER[54]={
0x42,0x4D,0x36,0xFA,0x05,0x00,0x00,0x00,0x00,0x00, // ID=BM, Filsize=(480x272x3+54)
0x36,0x00,0x00,0x00,0x28,0x00,0x00,0x00,           // Offset=54d, Headerlen=40d
0xE0,0x01,0x00,0x00,0x10,0x01,0x00,0x00,0x01,0x00, // W=480d, H=272d (landscape)
0x18,0x00,0x00,0x00,0x00,0x00,0x00,0xFA,0x05,0x00, // 24bpp, unkomprimiert, Data=(480x272x3)
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,           // nc
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};          // nc



typedef struct {
	const uint8_t *tile_table;	// background tile table
	uint16_t BGTM_start_adr;	// background tile map start adr
	uint16_t WBGTD_start_adr;	// window and background tile data start adr
	uint16_t WINTM_start_adr;	// window tile map start adr
	uint8_t sprite_height;		// sprite height
	uint8_t lcd_mode;			// used for lcd mode [0..3]
	uint8_t lcdc_status;		// reoad only bit0..2 of register 0xFF41
	uint16_t bg_col_table[4];
	uint16_t obj_col_table[4][2];
	uint32_t mcu_cycl_cnt;
	uint32_t div_cycl_cnt;
	uint8_t tim_enable; // timer
	uint32_t tim_cycl_cnt;
	uint32_t tim_cycl_ovf;
	uint8_t px_cnt;
}Shadow_t;
Shadow_t Shadow;




// used for USB keyboard
typedef struct {
	uint8_t code_cursor; // GB curser [NONE, up,down,left,right]
	uint8_t code_btn; // GB buttons [NONE, A,B,START,SELECT]
	uint32_t delay_cnt;
	uint8_t status;	// connected, disconnected
}Key_t;

// used for FPS display
typedef struct {
	uint32_t cnt;
	uint8_t fps;
	uint8_t flag;
}FrameCnt_t;

// used to hit 60fps
typedef struct {
	uint32_t delay_cnt;
	uint32_t delay_ovf;
	uint8_t current_fps;
	uint8_t target_fps;
	uint8_t flag;
}Timing_t;

// used for color settings
typedef struct {
	uint8_t bg_col_index;		// background table index
	uint8_t bg_col_value;
	uint8_t obj_col_index;		// sprites table index
	uint8_t obj0_col_value;
	uint8_t obj1_col_value;
}Col_t;


// uart load status
typedef enum {
	LOADING_DISABLE = 0,
	LOADING_WAITING,
	LOADING_RUNNING,
	LOADING_TIMEOUT,
	LOADING_ERROR
}LStatus_t;

// used to load a rom from UART
typedef struct {
	LStatus_t status;
	uint32_t timeout_cnt;
	uint32_t timeout_ovf;
	uint32_t rom_size;
}LoadUart_t;

// sd load status
typedef enum {
	SD_LOADING_DISABLE = 0,
	SD_LOADING_SELECT,
	SD_LOADING_COPY,
	SD_LOADING_ERROR
}SDLStatus_t;

// used to load a rom from SD
typedef struct {
	SDLStatus_t status;
	uint32_t current_item;
	uint32_t first_line;
	uint32_t items;
	char name[15];
	uint8_t flags;	// bit0=refresh, bit1=file
}LoadSD_t;


// used for mem controller
typedef struct {
	uint8_t logo_check;			// 0=ok, 1=error
	char title[CARTRIDGE_TITLE_SIZE+1];
	uint8_t type;
	uint8_t rom_size;
	uint8_t ram_size;
	uint8_t rom_bank_nr;
	uint32_t bank_offset;
	uint8_t *sdram;		// pointer to external sdram for cartridge data
}MemCtrl_t;

// emulator status
typedef enum {
	EMULATOR_RUNNING = 0,
	EMULATOR_ERROR,
	EMULATOR_STOPPED,
	EMULATOR_LOAD_UART,
	EMULATOR_LOAD_SD,
}Status_t;

// emulator error
typedef enum {
	ERROR_NONE = 0,
	ERROR_OPCODE,
	ERROR_LOGO,
	ERROR_MBC
}Error_t;

// screen functions
typedef struct {
	uint8_t mode;
	uint8_t x_mul;
	uint32_t (*fptr_ptlp) (uint32_t tile_ram_adr, uint32_t lcd_adr, uint8_t tile_pixel_mask);
	uint32_t (*fptr_ptl) (uint32_t tile_ram_adr, uint32_t lcd_adr);
	void (*fptr_pstl [2][2]) (uint32_t tile_ram_adr, uint32_t lcd_adr, uint8_t p);
	void (*fct_clrl [2][2]) (uint32_t lcd_adr);
	void (*fct_clrr [2][2]) (uint32_t lcd_adr);
	void (*fct_copy [2][2]) (uint32_t lcd_adr);
}Screen_t;

typedef struct {
	uint8_t ok;
	uint16_t bgcol1;
	uint16_t bgcol2;
	uint16_t fontcol1;
	uint16_t fontcol2;
	uint8_t use_sdcard_colors;
	uint16_t bg_table[4];
	uint16_t obj_table[4];
	uint8_t keytable[8]; // up,down,left,right,a,b,start,select
	uint8_t dbg_msg;
	uint8_t buf[20];
}Ini_t;

// gameboy main struct
typedef struct {
	Key_t key;
	FrameCnt_t frame;
	Timing_t timing;
	Col_t col;
	LoadUart_t load;
	LoadSD_t load_sd;
	MemCtrl_t mem_ctrl;
	Status_t status;
	Error_t err_nr;
	Screen_t screen;
	Ini_t ini;
}GB_t;
GB_t GB;



// cartridge file format
typedef struct {
  const uint8_t *table; // data
  uint32_t size;
}UB_GB_File;

// game roms
extern UB_GB_File Boot_ROM;
extern UB_GB_File Tetris_ROM;
extern UB_GB_File castelian;
extern UB_GB_File boulder;
extern UB_GB_File Kwirk_ROM;





//--------------------------------------------------------------
void gameboy_init(void);
void gameboy_boot_flash(uint8_t game_nr);
void gameboy_boot_ram(void);
void gameboy_boot_sdram(void);
void gameboy_single_step(void);
void gameboy_set_palette(uint8_t table_nr, uint8_t color_values);
void gameboy_wr_internal_register(uint16_t adr, uint8_t value);
void gameboy_wr_into_rom(uint16_t adr, uint8_t value);
uint8_t gameboy_rd_from_rom(uint16_t adr);
void gameboy_set_screenmode(void);


#endif /* GAMEBOY_UB_H_ */
