/**************************************************************************//**
* @file     2d.c
* @brief    N9H30 GE2D driver source file
*
* @note
* SPDX-License-Identifier: Apache-2.0
* Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "N9H30.h"
#include "sys.h"
#include "2d.h"

/** @addtogroup N9H30_Device_Driver N9H30 Device Driver
  @{
*/

/** @addtogroup N9H30_GE2D_Driver GE2D Driver
  @{
*/

/** @addtogroup N9H30_GE2D_EXPORTED_CONSTANTS GE2D Exported Constants
  @{
*/

/// @cond HIDDEN_SYMBOLS
static unsigned int GFX_Mem = 0;
static unsigned int GFX_BPP;
static unsigned int GFX_WIDTH;
static unsigned int GFX_HEIGHT;
static unsigned int GFX_PITCH;
static unsigned int GFX_SIZE;
#if defined ( __GNUC__ ) && !(__CC_ARM)
__attribute__((aligned(32))) static void *GFX_START_ADDR;
__attribute__((aligned(32))) static void *MONO_SOURCE_ADDR;
__attribute__((aligned(32))) static void *COLOR_SOURCE_ADDR;
__attribute__((aligned(32))) static void *CMODEL_START_ADDR;
__attribute__((aligned(32))) static void *GFX_OFFSCREEN_ADDR;
__attribute__((aligned(32))) static void *GFX_PAT_ADDR;
#else
static __align(32) void *GFX_START_ADDR;
static __align(32) void *MONO_SOURCE_ADDR;
static __align(32) void *COLOR_SOURCE_ADDR;
static __align(32) void *CMODEL_START_ADDR;
static __align(32) void *GFX_OFFSCREEN_ADDR;
static __align(32) void *GFX_PAT_ADDR;
#endif

void *Orig_GFX_START_ADDR;
void *Orig_MONO_SOURCE_ADDR;
void *Orig_COLOR_SOURCE_ADDR;
void *Orig_CMODEL_START_ADDR;
void *Orig_GFX_OFFSCREEN_ADDR;
void *Orig_GFX_PAT_ADDR;

#define  PN   1  // Quadrant 1
#define  NN   2  // Quadrant 2
#define  NP   3  // Quadrant 3
#define  PP   4  // Quadrant 4

#define ABS(x)      (((x)>0)?(x):-(x))
#define MAX(a,b)    (((a)>(b))?(a):(b))

/* octant code of line drawing */

#define XpYpXl      (0<<1)   // XY octant position is 1~3 in Control register
#define XpYpYl      (1<<1)
#define XpYmXl      (2<<1)
#define XpYmYl      (3<<1)
#define XmYpXl      (4<<1)
#define XmYpYl      (5<<1)
#define XmYmXl      (6<<1)
#define XmYmYl      (7<<1)

static MONOPATTERN MonoPatternData[6] = {
    {0x00000000, 0xff000000}, // HS_HORIZONTAL
    {0x08080808, 0x08080808}, // HS_VERTICAL
    {0x80402010, 0x08040201}, // HS_FDIAGONAL
    {0x01020408, 0x10204080}, // HS_BDIAGONAL
    {0x08080808, 0xff080808}, // HS_CROSS
    {0x81422418, 0x18244281}  // HS_DIAGCROSS
};

static char _DrawMode = MODE_OPAQUE;
static UINT32 _ColorKey = COLOR_KEY;
static UINT32 _ColorKeyMask = 0xFFFFFF;

static BOOL _EnableAlpha = FALSE;
static int _AlphaKs, _AlphaKd;
static BOOL _ClipEnable = FALSE;
static BOOL _OutsideClip = FALSE;
static UINT32 _ClipTL, _ClipBR;
static int _PatternType;

static unsigned	char FontData8[256][8] = {
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},  //0
    {0x7E,0x81,0xA5,0x81,0xBD,0x99,0x81,0x7E},  //1
    {0x7E,0xFF,0xDB,0xFF,0xC3,0xE7,0xFF,0x7E},  //2
    {0x6C,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00},  //3
    {0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00},  //4
    {0x38,0x7C,0x38,0xFE,0xFE,0x92,0x10,0x7C},  //5
    {0x00,0x10,0x38,0x7C,0xFE,0x7C,0x38,0x7C},  //6
    {0x00,0x00,0x18,0x3C,0x3C,0x18,0x00,0x00},  //7
    {0xFF,0xFF,0xE7,0xC3,0xC3,0xE7,0xFF,0xFF},  //8
    {0x00,0x3C,0x66,0x42,0x42,0x66,0x3C,0x00},  //9
    {0xFF,0xC3,0x99,0xBD,0xBD,0x99,0xC3,0xFF},  //10
    {0x0F,0x07,0x0F,0x7D,0xCC,0xCC,0xCC,0x78},  //11
    {0x3C,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18},  //12
    {0x3F,0x33,0x3F,0x30,0x30,0x70,0xF0,0xE0},  //13
    {0x7F,0x63,0x7F,0x63,0x63,0x67,0xE6,0xC0},  //14
    {0x99,0x5A,0x3C,0xE7,0xE7,0x3C,0x5A,0x99},  //15
    {0x80,0xE0,0xF8,0xFE,0xF8,0xE0,0x80,0x00},  //16
    {0x02,0x0E,0x3E,0xFE,0x3E,0x0E,0x02,0x00},  //17
    {0x18,0x3C,0x7E,0x18,0x18,0x7E,0x3C,0x18},  //18
    {0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x00},  //19
    {0x7F,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x00},  //20
    {0x3E,0x63,0x38,0x6C,0x6C,0x38,0x86,0xFC},  //21
    {0x00,0x00,0x00,0x00,0x7E,0x7E,0x7E,0x00},  //22
    {0x18,0x3C,0x7E,0x18,0x7E,0x3C,0x18,0xFF},  //23
    {0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x00},  //24
    {0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00},  //25
    {0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00},  //26
    {0x00,0x30,0x60,0xFE,0x60,0x30,0x00,0x00},  //27
    {0x00,0x00,0xC0,0xC0,0xC0,0xFE,0x00,0x00},  //28
    {0x00,0x24,0x66,0xFF,0x66,0x24,0x00,0x00},  //29
    {0x00,0x18,0x3C,0x7E,0xFF,0xFF,0x00,0x00},  //30
    {0x00,0xFF,0xFF,0x7E,0x3C,0x18,0x00,0x00},  //31
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},  //32
    {0x18,0x3C,0x3C,0x18,0x18,0x00,0x18,0x00},  //33
    {0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00},  //34
    {0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00},  //35
    {0x18,0x7E,0xC0,0x7C,0x06,0xFC,0x18,0x00},  //36
    {0x00,0xC6,0xCC,0x18,0x30,0x66,0xC6,0x00},  //37
    {0x38,0x6C,0x38,0x76,0xDC,0xCC,0x76,0x00},  //38
    {0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00},  //39
    {0x18,0x30,0x60,0x60,0x60,0x30,0x18,0x00},  //40
    {0x60,0x30,0x18,0x18,0x18,0x30,0x60,0x00},  //41
    {0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00},  //42
    {0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00},  //43
    {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30},  //44
    {0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00},  //45
    {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00},  //46
    {0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00},  //47
    {0x7C,0xCE,0xDE,0xF6,0xE6,0xC6,0x7C,0x00},  //48
    {0x30,0x70,0x30,0x30,0x30,0x30,0xFC,0x00},  //49
    {0x78,0xCC,0x0C,0x38,0x60,0xCC,0xFC,0x00},  //50
    {0x78,0xCC,0x0C,0x38,0x0C,0xCC,0x78,0x00},  //51
    {0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x1E,0x00},  //52
    {0xFC,0xC0,0xF8,0x0C,0x0C,0xCC,0x78,0x00},  //53
    {0x38,0x60,0xC0,0xF8,0xCC,0xCC,0x78,0x00},  //54
    {0xFC,0xCC,0x0C,0x18,0x30,0x30,0x30,0x00},  //55
    {0x78,0xCC,0xCC,0x78,0xCC,0xCC,0x78,0x00},  //56
    {0x78,0xCC,0xCC,0x7C,0x0C,0x18,0x70,0x00},  //57
    {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00},  //58
    {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30},  //59
    {0x18,0x30,0x60,0xC0,0x60,0x30,0x18,0x00},  //60
    {0x00,0x00,0x7E,0x00,0x7E,0x00,0x00,0x00},  //61
    {0x60,0x30,0x18,0x0C,0x18,0x30,0x60,0x00},  //62
    {0x3C,0x66,0x0C,0x18,0x18,0x00,0x18,0x00},  //63
    {0x7C,0xC6,0xDE,0xDE,0xDC,0xC0,0x7C,0x00},  //64
    {0x30,0x78,0xCC,0xCC,0xFC,0xCC,0xCC,0x00},  //65
    {0xFC,0x66,0x66,0x7C,0x66,0x66,0xFC,0x00},  //66
    {0x3C,0x66,0xC0,0xC0,0xC0,0x66,0x3C,0x00},  //67
    {0xF8,0x6C,0x66,0x66,0x66,0x6C,0xF8,0x00},  //68
    {0xFE,0x62,0x68,0x78,0x68,0x62,0xFE,0x00},  //69
    {0xFE,0x62,0x68,0x78,0x68,0x60,0xF0,0x00},  //70
    {0x3C,0x66,0xC0,0xC0,0xCE,0x66,0x3A,0x00},  //71
    {0xCC,0xCC,0xCC,0xFC,0xCC,0xCC,0xCC,0x00},  //72
    {0x78,0x30,0x30,0x30,0x30,0x30,0x78,0x00},  //73
    {0x1E,0x0C,0x0C,0x0C,0xCC,0xCC,0x78,0x00},  //74
    {0xE6,0x66,0x6C,0x78,0x6C,0x66,0xE6,0x00},  //75
    {0xF0,0x60,0x60,0x60,0x62,0x66,0xFE,0x00},  //76
    {0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0x00},  //77
    {0xC6,0xE6,0xF6,0xDE,0xCE,0xC6,0xC6,0x00},  //78
    {0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x38,0x00},  //79
    {0xFC,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00},  //80
    {0x7C,0xC6,0xC6,0xC6,0xD6,0x7C,0x0E,0x00},  //81
    {0xFC,0x66,0x66,0x7C,0x6C,0x66,0xE6,0x00},  //82
    {0x7C,0xC6,0xE0,0x78,0x0E,0xC6,0x7C,0x00},  //83
    {0xFC,0xB4,0x30,0x30,0x30,0x30,0x78,0x00},  //84
    {0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xFC,0x00},  //85
    {0xCC,0xCC,0xCC,0xCC,0xCC,0x78,0x30,0x00},  //86
    {0xC6,0xC6,0xC6,0xC6,0xD6,0xFE,0x6C,0x00},  //87
    {0xC6,0xC6,0x6C,0x38,0x6C,0xC6,0xC6,0x00},  //88
    {0xCC,0xCC,0xCC,0x78,0x30,0x30,0x78,0x00},  //89
    {0xFE,0xC6,0x8C,0x18,0x32,0x66,0xFE,0x00},  //90
    {0x78,0x60,0x60,0x60,0x60,0x60,0x78,0x00},  //91
    {0xC0,0x60,0x30,0x18,0x0C,0x06,0x02,0x00},  //92
    {0x78,0x18,0x18,0x18,0x18,0x18,0x78,0x00},  //93
    {0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00},  //94
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF},  //95
    {0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00},  //96
    {0x00,0x00,0x78,0x0C,0x7C,0xCC,0x76,0x00},  //97
    {0xE0,0x60,0x60,0x7C,0x66,0x66,0xDC,0x00},  //98
    {0x00,0x00,0x78,0xCC,0xC0,0xCC,0x78,0x00},  //99
    {0x1C,0x0C,0x0C,0x7C,0xCC,0xCC,0x76,0x00},  //100
    {0x00,0x00,0x78,0xCC,0xFC,0xC0,0x78,0x00},  //101
    {0x38,0x6C,0x64,0xF0,0x60,0x60,0xF0,0x00},  //102
    {0x00,0x00,0x76,0xCC,0xCC,0x7C,0x0C,0xF8},  //103
    {0xE0,0x60,0x6C,0x76,0x66,0x66,0xE6,0x00},  //104
    {0x30,0x00,0x70,0x30,0x30,0x30,0x78,0x00},  //105
    {0x0C,0x00,0x1C,0x0C,0x0C,0xCC,0xCC,0x78},  //106
    {0xE0,0x60,0x66,0x6C,0x78,0x6C,0xE6,0x00},  //107
    {0x70,0x30,0x30,0x30,0x30,0x30,0x78,0x00},  //108
    {0x00,0x00,0xCC,0xFE,0xFE,0xD6,0xD6,0x00},  //109
    {0x00,0x00,0xB8,0xCC,0xCC,0xCC,0xCC,0x00},  //110
    {0x00,0x00,0x78,0xCC,0xCC,0xCC,0x78,0x00},  //111
    {0x00,0x00,0xDC,0x66,0x66,0x7C,0x60,0xF0},  //112
    {0x00,0x00,0x76,0xCC,0xCC,0x7C,0x0C,0x1E},  //113
    {0x00,0x00,0xDC,0x76,0x62,0x60,0xF0,0x00},  //114
    {0x00,0x00,0x7C,0xC0,0x70,0x1C,0xF8,0x00},  //115
    {0x10,0x30,0xFC,0x30,0x30,0x34,0x18,0x00},  //116
    {0x00,0x00,0xCC,0xCC,0xCC,0xCC,0x76,0x00},  //117
    {0x00,0x00,0xCC,0xCC,0xCC,0x78,0x30,0x00},  //118
    {0x00,0x00,0xC6,0xC6,0xD6,0xFE,0x6C,0x00},  //119
    {0x00,0x00,0xC6,0x6C,0x38,0x6C,0xC6,0x00},  //120
    {0x00,0x00,0xCC,0xCC,0xCC,0x7C,0x0C,0xF8},  //121
    {0x00,0x00,0xFC,0x98,0x30,0x64,0xFC,0x00},  //122
    {0x1C,0x30,0x30,0xE0,0x30,0x30,0x1C,0x00},  //123
    {0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00},  //124
    {0xE0,0x30,0x30,0x1C,0x30,0x30,0xE0,0x00},  //125
    {0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00},  //126
    {0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0x00},  //127
    {0x7C,0xC6,0xC0,0xC6,0x7C,0x0C,0x06,0x7C},  //128
    {0x00,0xCC,0x00,0xCC,0xCC,0xCC,0x76,0x00},  //129
    {0x1C,0x00,0x78,0xCC,0xFC,0xC0,0x78,0x00},  //130
    {0x7E,0x81,0x3C,0x06,0x3E,0x66,0x3B,0x00},  //131
    {0xCC,0x00,0x78,0x0C,0x7C,0xCC,0x76,0x00},  //132
    {0xE0,0x00,0x78,0x0C,0x7C,0xCC,0x76,0x00},  //133
    {0x30,0x30,0x78,0x0C,0x7C,0xCC,0x76,0x00},  //134
    {0x00,0x00,0x7C,0xC6,0xC0,0x78,0x0C,0x38},  //135
    {0x7E,0x81,0x3C,0x66,0x7E,0x60,0x3C,0x00},  //136
    {0xCC,0x00,0x78,0xCC,0xFC,0xC0,0x78,0x00},  //137
    {0xE0,0x00,0x78,0xCC,0xFC,0xC0,0x78,0x00},  //138
    {0xCC,0x00,0x70,0x30,0x30,0x30,0x78,0x00},  //139
    {0x7C,0x82,0x38,0x18,0x18,0x18,0x3C,0x00},  //140
    {0xE0,0x00,0x70,0x30,0x30,0x30,0x78,0x00},  //141
    {0xC6,0x10,0x7C,0xC6,0xFE,0xC6,0xC6,0x00},  //142
    {0x30,0x30,0x00,0x78,0xCC,0xFC,0xCC,0x00},  //143
    {0x1C,0x00,0xFC,0x60,0x78,0x60,0xFC,0x00},  //144
    {0x00,0x00,0x7F,0x0C,0x7F,0xCC,0x7F,0x00},  //145
    {0x3E,0x6C,0xCC,0xFE,0xCC,0xCC,0xCE,0x00},  //146
    {0x78,0x84,0x00,0x78,0xCC,0xCC,0x78,0x00},  //147
    {0x00,0xCC,0x00,0x78,0xCC,0xCC,0x78,0x00},  //148
    {0x00,0xE0,0x00,0x78,0xCC,0xCC,0x78,0x00},  //149
    {0x78,0x84,0x00,0xCC,0xCC,0xCC,0x76,0x00},  //150
    {0x00,0xE0,0x00,0xCC,0xCC,0xCC,0x76,0x00},  //151
    {0x00,0xCC,0x00,0xCC,0xCC,0x7C,0x0C,0xF8},  //152
    {0xC3,0x18,0x3C,0x66,0x66,0x3C,0x18,0x00},  //153
    {0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0x78,0x00},  //154
    {0x18,0x18,0x7E,0xC0,0xC0,0x7E,0x18,0x18},  //155
    {0x38,0x6C,0x64,0xF0,0x60,0xE6,0xFC,0x00},  //156
    {0xCC,0xCC,0x78,0x30,0xFC,0x30,0xFC,0x30},  //157
    {0xF8,0xCC,0xCC,0xFA,0xC6,0xCF,0xC6,0xC3},  //158
    {0x0E,0x1B,0x18,0x3C,0x18,0x18,0xD8,0x70},  //159
    {0x1C,0x00,0x78,0x0C,0x7C,0xCC,0x76,0x00},  //160
    {0x38,0x00,0x70,0x30,0x30,0x30,0x78,0x00},  //161
    {0x00,0x1C,0x00,0x78,0xCC,0xCC,0x78,0x00},  //162
    {0x00,0x1C,0x00,0xCC,0xCC,0xCC,0x76,0x00},  //163
    {0x00,0xF8,0x00,0xB8,0xCC,0xCC,0xCC,0x00},  //164
    {0xFC,0x00,0xCC,0xEC,0xFC,0xDC,0xCC,0x00},  //165
    {0x3C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00},  //166
    {0x38,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00},  //167
    {0x18,0x00,0x18,0x18,0x30,0x66,0x3C,0x00},  //168
    {0x00,0x00,0x00,0xFC,0xC0,0xC0,0x00,0x00},  //169
    {0x00,0x00,0x00,0xFC,0x0C,0x0C,0x00,0x00},  //170
    {0xC6,0xCC,0xD8,0x36,0x6B,0xC2,0x84,0x0F},  //171
    {0xC3,0xC6,0xCC,0xDB,0x37,0x6D,0xCF,0x03},  //172
    {0x18,0x00,0x18,0x18,0x3C,0x3C,0x18,0x00},  //173
    {0x00,0x33,0x66,0xCC,0x66,0x33,0x00,0x00},  //174
    {0x00,0xCC,0x66,0x33,0x66,0xCC,0x00,0x00},  //175
    {0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88},  //176
    {0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA},  //177
    {0xDB,0xF6,0xDB,0x6F,0xDB,0x7E,0xD7,0xED},  //178
    {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18},  //179
    {0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18},  //180
    {0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18},  //181
    {0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36},  //182
    {0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36},  //183
    {0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18},  //184
    {0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36},  //185
    {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36},  //186
    {0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36},  //187
    {0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00},  //188
    {0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00},  //189
    {0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00},  //190
    {0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18},  //191
    {0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00},  //192
    {0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00},  //193
    {0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18},  //194
    {0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18},  //195
    {0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00},  //196
    {0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18},  //197
    {0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18},  //198
    {0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36},  //199
    {0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00},  //200
    {0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36},  //201
    {0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00},  //202
    {0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36},  //203
    {0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36},  //204
    {0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00},  //205
    {0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36},  //206
    {0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00},  //207
    {0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00},  //208
    {0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18},  //209
    {0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36},  //210
    {0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00},  //211
    {0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00},  //212
    {0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18},  //213
    {0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36},  //214
    {0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36},  //215
    {0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18},  //216
    {0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00},  //217
    {0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18},  //218
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},  //219
    {0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF},  //220
    {0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0},  //221
    {0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F},  //222
    {0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00},  //223
    {0x00,0x00,0x76,0xDC,0xC8,0xDC,0x76,0x00},  //224
    {0x00,0x78,0xCC,0xF8,0xCC,0xF8,0xC0,0xC0},  //225
    {0x00,0xFC,0xCC,0xC0,0xC0,0xC0,0xC0,0x00},  //226
    {0x00,0x00,0xFE,0x6C,0x6C,0x6C,0x6C,0x00},  //227
    {0xFC,0xCC,0x60,0x30,0x60,0xCC,0xFC,0x00},  //228
    {0x00,0x00,0x7E,0xD8,0xD8,0xD8,0x70,0x00},  //229
    {0x00,0x66,0x66,0x66,0x66,0x7C,0x60,0xC0},  //230
    {0x00,0x76,0xDC,0x18,0x18,0x18,0x18,0x00},  //231
    {0xFC,0x30,0x78,0xCC,0xCC,0x78,0x30,0xFC},  //232
    {0x38,0x6C,0xC6,0xFE,0xC6,0x6C,0x38,0x00},  //233
    {0x38,0x6C,0xC6,0xC6,0x6C,0x6C,0xEE,0x00},  //234
    {0x1C,0x30,0x18,0x7C,0xCC,0xCC,0x78,0x00},  //235
    {0x00,0x00,0x7E,0xDB,0xDB,0x7E,0x00,0x00},  //236
    {0x06,0x0C,0x7E,0xDB,0xDB,0x7E,0x60,0xC0},  //237
    {0x38,0x60,0xC0,0xF8,0xC0,0x60,0x38,0x00},  //238
    {0x78,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x00},  //239
    {0x00,0x7E,0x00,0x7E,0x00,0x7E,0x00,0x00},  //240
    {0x18,0x18,0x7E,0x18,0x18,0x00,0x7E,0x00},  //241
    {0x60,0x30,0x18,0x30,0x60,0x00,0xFC,0x00},  //242
    {0x18,0x30,0x60,0x30,0x18,0x00,0xFC,0x00},  //243
    {0x0E,0x1B,0x1B,0x18,0x18,0x18,0x18,0x18},  //244
    {0x18,0x18,0x18,0x18,0x18,0xD8,0xD8,0x70},  //245
    {0x18,0x18,0x00,0x7E,0x00,0x18,0x18,0x00},  //246
    {0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00},  //247
    {0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00},  //248
    {0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00},  //249
    {0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00},  //250
    {0x0F,0x0C,0x0C,0x0C,0xEC,0x6C,0x3C,0x1C},  //251
    {0x58,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00},  //252
    {0x70,0x98,0x30,0x60,0xF8,0x00,0x00,0x00},  //253
    {0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00},  //254
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}   //255
};

static unsigned	char FontData16[256][16] = {
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //0
    {0x00,0x00,0x7E,0x81,0xA5,0x81,0x81,0xBD,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00}, //1
    {0x00,0x00,0x7E,0xFF,0xDB,0xFF,0xFF,0xC3,0xE7,0xFF,0xFF,0x7E,0x00,0x00,0x00,0x00}, //2
    {0x00,0x00,0x00,0x00,0x6C,0xFE,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00}, //3
    {0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00}, //4
    {0x00,0x00,0x00,0x18,0x3C,0x3C,0xE7,0xE7,0xE7,0x99,0x18,0x3C,0x00,0x00,0x00,0x00}, //5
    {0x00,0x00,0x00,0x18,0x3C,0x7E,0xFF,0xFF,0x7E,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, //6
    {0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00}, //7
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xC3,0xC3,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, //8
    {0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x42,0x42,0x66,0x3C,0x00,0x00,0x00,0x00,0x00}, //9
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x99,0xBD,0xBD,0x99,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF}, //10
    {0x00,0x00,0x1E,0x0E,0x1A,0x32,0x78,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00}, //11
    {0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00}, //12
    {0x00,0x00,0x3F,0x33,0x3F,0x30,0x30,0x30,0x30,0x70,0xF0,0xE0,0x00,0x00,0x00,0x00}, //13
    {0x00,0x00,0x7F,0x63,0x7F,0x63,0x63,0x63,0x63,0x67,0xE7,0xE6,0xC0,0x00,0x00,0x00}, //14
    {0x00,0x00,0x00,0x18,0x18,0xDB,0x3C,0xE7,0x3C,0xDB,0x18,0x18,0x00,0x00,0x00,0x00}, //15
    {0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFE,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00}, //16
    {0x00,0x02,0x06,0x0E,0x1E,0x3E,0xFE,0x3E,0x1E,0x0E,0x06,0x02,0x00,0x00,0x00,0x00}, //17
    {0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00}, //18
    {0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00}, //19
    {0x00,0x00,0x7F,0xDB,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x1B,0x1B,0x00,0x00,0x00,0x00}, //20
    {0x00,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00}, //21
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00}, //22
    {0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x7E,0x00,0x00,0x00}, //23
    {0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00}, //24
    {0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00}, //25
    {0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00}, //26
    {0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00}, //27
    {0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xFE,0x00,0x00,0x00,0x00,0x00,0x00}, //28
    {0x00,0x00,0x00,0x00,0x00,0x28,0x6C,0xFE,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00}, //29
    {0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7C,0x7C,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00}, //30
    {0x00,0x00,0x00,0x00,0xFE,0xFE,0x7C,0x7C,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00}, //31
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //32
    {0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, //33
    {0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //34
    {0x00,0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00}, //35
    {0x18,0x18,0x7C,0xC6,0xC2,0xC0,0x7C,0x06,0x86,0xC6,0x7C,0x18,0x18,0x00,0x00,0x00}, //36
    {0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00}, //37
    {0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, //38
    {0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //39
    {0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00}, //40
    {0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00}, //41
    {0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00}, //42
    {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00}, //43
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00}, //44
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //45
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, //46
    {0x00,0x00,0x00,0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00}, //47
    {0x00,0x00,0x7C,0xC6,0xC6,0xCE,0xD6,0xD6,0xE6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, //48
    {0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00}, //49
    {0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00}, //50
    {0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00}, //51
    {0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00}, //52
    {0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x0E,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00}, //53
    {0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, //54
    {0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00}, //55
    {0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, //56
    {0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00}, //57
    {0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00}, //58
    {0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00}, //59
    {0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00}, //60
    {0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00}, //61
    {0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00}, //62
    {0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, //63
    {0x00,0x00,0x00,0x7C,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0x7C,0x00,0x00,0x00,0x00}, //64
    {0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}, //65
    {0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00}, //66
    {0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00}, //67
    {0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00}, //68
    {0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00}, //69
    {0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00}, //70
    {0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00}, //71
    {0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}, //72
    {0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, //73
    {0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00}, //74
    {0x00,0x00,0xE6,0x66,0x6C,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00}, //75
    {0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00}, //76
    {0x00,0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}, //77
    {0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}, //78
    {0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00}, //79
    {0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00}, //80
    {0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00}, //81
    {0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00}, //82
    {0x00,0x00,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, //83
    {0x00,0x00,0x7E,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, //84
    {0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, //85
    {0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00}, //86
    {0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00}, //87
    {0x00,0x00,0xC6,0xC6,0x6C,0x6C,0x38,0x38,0x6C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00}, //88
    {0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, //89
    {0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00}, //90
    {0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00}, //91
    {0x00,0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x06,0x02,0x00,0x00,0x00,0x00}, //92
    {0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00}, //93
    {0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //94
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00}, //95
    {0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //96
    {0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, //97
    {0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0xDC,0x00,0x00,0x00,0x00}, //98
    {0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}, //99
    {0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, //100
    {0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}, //101
    {0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00}, //102
    {0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0xCC,0x78,0x00}, //103
    {0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00}, //104
    {0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, //105
    {0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00}, //106
    {0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00}, //107
    {0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, //108
    {0x00,0x00,0x00,0x00,0x00,0xEC,0xFE,0xD6,0xD6,0xD6,0xD6,0xD6,0x00,0x00,0x00,0x00}, //109
    {0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00}, //110
    {0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, //111
    {0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00}, //112
    {0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00}, //113
    {0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x62,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00}, //114
    {0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00}, //115
    {0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00}, //116
    {0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, //117
    {0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00}, //118
    {0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00}, //119
    {0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00}, //120
    {0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00}, //121
    {0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00}, //122
    {0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00}, //123
    {0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00}, //124
    {0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00}, //125
    {0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //126
    {0x00,0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00}, //127
    {0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x0C,0x06,0x7C,0x00,0x00}, //128
    {0x00,0x00,0xCC,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, //129
    {0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}, //130
    {0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, //131
    {0x00,0x00,0xCC,0xCC,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, //132
    {0x00,0x60,0x30,0x18,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, //133
    {0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, //134
    {0x00,0x00,0x00,0x00,0x3C,0x66,0x60,0x60,0x66,0x3C,0x0C,0x06,0x3C,0x00,0x00,0x00}, //135
    {0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}, //136
    {0x00,0x00,0xC6,0xC6,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}, //137
    {0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}, //138
    {0x00,0x00,0x66,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, //139
    {0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, //140
    {0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, //141
    {0x00,0xC6,0xC6,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}, //142
    {0x38,0x6C,0x38,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}, //143
    {0x18,0x30,0x60,0x00,0xFE,0x66,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00}, //144
    {0x00,0x00,0x00,0x00,0x00,0xCC,0x76,0x36,0x7E,0xD8,0xD8,0x6E,0x00,0x00,0x00,0x00}, //145
    {0x00,0x00,0x3E,0x6C,0xCC,0xCC,0xFE,0xCC,0xCC,0xCC,0xCC,0xCE,0x00,0x00,0x00,0x00}, //146
    {0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, //147
    {0x00,0x00,0xC6,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, //148
    {0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, //149
    {0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, //150
    {0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, //151
    {0x00,0x00,0xC6,0xC6,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00}, //152
    {0x00,0xC6,0xC6,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00}, //153
    {0x00,0xC6,0xC6,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, //154
    {0x00,0x18,0x18,0x3C,0x66,0x60,0x60,0x60,0x66,0x3C,0x18,0x18,0x00,0x00,0x00,0x00}, //155
    {0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xE6,0xFC,0x00,0x00,0x00,0x00}, //156
    {0x00,0x00,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00}, //157
    {0x00,0xF8,0xCC,0xCC,0xF8,0xC4,0xCC,0xDE,0xCC,0xCC,0xCC,0xC6,0x00,0x00,0x00,0x00}, //158
    {0x00,0x0E,0x1B,0x18,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x18,0xD8,0x70,0x00,0x00}, //159
    {0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, //160
    {0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, //161
    {0x00,0x18,0x30,0x60,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, //162
    {0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, //163
    {0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00}, //164
    {0x76,0xDC,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}, //165
    {0x00,0x3C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //166
    {0x00,0x38,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //167
    {0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xC0,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, //168
    {0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00}, //169
    {0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00}, //170
    {0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x60,0xCE,0x93,0x06,0x0C,0x1F,0x00,0x00}, //171
    {0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x66,0xCE,0x9A,0x3F,0x06,0x0F,0x00,0x00}, //172
    {0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00}, //173
    {0x00,0x00,0x00,0x00,0x00,0x33,0x66,0xCC,0x66,0x33,0x00,0x00,0x00,0x00,0x00,0x00}, //174
    {0x00,0x00,0x00,0x00,0x00,0xCC,0x66,0x33,0x66,0xCC,0x00,0x00,0x00,0x00,0x00,0x00}, //175
    {0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44}, //176
    {0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA}, //177
    {0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77}, //178
    {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}, //179
    {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}, //180
    {0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}, //181
    {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}, //182
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}, //183
    {0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}, //184
    {0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}, //185
    {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}, //186
    {0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}, //187
    {0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //188
    {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //189
    {0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //190
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}, //191
    {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //192
    {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //193
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}, //194
    {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}, //195
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //196
    {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}, //197
    {0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}, //198
    {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}, //199
    {0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //200
    {0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}, //201
    {0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //202
    {0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}, //203
    {0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}, //204
    {0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //205
    {0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}, //206
    {0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //207
    {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //208
    {0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}, //209
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}, //210
    {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //211
    {0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //212
    {0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}, //213
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}, //214
    {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}, //215
    {0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}, //216
    {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //217
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}, //218
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, //219
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, //220
    {0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0}, //221
    {0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F}, //222
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //223
    {0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0xD8,0xD8,0xD8,0xDC,0x76,0x00,0x00,0x00,0x00}, //224
    {0x00,0x00,0x00,0x00,0x00,0xFC,0xC6,0xFC,0xC6,0xC6,0xFC,0xC0,0xC0,0xC0,0x00,0x00}, //225
    {0x00,0x00,0xFE,0xC6,0xC6,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00}, //226
    {0x00,0x00,0x00,0x00,0x80,0xFE,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00}, //227
    {0x00,0x00,0x00,0xFE,0xC6,0x60,0x30,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00}, //228
    {0x00,0x00,0x00,0x00,0x00,0x7E,0xD8,0xD8,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00}, //229
    {0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xC0,0x00,0x00,0x00}, //230
    {0x00,0x00,0x00,0x00,0x76,0xDC,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00}, //231
    {0x00,0x00,0x00,0x7E,0x18,0x3C,0x66,0x66,0x66,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00}, //232
    {0x00,0x00,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00}, //233
    {0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x6C,0x6C,0x6C,0xEE,0x00,0x00,0x00,0x00}, //234
    {0x00,0x00,0x1E,0x30,0x18,0x0C,0x3E,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00}, //235
    {0x00,0x00,0x00,0x00,0x00,0x7E,0xDB,0xDB,0xDB,0x7E,0x00,0x00,0x00,0x00,0x00,0x00}, //236
    {0x00,0x00,0x00,0x03,0x06,0x7E,0xCF,0xDB,0xF3,0x7E,0x60,0xC0,0x00,0x00,0x00,0x00}, //237
    {0x00,0x00,0x1C,0x30,0x60,0x60,0x7C,0x60,0x60,0x60,0x30,0x1C,0x00,0x00,0x00,0x00}, //238
    {0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}, //239
    {0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00}, //240
    {0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0xFF,0x00,0x00,0x00,0x00}, //241
    {0x00,0x00,0x00,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00,0x7E,0x00,0x00,0x00,0x00}, //242
    {0x00,0x00,0x00,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00,0x7E,0x00,0x00,0x00,0x00}, //243
    {0x00,0x00,0x0E,0x1B,0x1B,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}, //244
    {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00}, //245
    {0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7E,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00}, //246
    {0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00}, //247
    {0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //248
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //249
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //250
    {0x00,0x0F,0x0C,0x0C,0x0C,0x0C,0x0C,0xEC,0x6C,0x6C,0x3C,0x1C,0x00,0x00,0x00,0x00}, //251
    {0x00,0xD8,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //252
    {0x00,0x70,0x98,0x30,0x60,0xC8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, //253
    {0x00,0x00,0x00,0x00,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x00,0x00,0x00,0x00,0x00}, //254
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}  //255
};
/// @endcond /* HIDDEN_SYMBOLS */

/*@}*/ /* end of group N9H30_GE2D_EXPORTED_CONSTANTS */

/** @addtogroup N9H30_GE2D_EXPORTED_FUNCTIONS GE2D Exported Functions
  @{
*/

/// @cond HIDDEN_SYMBOLS

/* For align 32 */
static unsigned int shift_pointer(int ptr, int align)
{
    unsigned int pos;
    int remain;
    pos = ptr;

    if( (ptr%align)!=0) {
        remain = ptr % align;
        ptr = ptr + (align - remain);
        return ptr;
    } else
        return pos;
}

static unsigned long make_color(int color)
{
    UINT32 r, g, b;

    if (GFX_BPP==8) {
        r = (color & 0x00e00000) >> 16; // 3 bits
        g = (color & 0x0000e000) >> 11; // 3 bits
        b = (color & 0x000000c0) >> 6;  // 2 bits
        return (r | g | b);
    } else if (GFX_BPP==16) {
        r = (color & 0x00f80000) >> 8; // 5 bits
        g = (color & 0x0000fc00) >> 5; // 6 bits
        b = (color & 0x000000f8) >> 3; // 5 bits
        return (r | g | b);
    } else return (UINT32)color;
}
/// @endcond /* HIDDEN_SYMBOLS */

/**
  * @brief  Clear the on screen buffer with a specified color.
  * @param[in] color clear with this color.
  * @return none
  */
void ge2dClearScreen(int color)
{
    UINT32 cmd32;
    UINT32 color32, dest_pitch, dest_dimension;

    color32 = make_color(color);

    cmd32 = 0xcc430040;
    outpw(REG_GE2D_CTL, cmd32);
    outpw(REG_GE2D_BGCOLR, color32); // fill with background color

    dest_pitch = GFX_WIDTH << 16; // pitch in pixels
    outpw(REG_GE2D_SDPITCH, dest_pitch);

    outpw(REG_GE2D_DSTSPA, 0); // starts from (0,0)

    dest_dimension = GFX_HEIGHT << 16 | GFX_WIDTH;
    outpw(REG_GE2D_RTGLSZ, dest_dimension);

    outpw(REG_GE2D_TRG, 1);
    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete
    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Set output data mask.
  * @param[in] mask is mask value
  * @return none
  */
void ge2dSetWriteMask(int mask)
{
    outpw(REG_GE2D_WRPLNMSK, make_color(mask));
}

/**
  * @brief Set source origin starting address.
  * @param[in] ptr pointer of start address
  * @return none
  */
void ge2dSetSourceOriginStarting(void *ptr)
{
    outpw(REG_GE2D_XYSORG, (int)ptr);
}

/**
  * @brief Set destination origin starting address.
  * @param[in] ptr pointer of start address
  * @return none
  */
void ge2dSetDestinationOriginStarting(void *ptr)
{
    outpw(REG_GE2D_XYDORG, (int)ptr);
}

/**
  * @brief Graphics engine initialization.
  * @param[in] bpp bit per pixel
  * @param[in] width is width of display memory
  * @param[in] height is height of display memory
  * @param[in] destination is pointer of destination buffer address
  * @return none
  */
void ge2dInit(int bpp, int width, int height, void *destination)
{
    UINT32 data32;

    GFX_BPP = bpp;
    GFX_WIDTH = width;
    GFX_HEIGHT = height;
    GFX_PITCH = (GFX_WIDTH*(GFX_BPP/8));
    GFX_SIZE = (GFX_HEIGHT*GFX_PITCH);

    _DrawMode = MODE_TRANSPARENT;
    _ColorKey = COLOR_KEY;
    _ColorKeyMask = 0xFFFFFF;


    if(destination == NULL)
        return;

    Orig_GFX_START_ADDR = GFX_START_ADDR = (void *)destination;
    if(GFX_Mem == 0)
    {
        /* Only allocate memory once. Avoid memory fragmentation if calling ge2DInit() and ge2dReset repeatedly */
        Orig_GFX_PAT_ADDR = GFX_PAT_ADDR = (void *)malloc((8*8*(GFX_BPP/8))*2);
        GFX_PAT_ADDR = (void *)shift_pointer((int)GFX_PAT_ADDR, (8*8*(GFX_BPP/8))*2);  // two times of boundary size


        Orig_MONO_SOURCE_ADDR = MONO_SOURCE_ADDR = (void *)malloc(GFX_SIZE+32);
        MONO_SOURCE_ADDR = (void *)shift_pointer((int)MONO_SOURCE_ADDR, 32);
        Orig_COLOR_SOURCE_ADDR = COLOR_SOURCE_ADDR = (void *)malloc(GFX_SIZE+32);
        COLOR_SOURCE_ADDR = (void *)shift_pointer((int)COLOR_SOURCE_ADDR, 32);
        Orig_CMODEL_START_ADDR = CMODEL_START_ADDR = (void *)malloc(GFX_SIZE+32);
        CMODEL_START_ADDR = (void *)shift_pointer((int)CMODEL_START_ADDR, 32);
        Orig_GFX_OFFSCREEN_ADDR = GFX_OFFSCREEN_ADDR = (void *)malloc(GFX_SIZE+32);
        GFX_OFFSCREEN_ADDR = (void *)shift_pointer((int)GFX_OFFSCREEN_ADDR, 32);
        GFX_Mem = 1;
    }
#ifdef DEBUG
    sysprintf("init_GE()\n");
    sysprintf("screen width = %d\n", GFX_WIDTH);
    sysprintf("screen height = %d\n", GFX_HEIGHT);
    sysprintf("screen bpp = %d\n", GFX_BPP);
    sysprintf("screen size = 0x%x\n", GFX_SIZE);
#endif

    outpw(REG_CLK_HCLKEN, inpw(REG_CLK_HCLKEN) | (1<<28));

    outpw(REG_GE2D_INTSTS, 0); // clear interrupt
    outpw(REG_GE2D_PATSA, (unsigned int)GFX_PAT_ADDR);
    outpw(REG_GE2D_CTL, 0); // disable interrupt
    outpw(REG_GE2D_XYDORG, (unsigned int)GFX_START_ADDR);
    outpw(REG_GE2D_XYSORG, (unsigned int)GFX_START_ADDR);

    outpw(REG_GE2D_WRPLNMSK, 0x00ffffff); // write plane mask

    data32 = GE_BPP_8; // default is 8 bpp

    if (GFX_BPP==16) {
        data32 |= GE_BPP_16;
    } else if (GFX_BPP==32) {
        data32 |= GE_BPP_32;
    }

    outpw(REG_GE2D_MISCTL, data32);
}

/**
  * @brief Reset graphics engine.
  * @param none
  * @return none
  */
void ge2dReset(void)
{
    outpw(REG_GE2D_MISCTL, 0x40); // FIFO reset
    outpw(REG_GE2D_MISCTL, 0x00);

    outpw(REG_GE2D_MISCTL, 0x80); // Engine reset
    outpw(REG_GE2D_MISCTL, 0x00);

}


/**
  * @brief Reset FIFO of graphics engine.
  * @param none
  * @return none
  */
void ge2dResetFIFO(void)
{
    UINT32 temp32;

    temp32 = inpw(REG_GE2D_MISCTL);
    temp32 |= 0x00000040;
    outpw(REG_GE2D_MISCTL, temp32);
    temp32 &= 0xffffffbf;
    outpw(REG_GE2D_MISCTL, temp32);
}

/**
  * @brief Set BitBlt drawing mode.
  * @param[in] opt is drawing mode
  * @param[in] ckey is value of color key
  * @param[in] mask is value of color mask
  * @return none
  */
void ge2dBitblt_SetDrawMode(int opt, int ckey, int mask)
{
    if (opt==MODE_TRANSPARENT) {
        _DrawMode = MODE_TRANSPARENT;

        _ColorKey = make_color(ckey);
        _ColorKeyMask = make_color(mask);

        outpw(REG_GE2D_TRNSCOLR, _ColorKey);
        outpw(REG_GE2D_TCMSK, _ColorKeyMask);
    } else if (opt==MODE_DEST_TRANSPARENT) {
        _DrawMode = MODE_DEST_TRANSPARENT;

        _ColorKey = make_color(ckey);
        _ColorKeyMask = make_color(mask);

        outpw(REG_GE2D_TRNSCOLR, _ColorKey);
        outpw(REG_GE2D_TCMSK, _ColorKeyMask);
    } else {
        _DrawMode = MODE_OPAQUE; // default is OPAQUE
    }
}

/**
  * @brief Set alpha blending programming.
  * @param[in] opt is selection for enable or disable
  * @param[in] ks is value of alpha blending factor Ks
  * @param[in] kd is value of alpha blending factor Kd
  * @return none
  */
int ge2dBitblt_SetAlphaMode(int opt, int ks, int kd)
{
    if (ks + kd > 255)
        return -1;

    if (opt==1) {
        _EnableAlpha = TRUE;
        _AlphaKs = ks;
        _AlphaKd = kd;
    } else {
        _EnableAlpha = FALSE;
    }

    return 0;
}

/**
  * @brief Screen-to-Screen BitBlt with SRCCOPY ROP operation.
  * @param[in] srcx is source x position
  * @param[in] srcy is source y position
  * @param[in] destx is destination x position
  * @param[in] desty is destination y position
  * @param[in] width is display width
  * @param[in] height is display width
  * @return none
  */
void ge2dBitblt_ScreenToScreen(int srcx, int srcy, int destx, int desty, int width, int height)
{
    UINT32 cmd32, pitch, dest_start, src_start, dimension;
    UINT32 data32, alpha;

#ifdef DEBUG
    sysprintf("screen_to_screen_blt():\n");
    sysprintf("(%d,%d)=>(%d,%d)\n", srcx, srcy, destx, desty);
    sysprintf("width=%d height=%d\n", width, height);
#endif

    cmd32 = 0xcc430000;

    outpw(REG_GE2D_CTL, cmd32);

    if (srcx > destx) { //+X
        if (srcy > desty) { //+Y
        } else { //-Y
            cmd32 |= 0x08;
            srcy = srcy + height - 1;
            desty = desty + height - 1;
        }
    } else { //-X
        if (srcy > desty) { //+Y
            cmd32 |= 0x04; // 010
            srcx = srcx + width - 1;
            destx = destx + width - 1;
        } else { //-Y
            cmd32 |= 0xc; // 110
            srcx = srcx + width - 1;
            destx = destx + width - 1;
            srcy = srcy + height - 1;
            desty = desty + height - 1;
        }
    }

#ifdef DEBUG
    sysprintf("new srcx=%d srcy=%d\n", srcx, srcy);
    sysprintf("new destx=%d desty=%d\n", destx, desty);
#endif

    outpw(REG_GE2D_CTL, cmd32);

    pitch = GFX_WIDTH << 16 | GFX_WIDTH;
    outpw(REG_GE2D_SDPITCH, pitch);

    src_start = srcy << 16 | srcx;
    outpw(REG_GE2D_SRCSPA, src_start);

    dest_start = desty << 16 | destx;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dimension = height << 16 | width;
    outpw(REG_GE2D_RTGLSZ, dimension);

    //
    // force to use the same starting address
    //
    outpw(REG_GE2D_XYSORG, (int)GFX_START_ADDR);
    outpw(REG_GE2D_XYDORG, (int)GFX_START_ADDR);  //smf

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    if (_DrawMode==MODE_TRANSPARENT) {
        cmd32 |= 0x00008000; // color transparency
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_TRNSCOLR, _ColorKey);
        outpw(REG_GE2D_TCMSK, _ColorKeyMask);
    } else if (_DrawMode==MODE_DEST_TRANSPARENT) {
        cmd32 |= 0x00009000;   // destination pixels control transparency
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_TRNSCOLR, _ColorKey);
        outpw(REG_GE2D_TCMSK, _ColorKeyMask);
    }

    if (_EnableAlpha) {
        cmd32 |= 0x00200000;
        outpw(REG_GE2D_CTL, cmd32);

        data32 = inpw(REG_GE2D_MISCTL) & 0x0000ffff;
        alpha = (UINT32)((_AlphaKs << 8) | _AlphaKd);
        data32 |= (alpha << 16);

        outpw(REG_GE2D_MISCTL, data32);
    }

    outpw(REG_GE2D_TRG, 1);

    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete

    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Screen-to-Screen BitBlt with ROP option.
  * @param[in] srcx is source x position
  * @param[in] srcy is source y position
  * @param[in] destx is destination x position
  * @param[in] desty is destination y position
  * @param[in] width is display width
  * @param[in] height is display width
  * @param[in] rop is rop option
  * @return none
  */
void ge2dBitblt_ScreenToScreenRop(int srcx, int srcy, int destx, int desty, int width, int height, int rop)
{
    UINT32 cmd32, pitch, dest_start, src_start, dimension;
    UINT32 data32, alpha;

#ifdef DEBUG
    sysprintf("screen_to_screen_rop_blt():\n");
    sysprintf("ROP=0x%x\n", rop);
    sysprintf("(%d,%d)=>(%d,%d)\n", srcx, srcy, destx, desty);
    sysprintf("width=%d height=%d\n", width, height);
#endif

    cmd32 = 0x00430000 | (rop << 24);

    if (_PatternType==TYPE_MONO) {
        cmd32 |= 0x00000010; // default is TYPE_COLOR
    }

    outpw(REG_GE2D_CTL, cmd32);

    if (srcx > destx) { //+X
        if (srcy > desty) { //+Y
        } else { //-Y
            cmd32 |= 0x08;
            srcy = srcy + height - 1;
            desty = desty + height - 1;
        }
    } else { //-X
        if (srcy > desty) { //+Y
            cmd32 |= 0x04; // 010
            srcx = srcx + width - 1;
            destx = destx + width - 1;
        } else { //-Y
            cmd32 |= 0xc; // 110
            srcx = srcx + width - 1;
            destx = destx + width - 1;
            srcy = srcy + height - 1;
            desty = desty + height - 1;
        }
    }

#ifdef DEBUG
    sysprintf("new srcx=%d srcy=%d\n", srcx, srcy);
    sysprintf("new destx=%d desty=%d\n", destx, desty);
#endif

    outpw(REG_GE2D_CTL, cmd32);

    pitch = GFX_WIDTH << 16 | GFX_WIDTH; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, pitch);

    src_start = srcy << 16 | srcx;
    outpw(REG_GE2D_SRCSPA, src_start);

    dest_start = desty << 16 | destx;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dimension = height << 16 | width;
    outpw(REG_GE2D_RTGLSZ, dimension);

    //
    // force to use the same starting address
    //
    outpw(REG_GE2D_XYSORG, (int)GFX_START_ADDR);
    outpw(REG_GE2D_XYDORG, (int)GFX_START_ADDR);  //smf

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    if (_DrawMode==MODE_TRANSPARENT) {
        cmd32 |= 0x00008000; // color transparency
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_TRNSCOLR, _ColorKey);
        outpw(REG_GE2D_TCMSK, _ColorKeyMask);
    } else if (_DrawMode==MODE_DEST_TRANSPARENT) {
        cmd32 |= 0x00009000;
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_TRNSCOLR, _ColorKey);
        outpw(REG_GE2D_TCMSK, _ColorKeyMask);
    }

    if (_EnableAlpha) {
        cmd32 |= 0x00200000;
        outpw(REG_GE2D_CTL, cmd32);

        data32 = inpw(REG_GE2D_MISCTL) & 0x0000ffff;
        alpha = (UINT32)((_AlphaKs << 8) | _AlphaKd);
        data32 |= (alpha << 16);

        outpw(REG_GE2D_MISCTL, data32);
    }

    if ((rop==0x00) || (rop==0xff)) {
        cmd32 = (cmd32 & 0xffff0fff) | 0x00009000;
        outpw(REG_GE2D_CTL, cmd32);
    }

    outpw(REG_GE2D_TRG, 1);

    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete

    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Source to destination BitBlt with SRCCOPY ROP operation.
  * @param[in] srcx is source x position
  * @param[in] srcy is source y position
  * @param[in] destx is destination x position
  * @param[in] desty is destination y position
  * @param[in] width is display width
  * @param[in] height is display width
  * @param[in] srcpitch is source pixel pitch
  * @param[in] destpitch is destination pixel pitch
  * @return none
  * @note before calling this function, it would set the source and destination origin starting place
  */
void ge2dBitblt_SourceToDestination(int srcx, int srcy, int destx, int desty, int width, int height, int srcpitch, int destpitch)
{
    UINT32 cmd32, pitch, dest_start, src_start, dimension;
    UINT32 data32, alpha;

#ifdef DEBUG
    sysprintf("source_to_destination_blt():\n");
    sysprintf("(%d,%d)=>(%d,%d)\n", srcx, srcy, destx, desty);
    sysprintf("width=%d height=%d\n", width, height);
#endif

    cmd32 = 0xcc430000;

    outpw(REG_GE2D_CTL, cmd32);

    if (srcx > destx) { //+X
        if (srcy > desty) { //+Y
        } else { //-Y
            cmd32 |= 0x08;
            srcy = srcy + height - 1;
            desty = desty + height - 1;
        }
    } else { //-X
        if (srcy > desty) { //+Y
            cmd32 |= 0x04; // 010
            srcx = srcx + width - 1;
            destx = destx + width - 1;
        } else { //-Y
            cmd32 |= 0xc; // 110
            srcx = srcx + width - 1;
            destx = destx + width - 1;
            srcy = srcy + height - 1;
            desty = desty + height - 1;
        }
    }

#ifdef DEBUG
    sysprintf("new srcx=%d srcy=%d\n", srcx, srcy);
    sysprintf("new destx=%d desty=%d\n", destx, desty);
#endif

    outpw(REG_GE2D_CTL, cmd32);

    pitch = destpitch << 16 | srcpitch; // pitch in pixel, back | GFX_WIDTH ??
    outpw(REG_GE2D_SDPITCH, pitch);

    src_start = srcy << 16 | srcx;
    outpw(REG_GE2D_SRCSPA, src_start);

    dest_start = desty << 16 | destx;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dimension = height << 16 | width;
    outpw(REG_GE2D_RTGLSZ, dimension);


    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    if (_DrawMode==MODE_TRANSPARENT) {
        cmd32 |= 0x00008000; // color transparency
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_TRNSCOLR, _ColorKey);
        outpw(REG_GE2D_TCMSK, _ColorKeyMask);
    } else if (_DrawMode==MODE_DEST_TRANSPARENT) {
        cmd32 |= 0x00009000;   // destination pixels control transparency
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_TRNSCOLR, _ColorKey);
        outpw(REG_GE2D_TCMSK, _ColorKeyMask);
    }

    if (_EnableAlpha) {
        cmd32 |= 0x00200000;
        outpw(REG_GE2D_CTL, cmd32);

        data32 = inpw(REG_GE2D_MISCTL) & 0x0000ffff;
        alpha = (UINT32)((_AlphaKs << 8) | _AlphaKd);
        data32 |= (alpha << 16);

        outpw(REG_GE2D_MISCTL, data32);
    }

    outpw(REG_GE2D_TRG, 1);

    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete

    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Set the clip rectangle. (top-left to down-right).
  * @param[in] x1 is top-left x position
  * @param[in] y1 is top-left y position
  * @param[in] x2 is down-right x position
  * @param[in] y2 is down-right y position
  * @return none
  */
void ge2dClip_SetClip(int x1, int y1, int x2, int y2)
{

#ifdef DEBUG
    sysprintf("set_clip(): (%d,%d)-(%d,%d)\n", x1, y1, x2, y2);
#endif

    if ((x1>=0) && (y1>=0) && (x2>=0) && (y2>=0)) {
        if ((x2 > x1) && (y2 > y1)) {
            _ClipEnable = TRUE;
            /* hardware clipper not includes last pixel */
            x2++;
            y2++;
            _ClipTL = (UINT32)((y1 << 16) | x1);
            _ClipBR = (UINT32)((y2 << 16) | x2);
        } else {
            _ClipEnable = FALSE;
        }
    } else {
        _ClipEnable = FALSE;
    }
}

/**
  * @brief Set the clip to inside clip or outside clip.
  * @param[in] opt is option for setting clip inside or outside, value could be
  *                                 - \ref MODE_INSIDE_CLIP
  *                                 - \ref MODE_OUTSIDE_CLIP
  * @return none
  */
void ge2dClip_SetClipMode(int opt)
{
    _OutsideClip = (opt==0) ? FALSE : TRUE;

    if (_OutsideClip) {
#ifdef DEBUG
        sysprintf("set_clip_mode(): OUTSIDE\n");
#endif
    } else {
#ifdef DEBUG
        sysprintf("set_clip_mode(): INSIDE\n");
#endif
    }
}

/**
  * @brief Draw an one-pixel rectangle frame.
  * @param[in] x1 is top-left x position
  * @param[in] y1 is top-left y position
  * @param[in] x2 is down-right x position
  * @param[in] y2 is down-right y position
  * @param[in] color is color of this rectangle
  * @param[in] opt is draw option, value could be
  *                                - 0: rectangle
  *                                - 1: diagonal
  * @return none
  */
void ge2dDrawFrame(int x1, int y1, int x2, int y2, int color, int opt)
{
    UINT32 dest_pitch, dest_start, dest_dimension;
    UINT32 color32;

#ifdef DEBUG
    sysprintf("draw_frame():\n");
    sysprintf("(%d,%d)-(%d,%d)\n", x1, y1, x2, y2);
    sysprintf("color=0x%x opt=%d\n", color, opt);
#endif

    /*
    ** The opt==1 case must be specially handled.
    */

    if (opt==0) {
        outpw(REG_GE2D_CTL, 0xcccb0000); // rectangle
    } else {
        outpw(REG_GE2D_CTL, 0xcccf0000); // diagonal
    }

#ifdef DEBUG
    sysprintf("(%d,%d)-(%d,%d)\n", x1, y1, x2, y2);
#endif

    color32 = make_color(color);
    outpw(REG_GE2D_FGCOLR, color32);

    dest_pitch = GFX_WIDTH << 16; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, dest_pitch);

    dest_start = y1 << 16 | x1;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dest_dimension = (y2-y1) << 16 | (x2-x1);
    outpw(REG_GE2D_RTGLSZ, dest_dimension);

    outpw(REG_GE2D_MISCTL, inpw(REG_GE2D_MISCTL)); // address caculation

    outpw(REG_GE2D_TRG, 1);

    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete

    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Draw an solid rectangle line.
  * @param[in] x1 is top-left x position
  * @param[in] y1 is top-left y position
  * @param[in] x2 is down-right x position
  * @param[in] y2 is down-right y position
  * @param[in] color is color of this line
  * @return none
  */
void ge2dLine_DrawSolidLine(int x1, int y1, int x2, int y2, int color)
{
    int abs_X, abs_Y, min, max;
    UINT32 step_constant, initial_error, direction_code;
    UINT32 cmd32, dest_pitch, dest_start;

#ifdef DEBUG
    sysprintf("draw_solid_line():\n");
    sysprintf("(%d,%d)-(%d,%d)\n", x1, y1, x2, y2);
    sysprintf("color=0x%x\n", color);
#endif

    abs_X = ABS(x2-x1);   //absolute value
    abs_Y = ABS(y2-y1);   //absolute value
    if (abs_X > abs_Y) {  // X major
        max = abs_X;
        min = abs_Y;

        step_constant = (((UINT32)(2*(min-max))) << 16) | (UINT32)(2*min);
        initial_error = (((UINT32)(2*(min)-max)) << 16) | (UINT32)(max);

        if (x2 > x1) { // +X direction
            if (y2 > y1) // +Y direction
                direction_code = XpYpXl;
            else // -Y direction
                direction_code = XpYmXl;
        } else { // -X direction
            if (y2 > y1) // +Y direction
                direction_code = XmYpXl;
            else // -Y direction
                direction_code = XmYmXl;
        }
    } else { // Y major
        max = abs_Y;
        min = abs_X;

        step_constant = (((UINT32)(2*(min-max))) << 16) | (UINT32)(2*min);
        initial_error = (((UINT32)(2*(min)-max)) << 16) | (UINT32)(max);

        if (x2 > x1) { // +X direction
            if (y2 > y1) // +Y direction
                direction_code = XpYpYl;
            else // -Y direction
                direction_code = XpYmYl;
        } else { // -X direction
            if (y2 > y1) // +Y direction
                direction_code = XmYpYl;
            else // -Y direction
                direction_code = XmYmYl;
        }
    }

    outpw(REG_GE2D_BETSC, step_constant);
    outpw(REG_GE2D_BIEPC, initial_error);

    cmd32 = 0x008b0000 | direction_code;

    outpw(REG_GE2D_CTL, cmd32);

    outpw(REG_GE2D_BGCOLR, make_color(color));
    outpw(REG_GE2D_FGCOLR, make_color(color));

    dest_pitch = GFX_WIDTH << 16; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, dest_pitch);

    outpw(REG_GE2D_XYDORG, (int)GFX_START_ADDR);

    dest_start = y1 << 16 | x1;
    outpw(REG_GE2D_DSTSPA, dest_start);

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    outpw(REG_GE2D_TRG, 1);

    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete

    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Draw an solid rectangle line with assigned RGB565 color
  * @param[in] x1 is top-left x position
  * @param[in] y1 is top-left y position
  * @param[in] x2 is down-right x position
  * @param[in] y2 is down-right y position
  * @param[in] color is color of this line
  * @return none
  */
void ge2dLine_DrawSolidLine_RGB565(int x1, int y1, int x2, int y2, int color)
{
    int abs_X, abs_Y, min, max;
    UINT32 step_constant, initial_error, direction_code;
    UINT32 cmd32, dest_pitch, dest_start;

#ifdef DEBUG
    sysprintf("draw_solid_line():\n");
    sysprintf("(%d,%d)-(%d,%d)\n", x1, y1, x2, y2);
    sysprintf("color=0x%x\n", color);
#endif

    abs_X = ABS(x2-x1);   //absolute value
    abs_Y = ABS(y2-y1);   //absolute value
    if (abs_X > abs_Y) {  // X major
        max = abs_X;
        min = abs_Y;

        step_constant = (((UINT32)(2*(min-max))) << 16) | (UINT32)(2*min);
        initial_error = (((UINT32)(2*(min)-max)) << 16) | (UINT32)(max);

        if (x2 > x1) { // +X direction
            if (y2 > y1) // +Y direction
                direction_code = XpYpXl;
            else // -Y direction
                direction_code = XpYmXl;
        } else { // -X direction
            if (y2 > y1) // +Y direction
                direction_code = XmYpXl;
            else // -Y direction
                direction_code = XmYmXl;
        }
    } else { // Y major
        max = abs_Y;
        min = abs_X;

        step_constant = (((UINT32)(2*(min-max))) << 16) | (UINT32)(2*min);
        initial_error = (((UINT32)(2*(min)-max)) << 16) | (UINT32)(max);

        if (x2 > x1) { // +X direction
            if (y2 > y1) // +Y direction
                direction_code = XpYpYl;
            else // -Y direction
                direction_code = XpYmYl;
        } else { // -X direction
            if (y2 > y1) // +Y direction
                direction_code = XmYpYl;
            else // -Y direction
                direction_code = XmYmYl;
        }
    }

    outpw(REG_GE2D_BETSC, step_constant);
    outpw(REG_GE2D_BIEPC, initial_error);

    cmd32 = 0x008b0000 | direction_code;

    outpw(REG_GE2D_CTL, cmd32);

    outpw(REG_GE2D_BGCOLR, color);
    outpw(REG_GE2D_FGCOLR, color);

    dest_pitch = GFX_WIDTH << 16; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, dest_pitch);

    outpw(REG_GE2D_XYDORG, (int)GFX_START_ADDR);

    dest_start = y1 << 16 | x1;
    outpw(REG_GE2D_DSTSPA, dest_start);

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    outpw(REG_GE2D_TRG, 1);

    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete

    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}


/**
  * @brief Draw a styled line.
  * @param[in] x1 is top-left x position
  * @param[in] y1 is top-left y position
  * @param[in] x2 is down-right x position
  * @param[in] y2 is down-right y position
  * @param[in] style is style of line pattern
  * @param[in] fgcolor is color of foreground
  * @param[in] bkcolor is color of background
  * @param[in] draw_mode is transparent is enable or not
  * @return none
  */
void ge2dLine_DrawStyledLine(int x1, int y1, int x2, int y2, int style, int fgcolor, int bkcolor, int draw_mode)
{
    int abs_X, abs_Y, min, max;
    UINT32 step_constant, initial_error, direction_code;
    UINT32 cmd32, dest_pitch, dest_start;
    UINT32 temp32, line_control_code;

    abs_X = ABS(x2-x1);
    abs_Y = ABS(y2-y1);
    if (abs_X > abs_Y) { // X major
        max = abs_X;
        min = abs_Y;

        step_constant = (((UINT32)(2*(min-max))) << 16) | (UINT32)(2*min);
        initial_error = (((UINT32)(2*min-max)) << 16) | (UINT32)(max);

        if (x2 > x1) { // +X direction
            if (y2 > y1) // +Y direction
                direction_code = XpYpXl;
            else // -Y direction
                direction_code = XpYmXl;
        } else { // -X direction
            if (y2 > y1) // +Y direction
                direction_code = XmYpXl;
            else // -Y direction
                direction_code = XmYmXl;
        }
    } else { // Y major
        max = abs_Y;
        min = abs_X;

        step_constant = (((UINT32)(2*(min-max))) << 16) | (UINT32)(2*min);
        initial_error = (((UINT32)(2*min-max)) << 16) | (UINT32)(max);

        if (x2 > x1) { // +X direction
            if (y2 > y1) // +Y direction
                direction_code = XpYpYl;
            else // -Y direction
                direction_code = XpYmYl;
        } else { // -X direction
            if (y2 > y1) // +Y direction
                direction_code = XmYpYl;
            else // -Y direction
                direction_code = XmYmYl;
        }
    }

    outpw(REG_GE2D_BETSC, step_constant);
    outpw(REG_GE2D_BIEPC, initial_error);

    cmd32 = 0x009b0000 | direction_code; // styled line
    if (draw_mode==MODE_TRANSPARENT) {
        cmd32 |= 0x00008000; // default is MODE_OPAQUE
    }
    outpw(REG_GE2D_CTL, cmd32);

    outpw(REG_GE2D_BGCOLR, make_color(bkcolor));
    outpw(REG_GE2D_FGCOLR, make_color(fgcolor));

    dest_pitch = GFX_WIDTH << 16; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, dest_pitch);

    outpw(REG_GE2D_XYDORG, (int)GFX_START_ADDR);

    dest_start = y1 << 16 | x1;
    outpw(REG_GE2D_DSTSPA, dest_start);

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    line_control_code = style;
    temp32 = inpw(REG_GE2D_MISCTL) & 0x0000ffff;
    temp32 = (line_control_code << 16) | temp32;

    outpw(REG_GE2D_MISCTL, temp32); // address caculation

    outpw(REG_GE2D_TRG, 1);

    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete

    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Draw a styled line using RGB565 color
  * @param[in] x1 is top-left x position
  * @param[in] y1 is top-left y position
  * @param[in] x2 is down-right x position
  * @param[in] y2 is down-right y position
  * @param[in] style is style of line pattern
  * @param[in] fgcolor is color of foreground
  * @param[in] bkcolor is color of background
  * @param[in] draw_mode is transparent is enable or not
  * @return none
  */
void ge2dLine_DrawStyledLine_RGB565(int x1, int y1, int x2, int y2, int style, int fgcolor, int bkcolor, int draw_mode)
{
    int abs_X, abs_Y, min, max;
    UINT32 step_constant, initial_error, direction_code;
    UINT32 cmd32, dest_pitch, dest_start;
    UINT32 temp32, line_control_code;

    abs_X = ABS(x2-x1);
    abs_Y = ABS(y2-y1);
    if (abs_X > abs_Y) { // X major
        max = abs_X;
        min = abs_Y;

        step_constant = (((UINT32)(2*(min-max))) << 16) | (UINT32)(2*min);
        initial_error = (((UINT32)(2*min-max)) << 16) | (UINT32)(max);

        if (x2 > x1) { // +X direction
            if (y2 > y1) // +Y direction
                direction_code = XpYpXl;
            else // -Y direction
                direction_code = XpYmXl;
        } else { // -X direction
            if (y2 > y1) // +Y direction
                direction_code = XmYpXl;
            else // -Y direction
                direction_code = XmYmXl;
        }
    } else { // Y major
        max = abs_Y;
        min = abs_X;

        step_constant = (((UINT32)(2*(min-max))) << 16) | (UINT32)(2*min);
        initial_error = (((UINT32)(2*min-max)) << 16) | (UINT32)(max);

        if (x2 > x1) { // +X direction
            if (y2 > y1) // +Y direction
                direction_code = XpYpYl;
            else // -Y direction
                direction_code = XpYmYl;
        } else { // -X direction
            if (y2 > y1) // +Y direction
                direction_code = XmYpYl;
            else // -Y direction
                direction_code = XmYmYl;
        }
    }

    outpw(REG_GE2D_BETSC, step_constant);
    outpw(REG_GE2D_BIEPC, initial_error);

    cmd32 = 0x009b0000 | direction_code; // styled line
    if (draw_mode==MODE_TRANSPARENT) {
        cmd32 |= 0x00008000; // default is MODE_OPAQUE
    }
    outpw(REG_GE2D_CTL, cmd32);

    outpw(REG_GE2D_BGCOLR, bkcolor);
    outpw(REG_GE2D_FGCOLR, fgcolor);

    dest_pitch = GFX_WIDTH << 16; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, dest_pitch);

    outpw(REG_GE2D_XYDORG, (int)GFX_START_ADDR);

    dest_start = y1 << 16 | x1;
    outpw(REG_GE2D_DSTSPA, dest_start);

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    line_control_code = style;
    temp32 = inpw(REG_GE2D_MISCTL) & 0x0000ffff;
    temp32 = (line_control_code << 16) | temp32;

    outpw(REG_GE2D_MISCTL, temp32); // address caculation

    outpw(REG_GE2D_TRG, 1);

    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete

    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Rectangle solid color fill with foreground color.
  * @param[in] dx x position
  * @param[in] dy y position
  * @param[in] width is display width
  * @param[in] height is display height
  * @param[in] color is color of foreground
  * @return none
  */
void ge2dFill_Solid(int dx, int dy, int width, int height, int color)
{
    UINT32 cmd32, color32;
    UINT32 dest_start, dest_pitch, dest_dimension;

#ifdef DEBUG
    sysprintf("solid_fill()\n");
    sysprintf("(%d,%d)-(%d,%d)\n", dx, dy, dx+width-1, dy+height-1);
    sysprintf("color=0x%x\n", color);
#endif

    color32 = make_color(color);
    cmd32 = 0xcc430060;
    outpw(REG_GE2D_CTL, cmd32);
    outpw(REG_GE2D_FGCOLR, color32); // fill with foreground color

    dest_pitch = GFX_WIDTH << 16; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, dest_pitch);

    dest_start = dy << 16 | dx;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dest_dimension = height << 16 | width;
    outpw(REG_GE2D_RTGLSZ, dest_dimension);

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    outpw(REG_GE2D_CTL, cmd32);

    outpw(REG_GE2D_TRG, 1);

    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete

    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Rectangle solid color fill with RGB565 color.
  * @param[in] dx x position
  * @param[in] dy y position
  * @param[in] width is display width
  * @param[in] height is display height
  * @param[in] color is RGB565 color of foreground
  * @return none
  */
void ge2dFill_Solid_RGB565(int dx, int dy, int width, int height, int color)
{
    UINT32 cmd32;
    UINT32 dest_start, dest_pitch, dest_dimension;

#ifdef DEBUG
    sysprintf("solid_fill()\n");
    sysprintf("(%d,%d)-(%d,%d)\n", dx, dy, dx+width-1, dy+height-1);
    sysprintf("color=0x%x\n", color);
#endif

    cmd32 = 0xcc430060;
    outpw(REG_GE2D_CTL, cmd32);
    outpw(REG_GE2D_FGCOLR, color); // fill with foreground color

    dest_pitch = GFX_WIDTH << 16; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, dest_pitch);

    dest_start = dy << 16 | dx;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dest_dimension = height << 16 | width;
    outpw(REG_GE2D_RTGLSZ, dest_dimension);

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    outpw(REG_GE2D_CTL, cmd32);

    outpw(REG_GE2D_TRG, 1);

    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete

    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Rectangle solid color fill with background color.
  * @param[in] dx x position
  * @param[in] dy y position
  * @param[in] width is display width
  * @param[in] height is display height
  * @param[in] color is color of background
  * @return none
  */
void ge2dFill_SolidBackground(int dx, int dy, int width, int height, int color)
{
    UINT32 cmd32, color32;
    UINT32 dest_start, dest_pitch, dest_dimension;

#ifdef DEBUG
    sysprintf("solid_fill_back()\n");
    sysprintf("(%d,%d)-(%d,%d)\n", dx, dy, dx+width-1,dy+height-1);
    sysprintf("color=0x%x\n", color);
#endif

    color32 = make_color(color);

    cmd32 = 0xcc430040;
    outpw(REG_GE2D_CTL, cmd32);
    outpw(REG_GE2D_BGCOLR, color32); // fill with foreground color

    dest_pitch = GFX_WIDTH << 16; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, dest_pitch);

    dest_start = dy << 16 | dx;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dest_dimension = height << 16 | width;
    outpw(REG_GE2D_RTGLSZ, dest_dimension);

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    outpw(REG_GE2D_CTL, cmd32);

    outpw(REG_GE2D_TRG, 1);

    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete

    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Rectangle fill with 8x8 color pattern.
  * @param[in] dx x position
  * @param[in] dy y position
  * @param[in] width is display width
  * @param[in] height is display height
  * @return none
  * @note The color pattern data is stored in the off-screen buffer.
  */
void ge2dFill_ColorPattern(int dx, int dy, int width, int height)
{
    UINT32 cmd32;
    UINT32 dest_start, dest_pitch, dest_dimension;

#ifdef DEBUG
    sysprintf("color_pattern_fill()\n");
    sysprintf("(%d,%d)-(%d,%d)\n", dx, dy, dx+width-1, dy+height-1);
    sysprintf("pattern offset (%d,%d)\n", dx%8, dy%8);
#endif

    cmd32 = 0xf0430000;
    outpw(REG_GE2D_CTL, cmd32);

    dest_pitch = GFX_WIDTH << 16; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, dest_pitch);

    dest_start = dy << 16 | dx;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dest_dimension = height << 16 | width;
    outpw(REG_GE2D_RTGLSZ, dest_dimension);

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    outpw(REG_GE2D_TRG, 1);
    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete
    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Rectangle fill with 8x8 mono pattern.
  * @param[in] dx x position
  * @param[in] dy y position
  * @param[in] width is display width
  * @param[in] height is display height
  * @param[in] opt is transparent is enable or not
  * @return none
  */
void ge2dFill_MonoPattern(int dx, int dy, int width, int height, int opt)
{
    UINT32 cmd32;
    UINT32 dest_start, dest_pitch, dest_dimension;

#ifdef DEBUG
    sysprintf("mono_pattern_fill()\n");
    sysprintf("(%d,%d)-(%d,%d)\n", dx, dy, dx+width-1, dy+height-1);
#endif

    cmd32 = 0xf0430010;
    if (opt==MODE_TRANSPARENT) {
        cmd32 |= 0x00006000;
    }
    outpw(REG_GE2D_CTL, cmd32);

    dest_pitch = GFX_WIDTH << 16; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, dest_pitch);

    dest_start = dy << 16 | dx;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dest_dimension = height << 16 | width;
    outpw(REG_GE2D_RTGLSZ, dest_dimension);

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    outpw(REG_GE2D_TRG, 1);
    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete
    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Rectangle fill with 8x8 color pattern.
  * @param[in] sx x position
  * @param[in] sy y position
  * @param[in] width is display width
  * @param[in] height is display height
  * @param[in] rop is ROP operation code
  * @return none
  */
void ge2dFill_ColorPatternROP(int sx, int sy, int width, int height, int rop)
{
    UINT32 cmd32;
    UINT32 dest_start, dest_pitch, dest_dimension;

#ifdef DEBUG
    sysprintf("color_pattern_fill()\n");
    sysprintf("(%d,%d)-(%d,%d)\n", sx, sy, sx+width-1, sy+height-1);
    sysprintf("pattern offset (%d,%d)\n", sx%8, sy%8);
#endif

    cmd32 = 0x00430000 | (rop<<24);
    outpw(REG_GE2D_CTL, cmd32);

    dest_pitch = GFX_WIDTH << 16; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, dest_pitch);

    dest_start = sy << 16 | sx;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dest_dimension = height << 16 | width;
    outpw(REG_GE2D_RTGLSZ, dest_dimension);

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    outpw(REG_GE2D_TRG, 1);
    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete
    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Rectangle fill with 8x8 mono pattern.
  * @param[in] sx x position
  * @param[in] sy y position
  * @param[in] width is display width
  * @param[in] height is display height
  * @param[in] opt is transparent is enable or not
  * @param[in] rop is ROP operation code
  * @return none
  */
void ge2dFill_MonoPatternROP(int sx, int sy, int width, int height, int rop, int opt)
{
    UINT32 cmd32;
    UINT32 dest_start, dest_pitch, dest_dimension;

#ifdef DEBUG
    sysprintf("mono_pattern_fill()\n");
    sysprintf("(%d,%d)-(%d,%d)\n", sx, sy, sx+width-1, sy+height-1);
#endif

    cmd32 = 0x00430010 | (rop<<24);
    if (opt==MODE_TRANSPARENT) {
        cmd32 |= 0x00006000;
    }
    outpw(REG_GE2D_CTL, cmd32);

    dest_pitch = GFX_WIDTH << 16; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, dest_pitch);

    dest_start = sy << 16 | sx;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dest_dimension = height << 16 | width;
    outpw(REG_GE2D_RTGLSZ, dest_dimension);

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    outpw(REG_GE2D_TRG, 1);

    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete

    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief TileBLT function.
  * @param[in] srcx source x position
  * @param[in] srcy source y position
  * @param[in] destx destination x position
  * @param[in] desty destination y position
  * @param[in] width is display width
  * @param[in] height is display height
  * @param[in] x_count is tile count for x-axis
  * @param[in] y_count is tile count for y-axis
  * @return none
  */
void ge2dFill_TileBlt(int srcx, int srcy, int destx, int desty, int width, int height, int x_count, int y_count)
{
    UINT32 cmd32, pitch, dest_start, src_start, dimension;
    UINT32 tile_ctl;

#ifdef DEBUG
    sysprintf("tile_blt_image()\n");
    sysprintf("(%d,%d)=>(%d,%d)\n", srcx, srcy, destx, desty);
    sysprintf("width=%d height=%d\n", width, height);
    sysprintf("%dx%d grids\n", x_count, y_count);
#endif

    if (x_count > 0) x_count--;
    if (y_count > 0) y_count--;

    cmd32 = 0xcc430400; // b10 is the tile control

    outpw(REG_GE2D_CTL, cmd32);

    pitch = GFX_WIDTH << 16 | GFX_WIDTH; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, pitch);

    src_start = srcy << 16 | srcx;           // redundancy ??
    outpw(REG_GE2D_SRCSPA, src_start);  // redundancy ??

    dest_start = desty << 16 | destx;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dimension = height << 16 | width;
    outpw(REG_GE2D_RTGLSZ, dimension);

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    tile_ctl = (y_count << 8) | (x_count);
    outpw(REG_GE2D_TCNTVHSF, tile_ctl);

    outpw(REG_GE2D_TRG, 1);
    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete
    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Host-to-Screen BitBlt with SRCCOPY (through data port)
  * @param[in] x x position
  * @param[in] y y position
  * @param[in] width is display width
  * @param[in] height is display height
  * @param[in] buf is pointer of HostBLT data
  * @return none
  */
void ge2dHostBlt_Write(int x, int y, int width, int height, void *buf)
{
    UINT32 cmd32, dest_pitch, dest_start, dest_dimension;
    int transfer_count, i, j;
    UINT32 *ptr32, data32;

#ifdef DEBUG
    sysprintf("host_write_blt()\n");
    sysprintf("(%d,%d)-(%d,%d)\n", x, y, x+width-1, y+height-1);
    sysprintf("width=%d height=%d\n", width, height);
#endif

    cmd32 = 0xcc430020;

    outpw(REG_GE2D_CTL, cmd32);

    dest_pitch = GFX_WIDTH << 16; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, dest_pitch);

    dest_start = y << 16 | x;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dest_dimension = height << 16 | width;
    outpw(REG_GE2D_RTGLSZ, dest_dimension);

    outpw(REG_GE2D_TRG, 1);

    ptr32 = (UINT32 *)buf;
    for (i=0; i<height; i++) { // 120
        transfer_count = (width * (GFX_BPP/8) + 3) / 4; // 4-byte count

        while (transfer_count >= 8) {
            while ((inpw(REG_GE2D_MISCTL) & 0x00000800)==0); // check empty
            for (j=0; j<8; j++) {
                data32 = *ptr32++;
                outpw(REG_GE2D_GEHBDW0, data32);
            }
            transfer_count -= 8;
        }

        if (transfer_count > 0) {
            while ((inpw(REG_GE2D_MISCTL) & 0x00000800)==0); // check empty
            for (j=0; j<transfer_count; j++) {
                data32 = *ptr32++;
                outpw(REG_GE2D_GEHBDW0, data32);
            }
        }
    }

    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete
    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Screen-to-Host BitBlt with SRCCOPY (through data port).
  * @param[in] x x position
  * @param[in] y y position
  * @param[in] width is display width
  * @param[in] height is display height
  * @param[in] buf is pointer of HostBLT data
  * @return none
  */
void ge2dHostBlt_Read(int x, int y, int width, int height, void *buf)
{
    UINT32 cmd32, dest_pitch, dest_start, dest_dimension;
    int transfer_count, i, j;
    UINT32 *ptr32;

#ifdef DEBUG
    sysprintf("host_read_blt()\n");
    sysprintf("(%d,%d)-(%d,%d)\n", x, y, x+width-1, y+height-1);
    sysprintf("width=%d height=%d\n", width, height);
#endif

    cmd32 = 0xcc430001;

    outpw(REG_GE2D_CTL, cmd32);

    dest_pitch = GFX_WIDTH << 16; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, dest_pitch);

    dest_start = y << 16 | x;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dest_dimension = height << 16 | width;
    outpw(REG_GE2D_RTGLSZ, dest_dimension);

    outpw(REG_GE2D_TRG, 1);

    ptr32 = (UINT32 *)buf;
    for (i=0; i<height; i++) {
        transfer_count = (width * (GFX_BPP/8) + 3) / 4; // 4-byte count

        while (transfer_count >= 8) {
            while ((inpw(REG_GE2D_MISCTL) & 0x00000400)==0);
            for (j=0; j<8; j++) {
                *ptr32++ = inpw(REG_GE2D_GEHBDW0);
            }
            transfer_count -= 8;
        }

        if (transfer_count > 0) {
            while (((inpw(REG_GE2D_MISCTL) & 0x0000f000)>>12) != transfer_count);
            for (j=0; j<transfer_count; j++) {
                *ptr32++ = inpw(REG_GE2D_GEHBDW0);
            }
        }
    }

    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete

    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Host-to-Screen SpriteBlt with SRCCOPY.
  * @param[in] x x position
  * @param[in] y y position
  * @param[in] width is display width
  * @param[in] height is display height
  * @param[in] buf is pointer of HostBLT data
  * @return none
  */
void ge2dHostBlt_Sprite(int x, int y, int width, int height, void *buf)
{
    UINT32 cmd32, dest_pitch, dest_start, dest_dimension;
    int transfer_count, i, j;
    UINT32 *ptr32, data32, alpha;

#ifdef DEBUG
    sysprintf("host_sprite_blt()\n");
    sysprintf("(%d,%d)-(%d,%d)\n", x, y, x+width-1, y+height-1);
#endif

    cmd32 = 0xcc430020;

    outpw(REG_GE2D_CTL, cmd32);

    dest_pitch = GFX_WIDTH << 16; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, dest_pitch);

    dest_start = y << 16 | x;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dest_dimension = height << 16 | width;
    outpw(REG_GE2D_RTGLSZ, dest_dimension);

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    if (_DrawMode==MODE_TRANSPARENT) {
        cmd32 |= 0x00008000; // color transparency
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_TRNSCOLR, _ColorKey);
        outpw(REG_GE2D_TCMSK, _ColorKeyMask);
    } else if (_DrawMode==MODE_DEST_TRANSPARENT) {
        cmd32 |= 0x00009000;
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_TRNSCOLR, _ColorKey);
        outpw(REG_GE2D_TCMSK, _ColorKeyMask);
    }

    if (_EnableAlpha) {
        cmd32 |= 0x00200000;
        outpw(REG_GE2D_CTL, cmd32);

        data32 = inpw(REG_GE2D_MISCTL) & 0x0000ffff;
        alpha = (UINT32)((_AlphaKs << 8) | _AlphaKd);
        data32 |= (alpha << 16);

        outpw(REG_GE2D_MISCTL, data32);
    }

    outpw(REG_GE2D_TRG, 1);

    ptr32 = (UINT32 *)buf;
    for (i=0; i<height; i++) {
        transfer_count = width * (GFX_BPP/8) / 4; // 4-byte count

        while (transfer_count > 8) {
            while ((inpw(REG_GE2D_MISCTL) & 0x00000800)==0); // check empty
            for (j=0; j<8; j++) {
                data32 = *ptr32++;
                outpw(REG_GE2D_GEHBDW0, data32);
            }
            transfer_count -= 8;
        }

        if (transfer_count > 0) {
            while ((inpw(REG_GE2D_MISCTL) & 0x00000800)==0); // check empty
            for (j=0; j<transfer_count; j++) {
                data32 = *ptr32++;
                outpw(REG_GE2D_GEHBDW0, data32);
            }
        }
    }

    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete

    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Captured the specified photo data from display memory, then displayed on display memory by rotation angle
  * @param[in] srcx source x position
  * @param[in] srcy source y position
  * @param[in] destx destination x position
  * @param[in] desty destination y position
  * @param[in] width is display width
  * @param[in] height is display height
  * @param[in] ctl is drawing direction
  * @return none
  */
void ge2dRotation(int srcx, int srcy, int destx, int desty, int width, int height, int ctl)
{
    UINT32 cmd32, dest_start, src_start, dimension, pitch;
    void *tmpscreen,*orig_dest_start00;

    tmpscreen = (void *)malloc(width*height*GFX_BPP/8);

#ifdef DEBUG
    sysprintf("rotation_image()\n");
    sysprintf("(%d,%d)=>(%d,%d)\n", srcx, srcy, destx, desty);
    sysprintf("width=%d height=%d\n", width, height);
#endif

    memset(tmpscreen,0,width*height*GFX_BPP/8);

    orig_dest_start00 = (void *)inpw(REG_GE2D_XYDORG);
    outpw(REG_GE2D_XYDORG, (int)tmpscreen);   //captured photo to another position
    outpw(REG_GE2D_XYSORG, (int)GFX_START_ADDR);

    ge2dBitblt_SourceToDestination(srcx,srcy,0,0,width,height,GFX_WIDTH,width);

    src_start = dest_start = dimension = cmd32 = pitch = 0;

    outpw(REG_GE2D_XYDORG, (int)orig_dest_start00);
    outpw(REG_GE2D_XYSORG, (int)tmpscreen);

    pitch = GFX_WIDTH << 16 | width;
    outpw(REG_GE2D_SDPITCH, pitch);

    src_start = 0 << 16 | 0;  // captured photo at (0,0) position
    outpw(REG_GE2D_SRCSPA, src_start);

    dest_start = desty << 16 | destx;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dimension = height << 16 | width;
    outpw(REG_GE2D_RTGLSZ, dimension);

    cmd32 = 0xcc030000 | (ctl << 1);

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    /* set rotation reference point xy register, then nothing happened */
    outpw(REG_GE2D_CTL, cmd32);

    outpw(REG_GE2D_TRG, 1);
    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete
    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status

    free(tmpscreen);
}

/**
  * @brief OffScreen-to-OnScreen SpriteBlt with SRCCOPY.
  * @param[in] destx destination x position
  * @param[in] desty destination y position
  * @param[in] sprite_width is sprite width
  * @param[in] sprite_height is sprite height
  * @param[in] buf is pointer of origin data
  * @return none
  */
void ge2dSpriteBlt_Screen(int destx, int desty, int sprite_width, int sprite_height, void *buf)
{
    UINT32 cmd32, pitch, dest_start, src_start, dimension;
    UINT32 data32, alpha;

#ifdef DEBUG
    sysprintf("screen_sprite_blt():\n");
    sysprintf("x=%d y=%d width=%d height=%d\n", destx, desty, sprite_width, sprite_height);
#endif

    cmd32 = 0xcc430000;

    outpw(REG_GE2D_CTL, cmd32);

    pitch = GFX_WIDTH << 16 | sprite_width; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, pitch);

    src_start = 0; // start from (0,0) of sprite
    outpw(REG_GE2D_SRCSPA, src_start);

    dest_start = desty << 16 | destx;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dimension = sprite_height << 16 | sprite_width;
    outpw(REG_GE2D_RTGLSZ, dimension);

    outpw(REG_GE2D_XYSORG, (UINT32)buf);
    outpw(REG_GE2D_XYDORG, (int)GFX_START_ADDR);

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }


    if (_DrawMode==MODE_TRANSPARENT) {
        cmd32 |= 0x00008000; // color transparency
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_TRNSCOLR, _ColorKey);
        outpw(REG_GE2D_TCMSK, _ColorKeyMask);
    } else if (_DrawMode==MODE_DEST_TRANSPARENT) {
        cmd32 |= 0x00009000;   // destination pixels control transparency
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_TRNSCOLR, _ColorKey);
        outpw(REG_GE2D_TCMSK, _ColorKeyMask);
    }


    if (_EnableAlpha) {
        cmd32 |= 0x00200000;
        outpw(REG_GE2D_CTL, cmd32);

        data32 = inpw(REG_GE2D_MISCTL) & 0x0000ffff;
        alpha = (UINT32)((_AlphaKs << 8) | _AlphaKd);
        data32 |= (alpha << 16);

        outpw(REG_GE2D_MISCTL, data32);
    }

    outpw(REG_GE2D_CTL, cmd32);

    outpw(REG_GE2D_TRG, 1);
    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete
    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief OffScreen-to-OnScreen SpriteBlt with SRCCOPY.
  * @param[in] x x position
  * @param[in] y y position
  * @param[in] sprite_sx sprite x position
  * @param[in] sprite_sy sprite y position
  * @param[in] width is width
  * @param[in] height is height
  * @param[in] sprite_width is sprite width
  * @param[in] sprite_height is sprite height
  * @param[in] buf is pointer of origin data
  * @return none
  * @note The sprite starting address can be programmed.
  */
void ge2dSpriteBltx_Screen(int x, int y, int sprite_sx, int sprite_sy, int width, int height, int sprite_width, int sprite_height, void *buf)
{
    UINT32 cmd32, pitch, dest_start, src_start, dimension;
    UINT32 data32, alpha;

#ifdef DEBUG
    sysprintf("screen_sprite_bltx(): (%d,%d)\n", x, y);
    sysprintf("sprite width=%d height=%d\n", sprite_width, sprite_height);
    sysprintf("x=%d y=%d width=%d height=%d\n", sprite_sx, sprite_sy, width, height);
#endif

    cmd32 = 0xcc430000;

    outpw(REG_GE2D_CTL, cmd32);

    pitch = GFX_WIDTH << 16 | sprite_width; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, pitch);

    outpw(REG_GE2D_XYSORG, (UINT32)buf);
    outpw(REG_GE2D_XYDORG, (int)GFX_START_ADDR);

    src_start = sprite_sy << 16 | sprite_sx;
    outpw(REG_GE2D_SRCSPA, src_start);

    dest_start = y << 16 | x;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dimension = height << 16 | width;
    outpw(REG_GE2D_RTGLSZ, dimension);

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    if (_DrawMode==MODE_TRANSPARENT) {
        cmd32 |= 0x00008000; // color transparency
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_TRNSCOLR, _ColorKey);
        outpw(REG_GE2D_TCMSK, _ColorKeyMask);
    } else if (_DrawMode==MODE_DEST_TRANSPARENT) {
        cmd32 |= 0x00009000;   // destination pixels control transparency
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_TRNSCOLR, _ColorKey);
        outpw(REG_GE2D_TCMSK, _ColorKeyMask);
    }

    if (_EnableAlpha) {
        cmd32 |= 0x00200000;
        outpw(REG_GE2D_CTL, cmd32);

        data32 = inpw(REG_GE2D_MISCTL) & 0x0000ffff;
        alpha = (UINT32)((_AlphaKs << 8) | _AlphaKd);
        data32 |= (alpha << 16);

        outpw(REG_GE2D_MISCTL, data32);
    }

    outpw(REG_GE2D_TRG, 1);
    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete
    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief OffScreen-to-OnScreen SpriteBlt with ROP.
  * @param[in] x x position
  * @param[in] y y position
  * @param[in] sprite_width is sprite width
  * @param[in] sprite_height is sprite height
  * @param[in] buf is pointer of origin data
  * @param[in] rop is ROP operation code
  * @return none
  * @note The sprite always starts from (0,0) for the BLT.
  */
void ge2dSpriteBlt_ScreenRop(int x, int y, int sprite_width, int sprite_height, void *buf, int rop)
{
    UINT32 cmd32, pitch, dest_start, src_start, dimension;
    UINT32 data32, alpha;

#ifdef DEBUG
    sysprintf("screen_sprite_rop_blt():\n");
    sysprintf("x=%d y=%d width=%d height=%d\n", x, y, sprite_width, sprite_height);
    sysprintf("rop=0x%x\n", rop);
#endif

    cmd32 = 0x00430000 | (rop << 24);

    if (_PatternType==TYPE_MONO) {
        cmd32 |= 0x00000010; // default is TYPE_COLOR
    }

    outpw(REG_GE2D_CTL, cmd32);

    pitch = GFX_WIDTH << 16 | sprite_width; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, pitch);

    src_start = 0; // start from (0,0) of sprite
    outpw(REG_GE2D_SRCSPA, src_start);

    dest_start = y << 16 | x;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dimension = sprite_height << 16 | sprite_width;
    outpw(REG_GE2D_RTGLSZ, dimension);

    outpw(REG_GE2D_XYSORG, (UINT32)buf);
    outpw(REG_GE2D_XYDORG,(int) GFX_START_ADDR);  //smf

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    if (_DrawMode==MODE_TRANSPARENT) {
        cmd32 |= 0x00008000; // color transparency
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_TRNSCOLR, _ColorKey);
        outpw(REG_GE2D_TCMSK, _ColorKeyMask);
    } else if (_DrawMode==MODE_DEST_TRANSPARENT) {
        cmd32 |= 0x00009000;   // destination pixels control transparency
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_TRNSCOLR, _ColorKey);
        outpw(REG_GE2D_TCMSK, _ColorKeyMask);
    }

    if (_EnableAlpha) {
        cmd32 |= 0x00200000;
        outpw(REG_GE2D_CTL, cmd32);

        data32 = inpw(REG_GE2D_MISCTL) & 0x0000ffff;
        alpha = (UINT32)((_AlphaKs << 8) | _AlphaKd);
        data32 |= (alpha << 16);

        outpw(REG_GE2D_MISCTL, data32);
    }

    if ((rop==0x00) || (rop==0xff)) {
        cmd32 = (cmd32 & 0xffff0fff) | 0x00009000;
        outpw(REG_GE2D_CTL, cmd32);
    }

    outpw(REG_GE2D_TRG, 1);
    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete
    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief OffScreen-to-OnScreen SpriteBlt with ROP.
  * @param[in] x x position
  * @param[in] y y position
  * @param[in] sprite_sx sprite x position
  * @param[in] sprite_sy sprite y position
  * @param[in] width is width
  * @param[in] height is height
  * @param[in] sprite_width is sprite width
  * @param[in] sprite_height is sprite height
  * @param[in] buf is pointer of origin data
  * @param[in] rop is ROP operation code
  * @return none
  * @note The sprite always starts from (0,0) for the BLT.
  */
void ge2dSpriteBltx_ScreenRop(int x, int y, int sprite_sx, int sprite_sy, int width, int height, int sprite_width, int sprite_height, void *buf, int rop)
{
    UINT32 cmd32, pitch, dest_start, src_start, dimension;
    UINT32 data32, alpha;

#ifdef DEBUG
    sysprintf("screen_sprite_rop_bltx():\n");
    sysprintf("x=%d y=%d width=%d height=%d\n", x, y, sprite_width, sprite_height);
    sysprintf("rop=0x%x\n", rop);
#endif

    cmd32 = 0x00430000 | (rop << 24);

    if (_PatternType==TYPE_MONO) {
        cmd32 |= 0x00000010; // default is TYPE_COLOR
    }

    outpw(REG_GE2D_CTL, cmd32);

    pitch = GFX_WIDTH << 16 | sprite_width; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, pitch);

    src_start = sprite_sy << 16 | sprite_sx;
    outpw(REG_GE2D_SRCSPA, src_start);

    dest_start = y << 16 | x;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dimension = height << 16 | width;
    outpw(REG_GE2D_RTGLSZ, dimension);

    outpw(REG_GE2D_XYSORG, (UINT32)buf);
    outpw(REG_GE2D_XYDORG, (int)GFX_START_ADDR);  //smf

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    if (_DrawMode==MODE_TRANSPARENT) {
        cmd32 |= 0x00008000; // color transparency
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_TRNSCOLR, _ColorKey);
        outpw(REG_GE2D_TCMSK, _ColorKeyMask);
    } else if (_DrawMode==MODE_DEST_TRANSPARENT) {
        cmd32 |= 0x00009000;   // destination pixels control transparency
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_TRNSCOLR, _ColorKey);
        outpw(REG_GE2D_TCMSK, _ColorKeyMask);
    }

    if (_EnableAlpha) {
        cmd32 |= 0x00200000;
        outpw(REG_GE2D_CTL, cmd32);

        data32 = inpw(REG_GE2D_MISCTL) & 0x0000ffff;
        alpha = (UINT32)((_AlphaKs << 8) | _AlphaKd);
        data32 |= (alpha << 16);

        outpw(REG_GE2D_MISCTL, data32);
    }

    if ((rop==0x00) || (rop==0xff)) {
        cmd32 = (cmd32 & 0xffff0fff) | 0x00009000;
        outpw(REG_GE2D_CTL, cmd32);
    }

    outpw(REG_GE2D_TRG, 1);
    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete
    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief OffScreen-to-OnScreen TextBLT.
  * @param[in] x x position
  * @param[in] y y position
  * @param[in] width is width
  * @param[in] height is height
  * @param[in] fore_color is color of foreground
  * @param[in] back_color is color of background
  * @param[in] opt is transparent is enable or not
  * @param[in] buf is pointer of origin data
  * @return none
  * @note Fetch the monochrome source data from off-screen memory to the desired destination area
  */
void ge2dColorExpansionBlt(int x, int y, int width, int height, int fore_color, int back_color, int opt, void *buf)
{
    UINT32 cmd32, dest_pitch, src_pitch, pitch, dest_start, dest_dimension;
    UINT32 fore_color32, back_color32;

    fore_color32 = make_color(fore_color);
    back_color32 = make_color(back_color);

    cmd32 = 0xcc430080;
    if (opt==MODE_TRANSPARENT) {
        cmd32 |= 0x00004000; // mono transparency
    }

    outpw(REG_GE2D_CTL, cmd32);

    outpw(REG_GE2D_FGCOLR, fore_color32);
    outpw(REG_GE2D_BGCOLR, back_color32);

    dest_pitch = GFX_WIDTH; // pitch in pixels
    src_pitch = width; // pitch in pixels

    pitch = (dest_pitch << 16) | src_pitch;
    outpw(REG_GE2D_SDPITCH, pitch);

    outpw(REG_GE2D_XYSORG, (int)buf);
    outpw(REG_GE2D_SRCSPA, 0); // always start from (0,0)

    dest_start = y << 16 | x;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dest_dimension = height << 16 | width;
    outpw(REG_GE2D_RTGLSZ, dest_dimension);

    if (_ClipEnable) {
        cmd32 |= 0x00000200;
        if (_OutsideClip) {
            cmd32 |= 0x00000100;
        }
        outpw(REG_GE2D_CTL, cmd32);
        outpw(REG_GE2D_CLPBTL, _ClipTL);
        outpw(REG_GE2D_CLPBBR, _ClipBR);
    }

    outpw(REG_GE2D_TRG, 1);
    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete
    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Host-to-Screen TextBLT through data port.
  * @param[in] x x position
  * @param[in] y y position
  * @param[in] width is width
  * @param[in] height is height
  * @param[in] fore_color is color of foreground
  * @param[in] back_color is color of background
  * @param[in] opt is transparent is enable or not
  * @param[in] buf is pointer of origin data
  * @return none
  */
void ge2dHostColorExpansionBlt(int x, int y, int width, int height, int fore_color, int back_color, int opt, void *buf)
{
    UINT32 cmd32, dest_pitch, dest_start, dest_dimension;
    UINT32 fore_color32, back_color32;
    UINT32 *ptr32, data32;
    int transfer_count, i, j;

    fore_color32 = make_color(fore_color);
    back_color32 = make_color(back_color);

    cmd32 = 0xcc4300a0;
    if (opt==MODE_TRANSPARENT) {
        cmd32 |= 0x00004000; // mono transparency
    }

    outpw(REG_GE2D_CTL, cmd32);

    outpw(REG_GE2D_FGCOLR, fore_color32);
    outpw(REG_GE2D_BGCOLR, back_color32);

    dest_pitch = GFX_WIDTH << 16; // pitch in pixel
    outpw(REG_GE2D_SDPITCH, dest_pitch);

    dest_start = y << 16 | x;
    outpw(REG_GE2D_DSTSPA, dest_start);
    outpw(REG_GE2D_SRCSPA, dest_start);

    dest_dimension = height << 16 | width;
    outpw(REG_GE2D_RTGLSZ, dest_dimension);

    outpw(REG_GE2D_TRG, 1);

    ptr32 = (UINT32 *)buf;
    for (i=0; i<height; i++) {
        transfer_count = (width+31) / 32; // 32 pixels unit

        while (transfer_count > 8) {
            while ((inpw(REG_GE2D_MISCTL) & 0x00000800)==0); // check empty
            for (j=0; j<8; j++) {
                data32 = *ptr32++;
                outpw(REG_GE2D_GEHBDW0, data32);
            }
            transfer_count -= 8;
        }

        if (transfer_count > 0) {
            while ((inpw(REG_GE2D_MISCTL) & 0x00000800)==0); // check empty
            for (j=0; j<transfer_count; j++) {
                data32 = *ptr32++;
                outpw(REG_GE2D_GEHBDW0, data32);
            }
        }
    }

    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete

    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Set the 8x8 mono pattern for following BitBLT functions.
  * @param[in] opt is index for build-in pattern
  * @param[in] fore_color is color of foreground
  * @param[in] back_color is color of background
  * @return none
  */
void ge2dInitMonoPattern(int opt, int fore_color, int back_color)
{
    UINT32 color32;

    /*
    ** If hardware pattern definition is a little different from software.
    ** Need to do the BYTE swap before programming the pattern registers.
    */

    outpw(REG_GE2D_PTNA, MonoPatternData[opt].PatternA);
    outpw(REG_GE2D_PTNB, MonoPatternData[opt].PatternB);

    color32 = make_color(fore_color);
    outpw(REG_GE2D_FGCOLR, color32);

    color32 = make_color(back_color);
    outpw(REG_GE2D_BGCOLR, color32);

    _PatternType = TYPE_MONO;
}

/**
  * @brief Set the 8x8 mono pattern for following BitBLT functions.
  * @param[in] PatternA is pattern A
  * @param[in] PatternB is pattern B
  * @param[in] fore_color is color of foreground
  * @param[in] back_color is color of background
  * @return none
  */
void ge2dInitMonoInputPattern(UINT32 PatternA, UINT32 PatternB, int fore_color, int back_color)
{
    UINT32 color32;

    /*
    ** If hardware pattern definition is a little different from software.
    ** Need to do the BYTE swap before programming the pattern registers.
    */

    outpw(REG_GE2D_PTNA, PatternA);
    outpw(REG_GE2D_PTNB, PatternB);

    color32 = make_color(fore_color);
    outpw(REG_GE2D_FGCOLR, color32);

    color32 = make_color(back_color);
    outpw(REG_GE2D_BGCOLR, color32);

    _PatternType = TYPE_MONO;
}

/**
  * @brief Set the 8x8 color pattern for following BitBLT functions.
  * @param[in] patformat is format of pattern, value could be
  *                                     - \ref RGB888
  *                                     - \ref RGB565
  *                                     - \ref RGB332
  * @param[in] patdata is pointer of input pattern image
  * @return none
  * @note This function transfers those forms:
  *   RGB888 to RGB565 or RGB332
  *   RGB565 to RGB332 or RGB888
  *   RGB332 to RGB565 or RGB888
  */
void ge2dInitColorPattern(int patformat, void *patdata)
{
    UINT8 *ptr_pat;
    UINT8 *ptr8, r8, g8, b8;
    UINT16 *ptr16, r16, g16, b16, g16_1, g16_2;
    UINT32 *ptr32, r32, g32, b32, g32_1, g32_2;
    int idx;

    ptr_pat = (UINT8 *)patdata;
    if(patformat == RGB888) {
        if (GFX_BPP==8) {
            ptr8 = (UINT8 *)GFX_PAT_ADDR;
            for (idx=0; idx<64; idx++) {
                b8 = (UINT8)(*ptr_pat++) & 0xc0; // 2 bits
                g8 = (UINT8)(*ptr_pat++) & 0xe0; // 3 bits
                r8 = (UINT8)(*ptr_pat++) & 0xe0; // 3 bits
                ptr_pat++;
                *ptr8++ = r8 | (g8>>3) | (b8>>6);
            }
        } else if (GFX_BPP==16) {
            ptr16 = (UINT16 *)GFX_PAT_ADDR;
            for (idx=0; idx<64; idx++) {
                b16 = (UINT16)(*ptr_pat++) & 0x000f8; // 5 bits
                g16 = (UINT16)(*ptr_pat++) & 0x000fc; // 6 bits
                r16 = (UINT16)(*ptr_pat++) & 0x000f8; // 5 bits
                ptr_pat++;
                *ptr16++ = (r16<<8) | (g16<<3) | (b16>>3);
            }
        } else if (GFX_BPP==32) {
            ptr32 = (UINT32 *)GFX_PAT_ADDR;
            for (idx=0; idx<64; idx++) {
                b32 = (UINT32)(*ptr_pat++);
                g32 = (UINT32)(*ptr_pat++);
                r32 = (UINT32)(*ptr_pat++);
                ptr_pat++;
                *ptr32++ = (r32<<16) | (g32<<8) | b32;
            }
        }
    } else if(patformat == RGB565) {
        if (GFX_BPP==8) {
            ptr8 = (UINT8 *)GFX_PAT_ADDR;

            for (idx=0; idx<64; idx++) {
                b8 = (UINT8)(*ptr_pat++) & 0x00018; // 2 bits
                g8 = (UINT8)(*ptr_pat) & 0x00007;  // 3 bits
                r8 = (UINT8)(*ptr_pat++) & 0x000e0;  // 3bits
                *ptr8++ = r8 | (g8<<2) | (b8>>3);
            }
        } else if (GFX_BPP==16) {
            ptr16 = (UINT16 *)GFX_PAT_ADDR;

            for (idx=0; idx<64; idx++) {
                *ptr16++ = (*ptr_pat) | (*(ptr_pat+1)) << 8;
                ptr_pat+=2;
            }
        } else if (GFX_BPP==32) {
            ptr32 = (UINT32 *)GFX_PAT_ADDR;

            for (idx=0; idx<64; idx++) {
                b32 = (UINT8)(*ptr_pat) & 0x1f;      // 5 bits
                g32_1 = (UINT8)(*ptr_pat++) & 0xe0;  // front 3 bits
                g32_2 = (UINT8)(*ptr_pat) & 0x07;    // back 3 bits
                g32 = ((g32_1>>5) | (g32_2<<3))<<2;
                r32 = (UINT8)(*ptr_pat++) & 0xf8;    // 5 bits
                *ptr32++ = 0<<24 | (r32<<16) | (g32<<8) | (b32<<3);
            }
        }
    } else if(patformat == RGB332) {
        if (GFX_BPP==8) {
            ptr8 = (UINT8 *)GFX_PAT_ADDR;

            for (idx=0; idx<64; idx++) {
                *ptr8++ = *ptr_pat;
                ptr_pat++;
            }
        } else if (GFX_BPP==16) {
            ptr16 = (UINT16 *)GFX_PAT_ADDR;

            for (idx=0; idx<64; idx++) {
                r16 = (UINT8)(*ptr_pat) & 0xe0; // 3 bits
                g16_1 = (UINT8)(*ptr_pat) & 0x10;
                g16_2 = (UINT8)(*ptr_pat) & 0x0c;
                g16 = (g16_1>>2) | (g16_2>>2);
                b16 = (UINT8)(*ptr_pat++) & 0x3; // 2 bits
                *ptr16++ = (r16<<8) | (g16<<8) | (b16<<3);
            }
        } else if (GFX_BPP==32) {
            ptr32 = (UINT32 *)GFX_PAT_ADDR;

            for (idx=0; idx<64; idx++) {
                r32 = (UINT8)(*ptr_pat) & 0xe0;  // 3 bits
                g32 = (UINT8)(*ptr_pat) & 0x1c;  // 3 bits
                b32 = (UINT8)(*ptr_pat++) & 0x3;  // 2 bits
                *ptr32++ = 0<<24 | (r32<<15) | (g32<<11) | (b32<<6);
            }
        }
    }

    _PatternType = TYPE_COLOR;
}

/**
  * @brief Display font character.
  * @param[in] x x position
  * @param[in] y y position
  * @param[in] asc_code is ascii code
  * @param[in] fore_color is color of foreground
  * @param[in] back_color is color of background
  * @param[in] draw_mode is transparent is enable or not
  * @param[in] font_id is selection of 8x8 or 8x16 font
  * @return none
  */
void ge2dFont_PutChar(int x, int y, char asc_code, int fore_color, int back_color, int draw_mode, int font_id)
{
    int cmd32, dest_pitch, src_pitch, pitch, dest_start, dest_dimension;
    UINT32 width, height;
    UINT32 fore_color32, back_color32;
    UINT8 *fptr;
    UINT8 *temp_buf[32*32], *ptr8;
    int idx;

    fore_color32 = make_color(fore_color);
    back_color32 = make_color(back_color);

    cmd32 = 0xcc430080;

    if (draw_mode==MODE_TRANSPARENT) {
        cmd32 |= 0x00004000; // mono transparency
    }

    outpw(REG_GE2D_CTL, cmd32);

    outpw(REG_GE2D_FGCOLR, fore_color32);
    outpw(REG_GE2D_BGCOLR, back_color32);

    if (font_id==F8x16) {
        fptr = (UINT8 *)&FontData16[asc_code][0];
        src_pitch = 32;
        width = 32;
        height = 16;

        ptr8 = (UINT8 *)&temp_buf[0];
        for (idx=0; idx<16; idx++) {
            *ptr8++ = *fptr++;
            *ptr8++ = 0;
            *ptr8++ = 0;
            *ptr8++ = 0;
        }
        fptr =  (UINT8 *)&temp_buf[0];
    } else { /* F8x8 */
        fptr = (UINT8 *)&FontData8[asc_code][0];
        src_pitch = 32;
        width = 32;
        height = 8;
        ptr8 = (UINT8 *)&temp_buf[0];
        for (idx=0; idx<8; idx++) {
            *ptr8++ = *fptr++;
            *ptr8++ = 0;
            *ptr8++ = 0;
            *ptr8++ = 0;
        }
        fptr =  (UINT8 *)&temp_buf[0];
    }

    dest_pitch = GFX_WIDTH; // pitch in pixels

    pitch = (dest_pitch << 16) | src_pitch;
    outpw(REG_GE2D_SDPITCH, pitch);

    outpw(REG_GE2D_XYSORG, (int)fptr);
    outpw(REG_GE2D_SRCSPA, 0); // always start from (0,0)

    dest_start = y << 16 | x;
    outpw(REG_GE2D_DSTSPA, dest_start);

    dest_dimension = height << 16 | width;
    outpw(REG_GE2D_RTGLSZ, dest_dimension);

    outpw(REG_GE2D_TRG, 1);
    while ((inpw(REG_GE2D_INTSTS)&0x01)==0); // wait for command complete
    outpw(REG_GE2D_INTSTS, 1); // clear interrupt status
}

/**
  * @brief Display font string.
  * @param[in] x x position
  * @param[in] y y position
  * @param[in] str is pointer of display string
  * @param[in] fore_color is color of foreground
  * @param[in] back_color is color of background
  * @param[in] draw_mode is transparent is enable or not
  * @param[in] font_id is selection of 8x8 or 8x16 font
  * @return none
  */
void ge2dFont_PutString(int x, int y, char *str, int fore_color, int back_color, int draw_mode, int font_id)
{
    char *ptr;
    int idx, sx;

    ptr =	str;
    sx = x;
    for (idx=0; idx<strlen(str); idx++) {
        ge2dFont_PutChar(sx, y, *ptr++, fore_color, back_color, draw_mode, font_id);
        sx += 8;	//char width
    }
}
/*@}*/ /* end of group N9H30_GE2D_EXPORTED_FUNCTIONS */

/*@}*/ /* end of group N9H30_GE2D_Driver */

/*@}*/ /* end of group N9H30_Device_Driver */

/*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/
