diff --git a/options.txt b/options.txt index 1c47300..124cfac 100644 --- a/options.txt +++ b/options.txt @@ -55,6 +55,9 @@ GraphIEC = 1 // If you are using a LCD screen and you would like PageUp and PageDown keys to work with it then specify this option //KeyboardBrowseLCDScreen = 1 +// change startup logo on oled - 1541ii or 1541classic +//LcdLogoName = 1541ii + // If you are using I2C LCD you can optionally change what pins it is connected to. // (defaults to 0 for non-split lines (Option A) or 1 for split lines (Option B)) //i2cBusMaster = 0 //SDA - pin 27 SCL - pin 28 diff --git a/src/FileBrowser.cpp b/src/FileBrowser.cpp index 9d643f5..a9566e0 100644 --- a/src/FileBrowser.cpp +++ b/src/FileBrowser.cpp @@ -35,7 +35,6 @@ extern "C" #define PNG_WIDTH 320 #define PNG_HEIGHT 200 - unsigned char FileBrowser::LSTBuffer[FileBrowser::LSTBuffer_size]; const unsigned FileBrowser::SwapKeys[30] = diff --git a/src/SSD1306.cpp b/src/SSD1306.cpp index 1838e24..6b32147 100644 --- a/src/SSD1306.cpp +++ b/src/SSD1306.cpp @@ -25,48 +25,25 @@ extern "C" #include "xga_font_data.h" } - -#define SSD1306_CMD_SET_MEMORY_ADDRESSING_MODE 0x20 - -#define SSD1306_CMD_SET_COLUMN_ADDRESS 0x21 -#define SSD1306_CMD_SET_PAGE_ADDRESS 0x22 -#define SSD1306_CMD_DEACTIVATE_SCROLL 0x2E -#define SSD1306_CMD_ACTIVATE_SCROLL 0x2F - -#define SSD1306_CMD_SET_CONTRAST_CONTROL 0x81 // Set Contrast Control for BANK0 -#define SSD1306_ENABLE_CHARGE_PUMP 0x8D - -#define SSD1306_CMD_ENTIRE_DISPLAY_ON 0xA4 -#define SSD1306_CMD_ENTIRE_DISPLAY_OFF 0xA5 -#define SSD1306_CMD_NORMAL_DISPLAY 0xA6 // 1 = on pixel -#define SSD1306_CMD_INVERT_DISPLAY 0xA7 // 0 = on pixel - -#define SSD1306_CMD_DISPLAY_OFF 0xAE -#define SSD1306_CMD_DISPLAY_ON 0xAF -#define SSD1306_CMD_MULTIPLEX_RATIO 0xA8 - -#define SSD1306_CMD_SET_START_LINE 0x40 - -#define SSD1306_CMD_SET_DISPLAY_OFFSET 0xD3 -#define SSD1306_CMD_SET_DISPLAY_CLOCK_DIVIDE_RATIO 0xD5 -#define SSD1306_CMD_SET_PRE_CHARGE_PERIOD 0xD9 -#define SSD1306_CMD_SET_COM_PINS 0xDA -#define SSD1306_CMD_SET_VCOMH_DESELECT_LEVEL 0xDB - -#define SSD1306_CONTROL_REG 0x00 -#define SSD1306_DATA_REG 0x40 - unsigned char frame[SSD1306_128x64_BYTES]; SSD1306::SSD1306(int BSCMaster, u8 address, int flip, int type) : BSCMaster(BSCMaster) , address(address) , type(type) + , flip(flip) + , contrast(127) { RPI_I2CInit(BSCMaster, 1); + InitHardware(); +} + +void SSD1306::InitHardware() +{ // SSD1306 data sheet configuration flow SendCommand(SSD1306_CMD_DISPLAY_OFF); // 0xAE + SendCommand(SSD1306_CMD_MULTIPLEX_RATIO); // 0xA8 SendCommand(0x3F); // SSD1306_LCDHEIGHT - 1 @@ -86,16 +63,12 @@ SSD1306::SSD1306(int BSCMaster, u8 address, int flip, int type) SendCommand(SSD1306_CMD_SET_COM_PINS); // 0xDA Layout and direction SendCommand(0x12); - SendCommand(SSD1306_CMD_SET_CONTRAST_CONTROL); - SendCommand(0x7F); + SetContrast(GetContrast()); SendCommand(SSD1306_CMD_ENTIRE_DISPLAY_ON); SendCommand(SSD1306_CMD_NORMAL_DISPLAY); // 0xA6 = non inverted -// SendCommand(0xD5); // CLOCK_DIVIDER_FREQ -// SendCommand(0x80); // 7:4 oscillator f, 3:0 divider - SendCommand(SSD1306_CMD_SET_PRE_CHARGE_PERIOD); // 0xD9 SendCommand(0xF1); @@ -108,27 +81,11 @@ SSD1306::SSD1306(int BSCMaster, u8 address, int flip, int type) SendCommand(SSD1306_ENABLE_CHARGE_PUMP); // Enable charge pump regulator SendCommand(0x14); // external = 0x10 internal = 0x14 -/* only for page mode addressing? so can be deleted - SendCommand(0x00); // Set Lower Column Start Address - SendCommand(0x10); // Set Higher Column Start Address - SendCommand(0xB0); // Set Page Start Address for Page Addressing Mode -*/ - SendCommand(SSD1306_CMD_SET_MEMORY_ADDRESSING_MODE); // Set Memory Addressing Mode SendCommand(0x00); // 00 - Horizontal Addressing Mode Home(); -/* replaced by Home - SendCommand(SSD1306_CMD_SET_COLUMN_ADDRESS); // 0x21 Set Column Address (only for horizontal or vertical mode) - SendCommand(0x00); // start 0 - SendCommand(0x7F); // end 127 - - SendCommand(SSD1306_CMD_SET_PAGE_ADDRESS); // 0x22 - SendCommand(0x00); // start 0 - SendCommand(0x07); // end 7 (so 8 vertical bytes == 64 row display) -*/ - SendCommand(SSD1306_CMD_DEACTIVATE_SCROLL); } @@ -166,14 +123,6 @@ void SSD1306::MoveCursorByte(u8 row, u8 col) SetDisplayWindow(col+2, 129, row, 7); // sh1106 has 132x64 ram, display is centreed else SetDisplayWindow(col+0, 127, row, 7); -/* - SendCommand(0x21); // set column - SendCommand(col); // start = col - SendCommand(0x7F); // end = col max - SendCommand(0x22); // set row - SendCommand(row); // start = row - SendCommand(0x07); // end = row max -*/ } void SSD1306::MoveCursorCharacter(u8 row, u8 col) @@ -228,6 +177,7 @@ void SSD1306::DisplayOff() void SSD1306::SetContrast(u8 value) { + contrast = value; SendCommand(SSD1306_CMD_SET_CONTRAST_CONTROL); SendCommand(value); SetVCOMDeselect( value >> 5); diff --git a/src/SSD1306.h b/src/SSD1306.h index cc0245f..d02d112 100644 --- a/src/SSD1306.h +++ b/src/SSD1306.h @@ -81,9 +81,11 @@ public: void PlotCharacter(int x, int y, char ascii, bool inverse); void Plottext(int x, int y, char* str, bool inverse); + void InitHardware(); void DisplayOn(); void DisplayOff(); void SetContrast(u8 value); + u8 GetContrast() { return contrast; } void SetVCOMDeselect(u8 value); void ClearScreen(); @@ -106,5 +108,31 @@ protected: int BSCMaster; u8 address; int type; + int flip; + int contrast; }; #endif + + +#define SSD1306_CMD_SET_MEMORY_ADDRESSING_MODE 0x20 +#define SSD1306_CMD_SET_COLUMN_ADDRESS 0x21 +#define SSD1306_CMD_SET_PAGE_ADDRESS 0x22 +#define SSD1306_CMD_DEACTIVATE_SCROLL 0x2E +#define SSD1306_CMD_ACTIVATE_SCROLL 0x2F +#define SSD1306_CMD_SET_CONTRAST_CONTROL 0x81 // Set Contrast Control for BANK0 +#define SSD1306_ENABLE_CHARGE_PUMP 0x8D +#define SSD1306_CMD_ENTIRE_DISPLAY_ON 0xA4 +#define SSD1306_CMD_ENTIRE_DISPLAY_OFF 0xA5 +#define SSD1306_CMD_NORMAL_DISPLAY 0xA6 // 1 = on pixel +#define SSD1306_CMD_INVERT_DISPLAY 0xA7 // 0 = on pixel +#define SSD1306_CMD_DISPLAY_OFF 0xAE +#define SSD1306_CMD_DISPLAY_ON 0xAF +#define SSD1306_CMD_MULTIPLEX_RATIO 0xA8 +#define SSD1306_CMD_SET_START_LINE 0x40 +#define SSD1306_CMD_SET_DISPLAY_OFFSET 0xD3 +#define SSD1306_CMD_SET_DISPLAY_CLOCK_DIVIDE_RATIO 0xD5 +#define SSD1306_CMD_SET_PRE_CHARGE_PERIOD 0xD9 +#define SSD1306_CMD_SET_COM_PINS 0xDA +#define SSD1306_CMD_SET_VCOMH_DESELECT_LEVEL 0xDB +#define SSD1306_CONTROL_REG 0x00 +#define SSD1306_DATA_REG 0x40 diff --git a/src/Screen.cpp b/src/Screen.cpp index b1c6314..00f07e6 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -337,3 +337,4 @@ void Screen::PlotImage(u32* image, int x, int y, int w, int h) } } } + diff --git a/src/Screen.h b/src/Screen.h index f5ceee7..78be877 100644 --- a/src/Screen.h +++ b/src/Screen.h @@ -71,4 +71,4 @@ private: float scaleY; }; -#endif \ No newline at end of file +#endif diff --git a/src/ScreenBase.h b/src/ScreenBase.h index a6c7a60..b62d57a 100644 --- a/src/ScreenBase.h +++ b/src/ScreenBase.h @@ -94,4 +94,4 @@ protected: u8* framebuffer; }; -#endif \ No newline at end of file +#endif diff --git a/src/ScreenLCD.cpp b/src/ScreenLCD.cpp index 859005e..3eae5ed 100644 --- a/src/ScreenLCD.cpp +++ b/src/ScreenLCD.cpp @@ -42,9 +42,6 @@ void ScreenLCD::Open(u32 widthDesired, u32 heightDesired, u32 colourDepth, int B ssd1306 = new SSD1306(BSCMaster, LCDAddress, LCDFlip, LCDType); ssd1306->DisplayOn(); - ssd1306->PlotImage(logo_ssd); - ssd1306->Plottext(5, 0, "Pi1541", false); - ssd1306->RefreshScreen(); opened = true; @@ -64,6 +61,14 @@ void ScreenLCD::Clear(RGBA colour) ssd1306->ClearScreen(); } +void ScreenLCD::ClearInit(RGBA colour) +{ + ssd1306->InitHardware(); + ssd1306->ClearScreen(); + ssd1306->SetContrast(ssd1306->GetContrast()); + ssd1306->DisplayOn(); +} + void ScreenLCD::SetContrast(u8 value) { ssd1306->SetContrast(value); @@ -84,6 +89,14 @@ void ScreenLCD::PlotImage(u32* image, int x, int y, int w, int h) { } +void ScreenLCD::PlotRawImage(const u8* image, int x, int y, int w, int h) +{ + if (x==0 && y==0 && w==128 && h==64) + { + ssd1306->PlotImage(image); + } +} + u32 ScreenLCD::PrintText(bool petscii, u32 x, u32 y, char *ptr, RGBA TxtColour, RGBA BkColour, bool measureOnly, u32* width, u32* height) { int len = 0; @@ -101,6 +114,11 @@ u32 ScreenLCD::GetFontHeight() return 16; } +void ScreenLCD::RefreshScreen() +{ + ssd1306->RefreshScreen(); +} + void ScreenLCD::SwapBuffers() { ssd1306->RefreshScreen(); diff --git a/src/ScreenLCD.h b/src/ScreenLCD.h index d3c1dd6..4e8f3bd 100644 --- a/src/ScreenLCD.h +++ b/src/ScreenLCD.h @@ -36,6 +36,7 @@ public: void ClearArea(u32 x1, u32 y1, u32 x2, u32 y2, RGBA colour); void Clear(RGBA colour); + void ClearInit(RGBA colour); void SetContrast(u8 value); @@ -49,9 +50,12 @@ public: void PlotImage(u32* image, int x, int y, int w, int h); + void PlotRawImage(const u8* image, int x, int y, int w, int h); + u32 GetFontHeight(); void SwapBuffers(); + void RefreshScreen(); void RefreshRows(u8 start, u8 amountOfRows); diff --git a/src/iec_commands.cpp b/src/iec_commands.cpp index 681e4b2..1bc71d3 100644 --- a/src/iec_commands.cpp +++ b/src/iec_commands.cpp @@ -47,6 +47,10 @@ extern unsigned versionMajor; extern unsigned versionMinor; +extern "C" { + extern void reboot_now(void); +} + #define WaitWhile(checkStatus) \ do\ {\ @@ -1278,10 +1282,13 @@ void IEC_Commands::User(void) case 'J': case ':': - case 202: // Hard reset Error(ERROR_73_DOSVERSION); break; + case 202: + // Really hard reset - reboot Pi + reboot_now(); + break; case '0': //OPEN1,8,15,"U0>"+CHR$(9):CLOSE1 if ((channel.buffer[2] & 0x1f) == 0x1e && channel.buffer[3] >= 4 && channel.buffer[3] <= 30) diff --git a/src/main.cpp b/src/main.cpp index d8cc764..107e629 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -43,6 +43,7 @@ extern "C" #include "logo.h" #include "sample.h" +#include "ssd_logo.h" unsigned versionMajor = 1; unsigned versionMinor = 7; @@ -80,6 +81,9 @@ const long int CBMFont_size = 4096; unsigned char CBMFontData[4096]; unsigned char* CBMFont = 0; +#define LCD_LOGO_MAX_SIZE 1024 +u8 LcdLogoFile[LCD_LOGO_MAX_SIZE]; + u8 s_u8Memory[0xc000]; DiskCaddy diskCaddy; @@ -345,26 +349,60 @@ void InitialiseHardware() void InitialiseLCD() { + + FILINFO filLcdIcon; + int i2cBusMaster = options.I2CBusMaster(); int i2cLcdAddress = options.I2CLcdAddress(); int i2cLcdFlip = options.I2CLcdFlip(); int i2cLcdOnContrast = options.I2CLcdOnContrast(); int i2cLcdDimContrast = options.I2CLcdDimContrast(); int i2cLcdDimTime = options.I2CLcdDimTime(); - if (strcasecmp(options.GetLCDName(), "ssd1306_128x64") == 0) + int i2cLcdModel = options.I2CLcdModel(); + + if (i2cLcdModel) { screenLCD = new ScreenLCD(); - screenLCD->Open(128, 64, 1, i2cBusMaster, i2cLcdAddress, i2cLcdFlip, 1306); + screenLCD->Open(128, 64, 1, i2cBusMaster, i2cLcdAddress, i2cLcdFlip, i2cLcdModel); screenLCD->SetContrast(i2cLcdOnContrast); - } - else if (strcasecmp(options.GetLCDName(), "sh1106_128x64") == 0) - { - screenLCD = new ScreenLCD(); - screenLCD->Open(128, 64, 1, i2cBusMaster, i2cLcdAddress, i2cLcdFlip, 1106); - screenLCD->SetContrast(i2cLcdOnContrast); - } - else - { + + bool logo_done = false; + if (strcasecmp(options.GetLcdLogoName(), "1541ii") == 0) + { + screenLCD->PlotRawImage(logo_ssd_1541ii, 0, 0, 128, 64); + snprintf(tempBuffer, tempBufferSize, "Pi1541 V%d.%02d", versionMajor, versionMinor); + screenLCD->PrintText(0, 16, 0, tempBuffer, 0xffffffff); + logo_done = true; + } + else if (strcasecmp(options.GetLcdLogoName(), "1541classic") == 0) + { + screenLCD->PlotRawImage(logo_ssd_1541classic, 0, 0, 128, 64); + logo_done = true; + } + else if (f_stat(options.GetLcdLogoName(), &filLcdIcon) == FR_OK && filLcdIcon.fsize <= LCD_LOGO_MAX_SIZE) + { + FIL fp; + FRESULT res; + + res = f_open(&fp, filLcdIcon.fname, FA_READ); + if (res == FR_OK) + { + u32 bytesRead; + f_read(&fp, LcdLogoFile, LCD_LOGO_MAX_SIZE, &bytesRead); + f_close(&fp); + screenLCD->PlotRawImage(LcdLogoFile, 0, 0, 128, 64); + logo_done = true; + } + } + + if (!logo_done) + { + snprintf(tempBuffer, tempBufferSize, "Pixxxx V%d.%02d", versionMajor, versionMinor); + int x = (128 - 8*strlen(tempBuffer) ) /2; + int y = (64-16)/2; + screenLCD->PrintText(0, x, y, tempBuffer, 0x0); + } + screenLCD->RefreshScreen(); } } @@ -1060,6 +1098,8 @@ void DisplayOptions(int y_pos) screen.PrintText(false, 0, y_pos += 16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); snprintf(tempBuffer, tempBufferSize, "LCDName = %s\r\n", options.GetLCDName()); screen.PrintText(false, 0, y_pos += 16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); + snprintf(tempBuffer, tempBufferSize, "LcdLogoName = %s\r\n", options.GetLcdLogoName()); + screen.PrintText(false, 0, y_pos += 16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); } static void CheckOptions() @@ -1242,6 +1282,8 @@ extern "C" IEC_Bus::Initialise(); + screenLCD->ClearInit(0); + #ifdef HAS_MULTICORE start_core(3, _spin_core); start_core(2, _spin_core); diff --git a/src/options.cpp b/src/options.cpp index f7d6a2a..78afb3c 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -143,10 +143,13 @@ Options::Options(void) , i2cBusMaster(1) , i2cLcdAddress(0x3C) , i2cLcdFlip(0) + , i2cLcdOnContrast(127) + , i2cLcdModel(0) , keyboardBrowseLCDScreen(0) { autoMountImageName[0] = 0; strcpy(ROMFontName, "chargen"); + strcpy(LcdLogoName, "1541ii"); starFileName[0] = 0; ROMName[0] = 0; ROMNameSlot2[0] = 0; @@ -221,9 +224,18 @@ void Options::Process(char* buffer) { strncpy(starFileName, pValue, 255); } + else if ((strcasecmp(pOption, "LCDLogoName") == 0)) + { + strncpy(LcdLogoName, pValue, 255); + } else if ((strcasecmp(pOption, "LCDName") == 0)) { strncpy(LCDName, pValue, 255); + if (strcasecmp(pValue, "ssd1306_128x64") == 0) + i2cLcdModel = 1306; + else if (strcasecmp(pValue, "sh1106_128x64") == 0) + i2cLcdModel = 1106; + } else if ((strcasecmp(pOption, "ROM") == 0) || (strcasecmp(pOption, "ROM1") == 0)) { diff --git a/src/options.h b/src/options.h index 1d1481e..1df50b9 100644 --- a/src/options.h +++ b/src/options.h @@ -76,6 +76,8 @@ public: inline unsigned int I2CLcdOnContrast() const { return i2cLcdOnContrast; } inline unsigned int I2CLcdDimContrast() const { return i2cLcdDimContrast; } inline unsigned int I2CLcdDimTime() const { return i2cLcdDimTime; } + inline unsigned int I2CLcdModel() const { return i2cLcdModel; } + inline const char* GetLcdLogoName() const { return LcdLogoName; } // Page up and down will jump a different amount based on the maximum number rows displayed. // Perhaps we should use some keyboard modifier to the the other screen? @@ -111,14 +113,16 @@ private: unsigned int i2cBusMaster; unsigned int i2cLcdAddress; unsigned int i2cLcdFlip; - unsigned int i2cLcdOnContrast = 127; + unsigned int i2cLcdOnContrast; unsigned int i2cLcdDimContrast; unsigned int i2cLcdDimTime; + unsigned int i2cLcdModel; unsigned int keyboardBrowseLCDScreen; char starFileName[256]; char LCDName[256]; + char LcdLogoName[256]; char autoMountImageName[256]; char ROMFontName[256]; diff --git a/src/ssd_logo.h b/src/ssd_logo.h index 0305bcd..3544933 100644 --- a/src/ssd_logo.h +++ b/src/ssd_logo.h @@ -1,4 +1,4 @@ -const unsigned char logo_ssd[] = { +const unsigned char logo_ssd_1541ii[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -65,3 +65,70 @@ const unsigned char logo_ssd[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; +const unsigned char logo_ssd_1541classic[] = { + 0x00, 0x00, 0xC0, 0xE0, 0xE0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xE0, 0xE0, 0x80, 0x00, 0x00, + 0xF8, 0xFF, 0xFF, 0x03, 0xE0, 0x30, 0x18, 0x08, 0x08, 0x88, 0xC8, 0x48, 0x48, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0xC8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, + 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x88, 0x88, 0x88, 0x08, 0x08, 0x88, 0x08, 0x08, 0x08, + 0x88, 0x08, 0x08, 0x88, 0x88, 0x88, 0x08, 0x08, 0x08, 0x88, 0x08, 0x08, 0x08, 0x88, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x18, 0x30, 0xE1, 0x07, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0x1F, 0x00, 0x3F, 0x60, 0xC0, 0x80, 0x87, 0x8F, 0x98, 0x90, 0x95, 0x85, 0x85, 0x80, + 0x86, 0x89, 0x80, 0x86, 0x89, 0x86, 0x8E, 0x81, 0x8F, 0x81, 0x8F, 0x8E, 0x81, 0x8F, 0x81, 0x8F, + 0x86, 0x89, 0x86, 0x89, 0x8F, 0x86, 0x89, 0x86, 0x8F, 0x83, 0x86, 0x8F, 0x86, 0x80, 0x80, 0x80, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x8F, 0x82, 0x82, 0x81, 0x80, 0x8E, 0x80, 0x80, 0x89, + 0x8F, 0x88, 0x80, 0x8B, 0x8A, 0x84, 0x80, 0x86, 0x85, 0x8F, 0x84, 0x80, 0x89, 0x8F, 0x88, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xC0, 0x60, 0x3F, 0x00, 0x1F, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0xFF, 0xFF, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xFF, + 0x02, 0x02, 0x02, 0x7A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, + 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, + 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, + 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4A, + 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, + 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x7A, 0x02, 0x02, 0x02, 0xFF, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0xFF, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xC1, 0xE1, 0xF1, + 0xF1, 0xE1, 0xC1, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0x1F, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x7F, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x43, + 0x43, 0x41, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x47, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x47, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x0F, + 0x00, 0x03, 0x03, 0x03, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x03, 0x03, 0x03, 0x00, + +};