Compare commits

..

No commits in common. "4bb5986ce77cbb364fb761e33a9692e726161088" and "bae9bbc741caf01d57744e026bcb29b7bcd4fe87" have entirely different histories.

9 changed files with 2438 additions and 563 deletions

View file

@ -57,19 +57,8 @@ void scanBTdevice() {//scan bluetooth device
Terminal(txt,0,48,320,191);//list devices
delay(100) ;
String dName = deviceName[i];
dName.toUpperCase();
String dAddr = deviceAddr[i];
dAddr.toLowerCase();
bool isMatch = (dName == "OBDII") ||
(dName.indexOf("OBD") != -1) ||
(dName.indexOf("ELM") != -1) ||
(dName == "DEBIAN") ||
(dAddr == "e8:48:b8:c8:20:00");
if (isMatch) {//match name.
//found device name "OBDII" or emulator
if (deviceName[i] == client_name || deviceName[i] == "debian" || deviceName[i].indexOf("OBD") != -1 || deviceAddr[i] == "e8:48:b8:c8:20:00") {//match name.
//found device name "OBDII"
foundOBD2 = true;
//00:1d:a5:00:12:92 -> {0x00,0x1d,0xa5,0x00,0x12,0x92};
//copy match bt mac address to client_name to connect
@ -91,10 +80,8 @@ void scanBTdevice() {//scan bluetooth device
pref.putBytes("recent_client",client_addr,sizeof(client_addr));//save new bt addr to pref.
Serial.println(F("Save a new BT client address"));
}
break; // Stop scanning once a matching device is found!
} else {
} else //not match
foundOBD2 = false;
}
}//for loop list device

View file

@ -1,162 +1,328 @@
/* "config.h"
Configuration menu for OBD2 Gauge
this header file is for configuration menu
*/
#include <FS.h>
#include <SD.h>
#include <SPIFFS.h>
//freeRTOS multi tasking
#include <esp_task_wdt.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#define mypic_filename "/mypic.jpg"
#define FORMAT_SPIFFS_IF_FAILED true
#include "music.h" //songs data
#include "nes_audio.h" //nes audio player
#include "firmware_update.h" //firmware updater function
#include "elm327.h"// read VIN function
/*------------ SOUND EFFECTS ----------*/
void beepbeep() {
ledcWriteTone(buzzerChannel, 2000);
delay(50);
ledcWriteTone(buzzerChannel, 0);
delay(50);
ledcWriteTone(buzzerChannel, 2000);
delay(50);
ledcWriteTone(buzzerChannel, 0);
#define mypic_filename "/mypic.jpg"//mypic file
#define FORMAT_SPIFFS_IF_FAILED true//format if no spiffs
Cartridge player(BUZZER_PIN);//not specified 4 pin , use 1 pin at buzzer pin
//configuration menu
const String menuList[8] = {
"Show pid/s & CPU Temp",//toggle show system
"Load my pic 320x240 px",//load user own pic
"Update firmware",//update new firmware
"Warning setting",//setting warning parameter (warning data, offset temp)
"DTCs",//dtc engine
"Auto-off",//auto turn off
"About",//about
"Exit"
};
const uint8_t maxMenu = array_length(menuList);//length of menu list
//menu list for warning setting (CPU offset + 4 PIDs)
const String parameterList[5][2] = {
{"CPU Temp ("+String(tempOverheat)+"`c), offset"," `c "},
{"- Temperatura (ECT)"," `c "},
{"- RPM"," rpm "},
{"- Voltaje Bateria / PCM"," V "},
{"- Velocidad (SPEED)"," km/h"}
};
//increasement and decreasement of each PID
const int pidWarnStep[5] = {1, 1, 100, 1, 5};
//Sprites
TFT_eSprite car = TFT_eSprite(&tft);
TFT_eSprite bk = TFT_eSprite(&tft);
TFT_eSprite pole = TFT_eSprite(&tft);
TFT_eSprite fence = TFT_eSprite(&tft);
//------ NES Audio play on Task0
TaskHandle_t TaskHandle0 = NULL;//create taskhandle0
void TaskPlayMusic(void *pvParameters) {
esp_task_wdt_init(62, false);//62 sec wd timer / disable wd
while(1) {
// player.frame_counter_cb(danceLight);//cal back fucntion (not use)
player.play_nes(song , true, 0.25); //play nes music, loop, volume 0.25, <lower vol lower distortion>
}
}
//----------------------------
void animation() {//start field effect
//sprite variable
#define BK_HEIGHT 80
#define BK_WIDTH 235
uint8_t cur_x = 68;
uint8_t cur_y = 10;
uint8_t dash_x = 20;
int16_t tag_x = 235;
int16_t fence_x = 0;
uint8_t ani_speed = 2;
void beep() {
ledcWriteTone(buzzerChannel, 2000);
delay(500);
ledcWriteTone(buzzerChannel, 0);
}
//create spirtes
bk.createSprite(BK_WIDTH,BK_HEIGHT);
void clickSound() {
ledcWriteTone(buzzerChannel, 5000);
delay(5);
ledcWriteTone(buzzerChannel, 0);
}
car.createSprite(CAR_WIDTH,CAR_HEIGHT);//image size 114x50
car.setSwapBytes(true);
car.pushImage(0,0,CAR_WIDTH,CAR_HEIGHT,futurecar);//image size 114x50
// Configuration menu list
const String menuList[3] = {
"Warning setting", // 0
"Load my pic 320x240 px", // 1
"Exit" // 2
};
const uint8_t maxMenu = 3;
pole.createSprite(POLE_WIDTH,POLE_HEIGHT);
pole.setSwapBytes(true);
pole.pushImage(0,0,POLE_WIDTH,POLE_HEIGHT,pole1);
// Menu list for warning setting (4 vehicle gauges)
const String parameterList[4][2] = {
{"- Temperatura (ECT)", " `c "},
{"- RPM", " rpm "},
{"- Voltaje Bateria", " V "},
{"- Velocidad (SPEED)", " km/h"}
};
fence.createSprite(FENCE_WIDTH,FENCE_HEIGHT);
fence.setSwapBytes(true);
fence.pushImage(0,0,FENCE_WIDTH,FENCE_HEIGHT,fence1);
//-------------------------------
tft.fillScreen(TFT_BLACK);//clear screen
//draw QRCode
tft.drawBitmap(0, 159, qrcode, QRCODE_WIDTH, QRCODE_HEIGHT, TFT_WHITE);
//draw text
tft.setTextColor(TFT_WHITE);
tft.drawString(">MAP/ENG LOAD/ECT/EOT/TFT/ENG SPD/PCM Volt",0,40,2);
tft.drawString(">Warning, Automatic Dim/OnOff/O็verheat Shutdown",0,60,2);
tft.drawString(">Read DTC Code & Clear MIL Status",0,80,2);
tft.drawString("* FW-\"VaandCobOBD2Gauge.bin\" * Image-\"mypic.jpg\"",0,100,2);
tft.drawString("* Facebook : www.facebook.com/vaandcob",0,120,2);
tft.setTextColor(TFT_YELLOW);
tft.drawString(" [ Manual ] ----------------[ Press button to exit ]",0,140,2);
tft.setTextColor(TFT_CYAN);
String txt = "[ "+serial_no+" ] BUILD : "+compile_date;
tft.drawString(txt,0,0,2);
//get VIN
getPID("ATE0");//force echo off
txt = "VIN : " + getVIN(getPID("0902"));
tft.setTextColor(TFT_GREENYELLOW);
tft.drawString(txt,0,20,2);
// Increments/decrements for each PID warning setting
const int pidWarnStep[4] = {1, 100, 1, 5};
bk.setTextColor(TFT_BLACK,TFT_ORANGE);
//loop draw Animation
while (digitalRead(SELECTOR_PIN) == HIGH && !isScreenPressed()) {//exit if press button or touch
// Highlight and change warning for each gauge
//draw road
bk.fillSprite(0x4228);//draw road
bk.fillRect(0,0,235,16,TFT_LIGHTGREY);
bk.fillRect(0,16,235,3,0x8430);
//draw dash line
for(int16_t i = 0; i < 5; i++) {
//speed //space //posY //length
// bk.drawFastHLine(dash_x +(40 * i), 20,10,TFT_WHITE);//far end dash line
bk.drawFastHLine((dash_x-20)*1.5+(60 * i),45,15,TFT_WHITE);//middle dash line
// bk.drawFastHLine((dash_x-40)*2.0+(80 * i),79,20,TFT_WHITE);//nearest dash line
}
dash_x = dash_x - ani_speed;
if (dash_x <= 0 ) dash_x = 40;
//draw traffic
tag_x = tag_x - ani_speed;
if (tag_x <= -80) tag_x = 235;
//bk.setTextColor(random(0xffff));
bk.drawString("< Thank You >",tag_x,0,2);//draw billboard
//draw car
int8_t move = random(-1,2);
cur_x = cur_x + move;
move = random(-1,2);
cur_y = cur_y + move;
if (cur_x > 235-CAR_WIDTH) cur_x = 235-CAR_WIDTH;
if (cur_x < 1) cur_x = 1;
if (cur_y < 1) cur_y = 1;
if (cur_y > 79-CAR_HEIGHT) cur_y = 79-CAR_HEIGHT;
car.pushToSprite(&bk,cur_x,cur_y,TFT_BLACK);//put car into bk, white color as transparent
//draw fence
for(int i=0;i<8;i++)//7 sprites
fence.pushToSprite(&bk,fence_x*2+(FENCE_WIDTH*i),80-FENCE_HEIGHT,TFT_BLACK);
fence_x = fence_x - ani_speed;
if (fence_x <= -FENCE_WIDTH + ani_speed) fence_x = 0;//loop back
//draw pole
pole.pushToSprite(&bk,tag_x*2,80-POLE_HEIGHT,TFT_BLACK);//draw bush
//show background sprite
bk.pushSprite(85,159);
//led blinking effect
digitalWrite(LED_RED_PIN, random(0,2));
digitalWrite(LED_GREEN_PIN, random(0,2));
digitalWrite(LED_BLUE_PIN, random(0,2));
checkCPUTemp();
autoDim();
}
//remove sprites
car.deleteSprite();
bk.deleteSprite();
pole.deleteSprite();
fence.deleteSprite();
}//task star field
/*------------------*/
//highlight and change warning each menu
void setWarning(int8_t index, int8_t change) {
for (uint8_t i = 0; i < 4; i++) {
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.drawString(parameterList[i][0], 10, 60 + (i * 30), 4);
tft.drawRightString(parameterList[i][1], 310, 60 + (i * 30), 4);
String result = warningValue[i];
tft.drawRightString(result.c_str(), 230, 60 + (i * 30), 4);
for (uint8_t i = 0;i<maxpidIndex+1;i++) {//draw all pid list
tft.setTextColor(TFT_WHITE,TFT_BLACK);
tft.drawString(parameterList[i][0],0,58+(i*16),2);//paramter list
tft.drawRightString(parameterList[i][1],319,57+(i*16),2);//unit
String result = "";
if (i == 0) result = String(tempOffset);
else result = warningValue[i-1];
switch (result.length()) {//remove indent
case 1: result = " " + result; break;
case 2: result = " " + result; break;
case 3: result = " " + result; break;
}//switch
tft.drawRightString(result,285,57+(i*16),2);
}
if (index >= 0 && index < 4) {
int min = pidConfig[index][4].toInt();
int max = pidConfig[index][5].toInt();
int val = warningValue[index].toInt();
if (change == -1) {
val -= pidWarnStep[index];
if (val < min) val = min;
} else if (change == 1) {
val += pidWarnStep[index];
if (val > max) val = max;
tft.setTextColor(TFT_BLACK,TFT_YELLOW);//highlight yellow
//update number on screen
if (index == 0) {//cpu overheat
int min = -99;//min temp offset
int max = 0;//max temp offset
if (change == -1) {//decrease
tempOffset = tempOffset - pidWarnStep[index];
if (tempOffset < min) tempOffset = min;
}
warningValue[index] = String(val);
if (change == 1) {//incrase
tempOffset = tempOffset + pidWarnStep[index];
if (tempOffset > max) tempOffset = max;
}
String result = String(tempOffset);
switch (result.length()) {
case 1: result = " " + result; break;
case 2: result = " " + result; break;
case 3: result = " " + result; break;
}//switch
tft.drawRightString(result,285,57+(index*16),2);//cpu offset
} else {//other pid
tft.setTextColor(TFT_BLACK, TFT_YELLOW); // highlight selected item
tft.drawString(parameterList[index][0], 10, 60 + (index * 30), 4);
tft.drawRightString(parameterList[index][1], 310, 60 + (index * 30), 4);
tft.drawRightString(warningValue[index].c_str(), 230, 60 + (index * 30), 4);
int min = pidConfig[index-1][4].toInt();//get min
int max = pidConfig[index-1][5].toInt();//get max
if (change == -1) {//decrease
warningValue[index-1] = String(warningValue[index-1].toInt() - pidWarnStep[index]);
if (warningValue[index-1].toInt() < min) warningValue[index-1] = String(min);
}
delay(150);
if (change == 1) {//increase
warningValue[index-1] = String(warningValue[index-1].toInt() + pidWarnStep[index]);
if (warningValue[index-1].toInt() > max) warningValue[index-1] = String(max);
}
String result = warningValue[index-1];
switch (result.length()) {
case 1: result = " " + result; break;
case 2: result = " " + result; break;
case 3: result = " " + result; break;
}//switch
tft.drawRightString(result,285,57+(index*16),2);//pid warning value
} //if i = 0
delay(300);//touch screen delay
}
/*--------------------*/
void loadMyPic() {
if (!SD.begin()) {
tft.pushImage(129, 44, 60, 60, sdcard);
if(!SD.begin()) {//sdcard not attach
tft.pushImage(129,44,60,60,sdcard);//show sdcard icon
Serial.println(F("Micro SD Card not mounted!"));
tft.setTextColor(TFT_WHITE, TFT_RED);
tft.drawCentreString("Please insert Micro SD Card", 159, 120, 4);
} else {
tft.setTextColor(TFT_WHITE,TFT_RED);
tft.drawCentreString("Please insert Micro SD Card",159,120,4);
} else {//sd card attached
Serial.println(F("Micro SD Card..OK"));
uint8_t cardType = SD.cardType();
if (cardType == CARD_NONE) {
if (cardType == CARD_NONE) {//bad card
Serial.println(F("Micro SD Card Error!"));
tft.setTextColor(TFT_WHITE, TFT_RED);
tft.drawCentreString("Micro SD Card Error!", 159, 120, 4);
} else {
tft.setTextColor(TFT_WHITE,TFT_RED);
tft.drawCentreString("Micro SD Card Error!",159,120,4);
} else {//good sd card attached
if (!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)) {
Serial.println(F("Error: SPIFFS failed!"));
tft.setTextColor(TFT_WHITE, TFT_RED);
tft.drawCentreString("Error: SPIFFS failed!", 159, 120, 4);
tft.setTextColor(TFT_WHITE,TFT_RED);
tft.drawCentreString("Error: SPIFFS failed!",159,120,4);
} else {
tft.setTextColor(TFT_BLACK,TFT_GREEN);
tft.drawCentreString("Copying...\"mypic.jpg\"",159,120,4);
Serial.println(F("Deleting...\"mypic.jpg\""));
SPIFFS.remove(mypic_filename);//remove old file first
File sourceFile = SD.open(mypic_filename);
if (sourceFile) {
if (sourceFile) {//found file
File destFile = SPIFFS.open(mypic_filename, FILE_WRITE);
Serial.println(F("Copying...\"mypic.jpg\""));
tft.setTextColor(TFT_BLACK, TFT_GREEN);
tft.setTextColor(TFT_BLACK,TFT_GREEN);
static uint8_t buf[512];
while (sourceFile.read(buf, 512)) {
destFile.write(buf, 512);
while(sourceFile.read( buf, 512) ) {
destFile.write( buf, 512 );//copy file from sdcard to spiffs
}
sourceFile.close();
destFile.close();
//load mypic.jpg from spiffs to show on screen
show_spiffs_jpeg_image(mypic_filename, 0, 0);
} else {
Serial.println(F("\"mypic.jpg\" not found!"));
tft.pushImage(130, 44, 60, 60, nofile);
tft.setTextColor(TFT_WHITE, TFT_RED);
tft.drawCentreString("\"mypic.jpg\" not found!", 159, 120, 4);
}
}
}
}
tft.pushImage(130,44,60,60,nofile);//show fileicon
tft.setTextColor(TFT_WHITE,TFT_RED);
tft.drawCentreString("\"mypic.jpg\" not found!",159,120,4);
}//if sourcefile
}//if SPIFFS.begin
}//else sccard errror
}//else sdcard attach
SD.end();
SPIFFS.end();
beep();
}
}//loadmypic
/*----------------*/
void listMenu(uint8_t choice) {
tft.fillRect(0, 30, 320, 180, TFT_BLACK);
tft.pushImage(15, 45, 25, 25, warning); // Warning setting icon
tft.pushImage(15, 95, 25, 25, image); // Load my pic icon
tft.pushImage(15, 145, 25, 25, quit); // Exit icon
//draw icon
if (showsystem) tft.pushImage(0,35,25,25,switchon);//switchon image
else tft.pushImage(0,35,25,25,switchoff);//switchon image
tft.pushImage(0,65,25,25,image);//image
tft.pushImage(0,95,25,25,cpu);//firmware
tft.pushImage(0,125,25,25,warning);//parameter
tft.pushImage(0,155,25,25,engine);//engine
tft.pushImage(159,155,25,25,autooff);//off
tft.pushImage(0,185,25,25,about);//about
tft.pushImage(159,185,25,25,quit);//exit
for (uint8_t i=0;i<maxMenu;i++) {
if (choice == i) tft.setTextColor(TFT_WHITE,TFT_BLUE);//highlight
else tft.setTextColor(TFT_WHITE,TFT_BLACK);
if (i<4) tft.drawString(menuList[i],32,35 + 30 * i,4);//write menu list
else if (i <6 ) tft.drawString(menuList[i],32+(i-4)*159,35 + 30 *4,4);//write menu list
else tft.drawString(menuList[i],32+(i-6)*159,35 + 30 *5,4);//write menu list
for (uint8_t i = 0; i < maxMenu; i++) {
if (choice == i) {
tft.setTextColor(TFT_WHITE, TFT_BLUE);
} else {
tft.setTextColor(TFT_WHITE, TFT_BLACK);
}
tft.drawString(menuList[i], 50, 45 + 50 * i, 4);
}
tft.setTextColor(TFT_YELLOW, TFT_BLACK);
tft.drawCentreString("Tap option to select or use Button", 160, 215, 2);
}//for i
tft.setTextColor(TFT_YELLOW,TFT_BLACK);
tft.drawString("Tap any option directly to select",10,215,2);
tft.drawString("Or use button: Click=Next, Hold=Select",10,228,2);
}
void configMenu() {
/*----------------*/
void configMenu() {//control configuration menu
uint8_t select = 0;
bool pressed = false;
long holdtimer = 0;
bool currentFlag = showsystem;//keep current flag status
beep();
tft.fillScreen(TFT_BLACK);
tft.fillScreen(TFT_BLACK);//clear screen
tft.fillRectVGradient(0, 0, 320, 26, TFT_ORANGE, 0xfc00);
tft.setTextColor(TFT_BLACK);
tft.drawCentreString("[--- Configuration Menu ---]", 159, 0, 4);
tft.drawCentreString("[--- Configuration Menu ---]",159,0,4);
listMenu(select);
delay(400);
while (true) {
delay(500);
while (true) {//loop check touch or button press
checkCPUTemp();
autoDim();
int8_t executeSelect = -1;
@ -164,9 +330,12 @@ void configMenu() {
if (getTouch(&tx, &ty)) {
int8_t touchedOpt = -1;
if (ty >= 35 && ty < 85) touchedOpt = 0;
else if (ty >= 85 && ty < 135) touchedOpt = 1;
else if (ty >= 135 && ty < 195) touchedOpt = 2;
if (ty >= 30 && ty < 60) touchedOpt = 0;
else if (ty >= 60 && ty < 90) touchedOpt = 1;
else if (ty >= 90 && ty < 120) touchedOpt = 2;
else if (ty >= 120 && ty < 150) touchedOpt = 3;
else if (ty >= 150 && ty < 180) touchedOpt = (tx < 160) ? 4 : 5;
else if (ty >= 180 && ty < 215) touchedOpt = (tx < 160) ? 6 : 7;
if (touchedOpt >= 0) {
select = touchedOpt;
@ -176,22 +345,22 @@ void configMenu() {
delay(10);
yield();
}
delay(100);
delay(120);
executeSelect = select;
}
} else if (digitalRead(SELECTOR_PIN) == LOW) {
if (!pressed) {
pressed = true;
holdtimer = millis();
} else if (millis() - holdtimer > 1200) {
} else if (millis() - holdtimer > 1500) {
executeSelect = select;
pressed = false;
}
} else {
if (pressed) {
if (millis() - holdtimer >= 40 && millis() - holdtimer <= 1200) {
if (millis() - holdtimer >= 40 && millis() - holdtimer <= 1500) {
select++;
if (select >= maxMenu) select = 0;
if (select == maxMenu) select = 0;
listMenu(select);
clickSound();
}
@ -202,38 +371,120 @@ void configMenu() {
if (executeSelect >= 0) {
select = executeSelect;
// Option 0: Warning setting
//---------- TOGGLE SHOW SYSTEM STATUS -----------
if (select == 0) {
clickSound();
tft.fillRect(0, 30, 320, 210, TFT_BLACK);
int8_t warningMenuIndex = 0;
int8_t inc_dec = 0;
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.drawCentreString("Warning Setting", 159, 32, 4);
beepbeep();
showsystem = !showsystem;//toggle
tft.setTextColor(TFT_WHITE,TFT_BLUE);
if (showsystem) tft.pushImage(0,35,25,25,switchon);//switchon image
else tft.pushImage(0,35,25,25,switchoff);//switchon image
for (uint8_t i = 0; i < 5; i++) {
tft.fillRoundRect(i * 64, 211, 60, 30, 5, TFT_NAVY);
}
tft.setTextColor(TFT_WHITE);
tft.drawCentreString("DEFAULT", 31, 217, 2);
tft.drawCentreString("^ PREV", 95, 217, 2);
tft.drawCentreString("NEXT v", 159, 217, 2);
tft.drawCentreString("-", 223, 206, 6);
tft.fillRect(286, 219, 3, 16, TFT_WHITE);
tft.fillRect(280, 225, 16, 3, TFT_WHITE);
setWarning(warningMenuIndex, inc_dec);
//--------- LOAD MY PIC -----------
if (select == 1) {
clickSound();
tft.fillRect(0,30,320,239,TFT_BLACK);
loadMyPic();//load pic from sdcard to spiffs
tft.setTextColor(TFT_BLACK,TFT_WHITE);
tft.drawCentreString("[- Tap screen or press button to exit -]",159,215,4);
delay(400);
while (digitalRead(SELECTOR_PIN) == HIGH) {
while (digitalRead(SELECTOR_PIN) == HIGH && !isScreenPressed()) {
//wait for button press or tap to exit
checkCPUTemp();
autoDim();
uint16_t t_x = 0, t_y = 0;
yield();
}//while
while (isScreenPressed()) { delay(10); yield(); }
clickSound();
tft.fillScreen(TFT_BLACK);//clear screen
tft.fillRectVGradient(0, 0, 320, 26, TFT_ORANGE, 0xfc00);
tft.setTextColor(TFT_BLACK);
tft.drawCentreString("[--- Configuration Menu ---]",159,0,4);
listMenu(select);
}
//--------- UPDATE FIRMWARE -----------
if (select == 2) {
clickSound();
tft.fillRect(0,30,320,239,TFT_BLACK);
tft.pushImage(56,44,60,60,sdcard);//show sdcard icon
tft.pushImage(203,44,60,60,wifi);//show wifi icon
tft.setTextColor(TFT_CYAN,TFT_BLACK);
tft.drawCentreString("Touch an icon to choose",159,125,4);
tft.drawCentreString("firmware update method.",159,155,4);
tft.setTextColor(TFT_BLACK,TFT_WHITE);
tft.drawCentreString("[- Tap bottom to exit -]",159,215,4);
delay(500);
while (digitalRead(SELECTOR_PIN) == HIGH) {//wait for button press to exit
autoDim();
checkCPUTemp();
//touching
uint16_t t_x = 0, t_y = 0; // To store the touch coordinates
bool touched = getTouch(&t_x, &t_y);
if (touched && (t_y < 50 || (t_y >= 180 && t_y < 210))) break;
if (touched) {
if ((t_y > 44) && (t_y < 104)) {
if ((t_x >= 56) && (t_x < 116)) {
clickSound();
updateFirmwareSD();//update by sd card
}
if ((t_x >= 203) && (t_x < 263)) {
clickSound();
updateFirmwareWIFI();//update by wifi
break;
}
} else if (t_y > 180) {
break; // Tap exit
}
}
delay(200);//touch screen delay
yield();
}//while
while (isScreenPressed()) { delay(10); yield(); }
tft.fillRect(0,30,320,210,TFT_BLACK);
listMenu(select);
}
//------------ WARNING SETTING -----------
if (select == 3) {
int8_t warningMenuIndex = 0;//index for warning setting
int8_t inc_dec = 0;//-1=decrease,0=no change, 1=increase
clickSound();
tft.fillRect(0,30,320,210,TFT_BLACK);
tft.setTextColor(TFT_WHITE,TFT_BLACK);
tft.drawCentreString("[ Warning Parameter Setting]",159,30,2);
tft.drawFastHLine(0,50,320,TFT_RED);
tft.setTextColor(TFT_WHITE,TFT_RED);
tft.drawCentreString("[- Tap here or Press button to Save & Exit -]",159,190,2);
for (uint8_t i = 0;i<5;i++) //draw buttons
tft.fillRoundRect(i*64,211,60,30,5,TFT_NAVY);
tft.setTextColor(TFT_WHITE);
tft.drawCentreString("DEFAULT",31,217,2);//reset
tft.drawCentreString("^ PREV",95,217,2);//prev
tft.drawCentreString("NEXT v",159,217,2);//next
tft.drawCentreString("-",223,206,6);//-
tft.fillRect(286,219,3,16,TFT_WHITE);//+
tft.fillRect(280,225,16,3,TFT_WHITE);//+
setWarning(warningMenuIndex,inc_dec);//list menu first
delay(500);
while (digitalRead(SELECTOR_PIN) == HIGH) {//wait for button press to exit
autoDim();
checkCPUTemp();
String status = "";
if (foundOBD2) {//temperature read not working if not connect to bluetooh or
status = " " +String(tempRead,1)+"`c";
} else {
status = "--.-`c";
}
tft.setTextColor(TFT_YELLOW,TFT_BLACK);
tft.drawRightString(status.c_str(),319,30,2); //show cpu temp on top-right corner
//touching
uint16_t t_x = 0, t_y = 0; // To store the touch coordinates
bool touched = getTouch(&t_x, &t_y);
if (touched && (t_y < 50 || (t_y >= 180 && t_y < 210))) break; // Touch top header or prompt to exit
if (touched && (t_y >= 55 && t_y < 180)) {
int8_t row = (t_y - 60) / 30;
if (row >= 0 && row < 4) {
int8_t row = (t_y - 58) / 16;
if (row >= 0 && row <= maxpidIndex) {
warningMenuIndex = row;
setWarning(warningMenuIndex, 0);
clickSound();
@ -242,71 +493,308 @@ void configMenu() {
}
if (touched && (t_y > 211)) {
clickSound();
if (t_x < 64) { // DEFAULT
for (uint8_t i = 0; i < 4; i++) {
warningValue[i] = pidConfig[i][8];
#ifdef SERIAL_DEBUG
Serial.printf("%d - %d\n",t_x,t_y);
#endif
if (t_x < 64) {//DEFAULT
tempOffset = factoryTempOffset;//load default
//read default warning value
for (uint8_t i=0;i < maxpidIndex; i++) warningValue[i] = pidConfig[i][8];
}
}
if ((t_x >= 64) && (t_x < 128)) warningMenuIndex--;
if ((t_x >= 128) && (t_x < 192)) warningMenuIndex++;
if ((t_x >= 192) && (t_x < 256)) inc_dec = -1;
if ((t_x >= 256) && (t_x < 320)) inc_dec = 1;
if (warningMenuIndex >= 4) warningMenuIndex = 0;
if (warningMenuIndex < 0) warningMenuIndex = 3;
if ((t_x >= 64) && (t_x <128)) warningMenuIndex--;//prev
if ((t_x >= 128) && (t_x <192)) warningMenuIndex++;//next
if ((t_x >= 192) && (t_x <256)) inc_dec = -1;//decrease
if ((t_x >= 256) && (t_x <320)) inc_dec = 1;//increase
if (warningMenuIndex == maxpidIndex+1) warningMenuIndex = 0;
if (warningMenuIndex < 0) warningMenuIndex = maxpidIndex;
setWarning(warningMenuIndex, inc_dec);
inc_dec = 0;
}
yield();
}
while (isScreenPressed()) { delay(10); yield(); }
setWarning(warningMenuIndex,inc_dec);//update list
inc_dec = 0;//reset
// Save warning values
for (uint8_t i = 0; i < 4; i++) {
pref.putString(pidConfig[i][0].c_str(), warningValue[i]);
}//if touched
}//while
//exit and save warning data to preference
pref.putInt("tempOffset",tempOffset);//save tempoffset
for (uint8_t i=0;i < maxpidIndex; i++) {//save all pid
pref.putString(pidConfig[i][0].c_str(),warningValue[i]);
}
tft.setTextColor(TFT_BLACK, TFT_GREEN);
tft.drawCentreString("Parameters Saved.", 159, 120, 4);
tft.setTextColor(TFT_BLACK,TFT_GREEN);
tft.drawCentreString("Parameters Saved.",159,120,4);
beep();
delay(1000);
tft.fillScreen(TFT_BLACK);
tft.fillRectVGradient(0, 0, 320, 26, TFT_ORANGE, 0xfc00);
tft.setTextColor(TFT_BLACK);
tft.drawCentreString("[--- Configuration Menu ---]", 159, 0, 4);
tft.fillRect(0,30,320,210,TFT_BLACK);
listMenu(select);
}
// Option 1: Load my pic
else if (select == 1) {
//--------------- DTC -----------
if (select == 4) {//https://www.elmelectronics.com/wp-content/uploads/2016/07/ELM327DS.pdf
clickSound();
tft.fillRect(0, 30, 320, 239, TFT_BLACK);
loadMyPic();
tft.setTextColor(TFT_BLACK, TFT_WHITE);
tft.drawCentreString("[- Tap screen or press button to exit -]", 159, 215, 4);
delay(400);
while (digitalRead(SELECTOR_PIN) == HIGH && !isScreenPressed()) {
tft.fillRect(0,30,320,239,TFT_BLACK);
tft.pushImage(0,28,25,25,engine);//about
tft.setTextColor(TFT_YELLOW,TFT_BLACK);
tft.drawString("Diagnostic Trouble Codes",30,28,4);
delay(500);
getPID("ATE0");//force echo off
//#1 get number of DTC & MIL status
//getAB2("41 01 86 0E 88 88 41 01 81 0C 00 00 ","41","01");//(A = 80+1,80h=MIL ON,no of dtc = A-80h)
uint8_t error_cnt = 0;
uint8_t no_of_dtc = 0;
A = 0xFF;//supoose error read A
while ((A == 0xFF) && (error_cnt <3) ) {//if A == 0xFF repeat reading again (A must be 0x80+) try 3 times
Serial.print(F("MIL Status 0101->"));
getAB2(getPID("0101"),"41","01");//try read MIL status
//Terminal(String(A).c_str(),0,88,320,125);
error_cnt++;
delay(100);
}
#ifdef TEST_DTC
A = 0x86;
#endif
if (A == 0xFF) {//Error reading MIL status
Serial.println(F("Error Reading MIL Status!"));
tft.setTextColor(TFT_WHITE,TFT_RED);
tft.drawCentreString("* Error Reading MIL Status! *",159,120,4);
tft.setTextColor(TFT_LIGHTGREY,TFT_BLACK);
tft.drawCentreString("[ Please try again ]",159,148,4);
tft.setTextColor(TFT_BLACK,TFT_WHITE);
tft.drawCentreString("[- Press button to exit -]",159,215,4);
beep();
} else {
if (A == 0x00) {//41 01 00 = Mil is OFF No DTC
tft.setTextColor(TFT_GREEN,TFT_BLACK);
tft.drawCentreString("MIL is OFF - No DTC",159,120,4);
tft.setTextColor(TFT_BLACK,TFT_WHITE);
tft.drawCentreString("[- Press button to exit -]",159,215,4);
} else if (A >= 0x80) {//41 01 8x if A =>80h then MIL status ON else skip to NO MIL below
Serial.print(F("A = "));Serial.println(A,HEX);
// #2 get Raw Diagnostic Troulbe Code from ELM327
//(for 1 dtc)43 06 00 7D
//(more than 1 dtc) 00E 0: 43 06 00 7D C6 93 1: 01 08 C6 0F 02 E9 02 e: E0 CC CC CC CC CC CC 43 01 C4 01
uint8_t error_cnt = 0;
String dtcRead = "";
//check first header 43 or 00
while ((dtcRead.substring(0,2) != "43") && (dtcRead.substring(0,2) != "00") && (error_cnt < 5)) {
Serial.print(F("Read DTC 03->"));
dtcRead = getPID("03");//try read DTC code
#ifdef TEST_DTC
dtcRead = "00E 0: 43 06 00 7D C6 93 1: 01 08 C6 0F 02 E9 02 2: E0 CC CC CC CC CC CC 43 01 C4 01";
#endif
//Terminal(dtcRead,0,88,320,125);
error_cnt++;
delay(100);
}
if (error_cnt >= 10) {//exist by error counter
Serial.println(F("Error Reading DTCs!"));
tft.setTextColor(TFT_WHITE,TFT_RED);
tft.drawCentreString("* Error Reading DTCs! *",159,120,4);
tft.setTextColor(TFT_LIGHTGREY,TFT_BLACK);
tft.drawCentreString("[ Please try again ]",159,148,4);
tft.setTextColor(TFT_BLACK,TFT_WHITE);
tft.drawCentreString("[- Press button to exit -]",159,215,4);
beep();
} else {
//#3 Interpret get the real DTC code 5 digits
//(for 1 dtc)43 06 00 7D
// 00E 0: <43 06> /00 7D /C6 93 /1: /01 08 /C6 0F /02 E9 /02 2: E0 /CC CC /CC CC /CC CC /<43 01>/C4 01 
beepbeep();
int byteCount = 0;//keep number of data byte
String hexcode[128];//4x16
uint8_t StringCount = 0;
dtcRead.trim();
while (dtcRead.length() > 0) {//split to hex byte
int index = dtcRead.indexOf(' ');
String getByte = dtcRead.substring(0, index);//get first byte
if (getByte.indexOf(':') == -1 ) {//no :
if (getByte.length() >= 3) {
byteCount = strtol(getByte.c_str(), NULL, 16);//get byte count = 14 byte
Serial.print(byteCount);
Serial.print(" = ");
} else {//skip ':' byte
hexcode[StringCount++] = getByte;//copy strings from 0 to space to hexcode
Serial.print(getByte + ",");
if (StringCount == byteCount) break;//stop when byte count reach, ignore the rest
//4306007DC6930108C60F02E902E0 = 14 byte
}
}
dtcRead = dtcRead.substring(index + 1);//copy the rest behind space to elm_rs
}//while
Serial.println(); //debug split hex byte
//interpret DTC 007D=P007D C693=U0693 0108=P0108 C60F=U060F 02E9=P02E9 02E0=P02E0
String dtcList[16] = {};//to keep all DTC in list
no_of_dtc = 0;
for (uint8_t index = 0;index < StringCount; index++) {
if (hexcode[index] == "43") {//check if first nibble is 43
index = index + 2;//skip 2 byte to next pid
}
String dtc_1 = hexcode[index];//C6
uint8_t code = strtol(dtc_1.substring(0,1).c_str(),0,16);//0x0C compare with dtcMap table
dtc_1 = dtcMap[code]+dtc_1.substring(1);//U0+6 = U06 change prefix,remove 1st char get the rest
index++;
String dtc_2 = hexcode[index];//0F
dtcList[no_of_dtc] = dtc_1+dtc_2;//U060F
Serial.print(dtcList[no_of_dtc] + ",");//got real DTC code here
no_of_dtc++;//keep real no of dtc in no_of_dtc
}//for
tft.setTextColor(TFT_RED,TFT_BLACK);
String txt = "MIL is ON - No of DTCs = "+String(no_of_dtc);
tft.drawCentreString(txt,159,58,4);
tft.drawFastHLine(0,85,320,TFT_WHITE);
Serial.printf("\nNo of DTCs = %d\n",no_of_dtc);
//#4 List all DTC on screen
tft.setTextColor(TFT_WHITE,TFT_BLACK);
for (uint8_t i=0;i<no_of_dtc;i=i+4) {
tft.setTextColor(TFT_PINK,TFT_BLACK);
tft.drawString(dtcList[i].c_str(),0,92+30*round(i/4),4);
tft.setTextColor(TFT_YELLOW,TFT_BLACK);
tft.drawString(dtcList[i+1].c_str(),80,92+30*round(i/4),4);
tft.setTextColor(TFT_GREEN,TFT_BLACK);
tft.drawString(dtcList[i+2].c_str(),160,92+30*round(i/4),4);
tft.setTextColor(TFT_BLUE,TFT_BLACK);
tft.drawString(dtcList[i+3].c_str(),240,92+30*round(i/4),4);
}
//#5 show clear MIL button
tft.setTextColor(TFT_BLACK,TFT_WHITE);
tft.drawRightString("[Press button to exit]",319,220,2);
tft.fillRoundRect(0,215, 127, 24, 12, TFT_RED);
tft.setTextColor(TFT_WHITE);
tft.drawCentreString("Clear MIL",63,217,4);
}//else !error_read//
}//else if A >0x80
}//else if error_ent>5
while (digitalRead(SELECTOR_PIN) == HIGH) { //wait for button press to exit
checkCPUTemp();
autoDim();
yield();
}
while (isScreenPressed()) { delay(10); yield(); }
uint16_t t_x = 0, t_y = 0; // To store the touch coordinates
bool touched = getTouch(&t_x, &t_y);
if (touched) {
if (no_of_dtc != 0 && (t_y > 215) && (t_x < 127)) {//touch clear MIL button
clickSound();
tft.fillScreen(TFT_BLACK);
BTSerial.print("04\r");//clear MIL 04->7F 04 78 7F 04 78
tft.setTextColor(TFT_BLACK,TFT_GREEN);
tft.drawCentreString("* Successful Clear MIL *",159,120,4);
Serial.println(F("* Successful Clear MIL *"));
beepbeep();
delay(3000);
break;
} else if (t_y > 200 || no_of_dtc == 0) {
break; // Touch exit
}
}
yield();
}//while button exit
while (isScreenPressed()) { delay(10); yield(); }
tft.fillRect(0,28,320,239,TFT_BLACK);
listMenu(select);
}//select = 4
//---------- Auto OFF Voltage -----------
if (select == 5) {
clickSound();
tft.fillRect(0,30,320,210,TFT_BLACK);
tft.pushImage(0,30,25,25,autooff);//about
tft.setTextColor(TFT_WHITE,TFT_BLACK);
tft.drawString("Gauge Auto-off Setting",40,30,4);
tft.setTextColor(TFT_WHITE,TFT_BLACK);
tft.drawString("Set detection PCM voltage to turn off gauge.",10,65,2);
tft.drawString("If gauge turn off while the engnine is running",10,85,2);
tft.drawString("Please lower down the voltage",10,105,2);
tft.drawString("Volt",220,135,4);
tft.setTextColor(TFT_BLACK,TFT_WHITE);
tft.drawCentreString("[- Tap here or Press button to exit -]",159,180,4);
for (uint8_t i = 0;i<5;i++) //draw buttons
tft.fillRoundRect(i*64,211,60,30,5,TFT_NAVY);
tft.setTextColor(TFT_WHITE);
tft.drawCentreString("DEFAULT",31,217,2);//reset
tft.drawCentreString("-",223,206,6);//-
tft.fillRect(286,219,3,16,TFT_WHITE);//+
tft.fillRect(280,225,16,3,TFT_WHITE);//+
tft.setTextColor(TFT_YELLOW,TFT_BLACK);
String result = String(ecu_off_volt, 1);
tft.drawCentreString(result.c_str(),159,135,4);
delay(500);
while (digitalRead(SELECTOR_PIN) == HIGH) {//wait for button press to exit
checkCPUTemp();
autoDim();
uint16_t t_x = 0, t_y = 0; // To store the touch coordinates
bool touched = getTouch(&t_x, &t_y);
if (touched && (t_y < 50 || (t_y >= 165 && t_y < 210))) break; // Touch top or prompt to exit
if (touched && (t_y > 211)) {
clickSound();
#ifdef SERIAL_DEBUG
Serial.printf("%d - %d\n",t_x,t_y);
#endif
if (t_x < 64) {//DEFAULT
ecu_off_volt = factoryECUOff;
}
if ((t_x >= 192) && (t_x <256)) {//decrease
ecu_off_volt = ecu_off_volt - 0.1;
if (ecu_off_volt <= 11.0) ecu_off_volt = 11.0;
}
if ((t_x >= 256) && (t_x <320)) {//increase
ecu_off_volt = ecu_off_volt + 0.1;
if (ecu_off_volt >= 15.0) ecu_off_volt = 15.0;
}
String result = String(ecu_off_volt, 1);
tft.drawCentreString(result.c_str(),159,135,4);
delay(300);//touch screen delay
}//if touched
yield();
}//while
while (isScreenPressed()) { delay(10); yield(); }
//exit and save warning data to preference
pref.putFloat("ecu_off_volt",ecu_off_volt);//save ecu_off_volt
tft.setTextColor(TFT_BLACK,TFT_GREEN);
tft.drawCentreString("Parameters Saved.",159,120,4);
beep();
delay(1000);
tft.fillRect(0,30,320,210,TFT_BLACK);
listMenu(select);
}//select = 5
//---------------------ABOUT-----------
if (select == 6) {
clickSound();
delay(500);
xTaskCreatePinnedToCore(
&TaskPlayMusic
, "play music in core 0" // A name just for humans
, 4096// This stack size can be checked & adjusted by reading the Stack Highwater
, NULL// no variable passting to task
, 3 //Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
, &TaskHandle0
, 0);//core0
animation();//play star field animation
vTaskDelete(TaskHandle0);//stop animation and text animation
pinMode(BUZZER_PIN,OUTPUT);//set pin mode again unless speaker stop working
ledcAttachPin(BUZZER_PIN, buzzerChannel);//reattach buzzer pin
clickSound();
while (isScreenPressed()) { delay(10); yield(); }
tft.fillScreen(TFT_BLACK);//clear screen
tft.fillRectVGradient(0, 0, 320, 26, TFT_ORANGE, 0xfc00);
tft.setTextColor(TFT_BLACK);
tft.drawCentreString("[--- Configuration Menu ---]", 159, 0, 4);
tft.drawCentreString("[--- Configuration Menu ---]",159,0,4);
listMenu(select);
}
// Option 2: Exit
else if (select == 2) {
}//if (select ==6)
//---------------------EXIT-----------
if (select == 7) {
clickSound();
break;
if (showsystem != currentFlag) {//save to eeprom only when flag changed
pref.putBool("showsystem", showsystem);//save to NVR
}
break;//exist main config menu loop while
}//select = 7
pressed = false;
prompt = true;
}
delay(30);
}
tft.fillScreen(TFT_BLACK);
}
prompt = true;//to trig reading elm again
} //if (executeSelect >= 0)
delay(40);
} //while (true)
tft.fillScreen(TFT_BLACK);//clear screen
}//configMenu

View file

@ -0,0 +1,99 @@
//elm327 interpreter
//DTC prefex code mapping
const String dtcMap[16] = {"P0","P1","P2","P3","C0","C1","C2","C3","B0","B1","B2","B3","U0","U1","U2","U3"};
//get A B from response return in global A B variable
void getAB2(String elm_rsp,String mode,String para) { //41 05 2A 3C 01>
elm_rsp.trim();
String hexcode[16];
uint8_t StringCount = 0;
while (elm_rsp.length() > 0) {//keep reading each char
int index = elm_rsp.indexOf(' ');//check space
if (index == -1) // No space found
{ //only data without space is now in hexcode {41,05,aa,bb}
hexcode[StringCount++] = elm_rsp; //last byte
//for (index=0;index<StringCount;index++) Serial.println(hexcode[index]);
if ((hexcode[0] == mode) && (hexcode[1] == para)) {//check correct response
A = strtol(hexcode[2].c_str(), NULL, 16); //byte 3 save to A
B = strtol(hexcode[3].c_str(), NULL, 16); //byte 4 save to B
} else A = 0xFF;//error
break;
} else {//found space
hexcode[StringCount++] = elm_rsp.substring(0, index);//copy strings from 0 to space to hexcode
elm_rsp = elm_rsp.substring(index + 1);//copy the rest behind space to elm_rsp
}
} //while
}//getAB
/*------------------*/
String getPID(String pid) {//fucntion getpid response from elm327
while (BTSerial.available()>0) {//clear rx buffer
BTSerial.read();
}
String bt_response = "";
BTSerial.print(pid+"\r");//get no of dtc
delay(500);//wait for response
while (BTSerial.available()>0) {//reading Bluetooth
char incomingChar = BTSerial.read();
//check CR/NL
if (incomingChar == '>') {
Serial.println(bt_response);
BTSerial.flush();
} else {
bt_response.concat(incomingChar);//keep elm327 respond
}
} //while BTSerial
return bt_response;
}
/*------------------*/
/* VIN reading
String resp = "014
0: 49 02 01 4D 50 42
1: 41 4D 46 30 36 30 4E
2: 58 34 33 37 30 39 33 "; */
//convert ascii code to Charactor
const char asciiTable[0x60]= " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}`";
char HextoChar(uint8_t asciiCode) {
if ((asciiCode > 0x20) && (asciiCode < 0x80)) {
return(asciiTable[asciiCode-32]);
}
else return '\0';//null-terminator
}
//----------------------------
//function get VIN Serial.println(getVIN(getPID(0902)));
String getVIN(String elm_rsp) {
String VIN = "";
uint8_t byteCount = 0;
elm_rsp.trim();
while (elm_rsp.length() > 0) {//keep reading each char
int index = elm_rsp.indexOf(' ');//check space
String getByte = elm_rsp.substring(0, index);//get first byte
if (index == -1) {//no space found
byte ascii = strtol(getByte.c_str(), NULL, 16);//read ascii
VIN.concat(HextoChar(ascii));//last char
//check correct VIN
if (VIN.length() == byteCount) {
VIN = VIN.substring(3);//remove first 3 string
Serial.println("VIN: " + VIN);
return VIN;//return VIN number
} else {
return "Cannot read VIN";
}
} else {//found space
if (getByte.indexOf(':') == -1 ) {
if (getByte.length() >= 3) {
byteCount = strtol(getByte.c_str(), NULL, 16);//get byte count
} else {//skip ':' byte
byte ascii = strtol(getByte.c_str(), NULL, 16);//read ascii
VIN.concat(HextoChar(ascii));//convert to hex charactor
}
}
elm_rsp = elm_rsp.substring(index + 1);//copy the rest behind space to elm_rsp.
}//else
} //while
return "Cannot read VIN";
}//getVIN
//----------------------------

View file

@ -0,0 +1,326 @@
//Firmware updater library
#include <esp_ota_ops.h>//ota partition boot option
#include <Update.h> // main updater
#include <FS.h> // File System
#include <SD.h> // SD Card ESP32
#include <SPIFFS.h> //safe file
//Wifi updater
#include <WiFi.h> //wifi
#include <WebServer.h>
const char* ssid = "Va&Cob OBD2 Gauge";
const char* password = "12345678";//default password
IPAddress local_IP(192, 168, 4,1);
IPAddress gateway(192, 168, 4, 1);
IPAddress subnet(255, 255, 255, 0);
WebServer server(80);
#define firmware_filename "/VaAndCobOBD2Gauge.bin"//firmware file
/*------------ SOUND EFFECT ----------*/
void beepbeep() { //2 shot beep
ledcWriteTone(buzzerChannel,2000);
delay(50);
ledcWriteTone(buzzerChannel,0);
delay(50);
ledcWriteTone(buzzerChannel,2000);
delay(50);
ledcWriteTone(buzzerChannel,0);
}
void beep() {
ledcWriteTone(buzzerChannel,2000);
delay(500);
ledcWriteTone(buzzerChannel,0);
}
void clickSound() {
ledcWriteTone(buzzerChannel,5000);
delay(5);
ledcWriteTone(buzzerChannel,0);
}
/*-----------------------------*/
//html update file
static const char uploadIndex[] PROGMEM =
R"(
<!DOCTYPE html>
<head>
<meta name='viewport' content='width=device-width'/>
</head>
<body>
<img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gHYSUNDX1BST0ZJTEUAAQEAAAHIAAAAAAQwAABtbnRyUkdCIFhZWiAH4AABAAEAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAACRyWFlaAAABFAAAABRnWFlaAAABKAAAABRiWFlaAAABPAAAABR3dHB0AAABUAAAABRyVFJDAAABZAAAAChnVFJDAAABZAAAAChiVFJDAAABZAAAAChjcHJ0AAABjAAAADxtbH
VjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEJYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9YWVogAAAAAAAA9tYAAQAAAADTLXBhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACAAAAAcAEcAbwBvAGcAbABlACAASQBuAGMALgAgADIAMAAxADb/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUF
BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCAAZAUADASIAAhEBAxEB/8QAHQAAAgICAwEAAAAAAAAAAAAABwgABQIGAQMECf/EAD0QAAEDAwQBAwIEAgcHBQAAAAECAwQFBhEABxIhCBMxQRRRFSIyYSNSCRZCcYGR8BgoMzQ3Q3Z0obGy0v/EABwBAAICAwEBAAAAAAAAAAAAAAIEAwUAAQYHCP/EADMRAAIBAgUCBAUDAwUAAAAAAAECEQMEAAUSITEGQRMiUWEycYGRoRRS8AcIQhUjcrHB/9oADAMBAAIRAxEAPwBy9cZGgx5Jby1zaSk0pVGgxnXKgpxsypJKgyUhJACBjJOT2TgY9jpdKl5A3izLfhzK5
U5LjSy28+y+mOoKB79NKU8QMg+4Vkfb4+b+if6HdRdbZZTza1qU0pPq0yZY6TBMAbQfUyewx6tSt2rcHD1VGpQ6PGXJny2IUdGOTshwIQnPQyT18j/PXlXcUNGMCU6D7KZhvOJP9xSgg6+f0zcq7qbX/qTcM6XKY6YkyleotCD2CjnnhkYPWrqHvfuTOXxYuGoyF/ZpCVH/ANk69bP9r2apRWql9SYETJLKPtpP5OLZModxsw/n0w9jVZjPN80h9KQCf4sdxs9e/wCpI12RKpDnrWiNLYkLR+tLTgUUf3gHI0jyq3ubWJjEmpVO4oTHIIVMWXmW2kk9nrA6Gfbs4wPjWMbcSqVt+LAXUqpyLiUtTJM1b6gs9AqSrIxnBwkAj7q1G/8AbTcmnNLMUZlEtpGoD
nk7enYE+2LGn049T4agw941yejoSeO8e7F0CXUbomy30yVIENmSoHi2AcrH7KJx3/L9jotAYGvkzqXJV6dzatlS11reEYLpOkmN4n04Pvjl7qgLas1IMGjuOMUV93lD29s+rXJUWJUiBTI6pMhENsLdDae1EJJGcDJPfsDrzbabjUXday6bdNBdW5S56FKb9YBK0FKilSVgE4IKT1nV/PgR6rBkwpjCZMSS2pl5lYylxChhSSPkEEj/AB0g+1O5EjxmsPyDshySuPU7WfXMoiXz+cpfKWG3UjHsFLjL+xKx7ZJ05k2UU85s6q0Qf1CskDsUYhTt7Egz6YqK9Y0XBPwkH784cHbDfC3d3K1dNNoCJizbkv6KZKeaSlhTnJQw2oKPIfkJzgdEffWuS/LCwYe9Le
165MtVxqkIiF1DSTFS8pAUGy5zzy7CcY/V1760/wAYLbpvjp4qi5qspYflwl3LUnHP1ErbCm0DGT+hKAB3lRPydJWmr2rWtn7o3El3ZChbwSblFdp8dlREllKXe0A/GStawPshGuvy7pjL7+9u1QMaKEU0Ik+c7FjA+EEEn0BGEal1UpokxqO5+WPq9U6pEotNl1CfJbiQYjK5EiQ6rCGm0pKlLUfgAAn+7QZsvzCsO97spdEis1uC3WH3Y1Hq1Qp5Zg1RbZwsMOZOcHr8wT2QDgnGqzcDyJoLPjDR7rqVORcTt2wWqexQo7n/ADsl9BQ6xkA4CT6gV11jGMnBVXb2mTdgdzLPa3wNSplu0aFKq1pQhIQ/EjST/FUy4UpyVjoYH/c4/CtKZJ0vRuLW4N6reICw
QAgFioM6V5JBie0T3wde7KuoTjafrj6QVmtQLepcqpVOYxAp8VsuvypDgQ22ke5Uo9AaXWV/SG7PRriFLE+qPR/U9NVVagFUVP5sZznmR85CD1oR+UW7l2bk+Flt3HUqe3brdx1ptMmPGWsgwwHi3y5DJC1NoWPuOPwc6bm29srETtfEtuBRaZIs+RDb/g+iktSG+Aw6rr8yiMK5n82e850muUWOU2q1s1Rnd3ZIRgAumAd4MmTsOMSeNUrOVpEAAA7++LqHuBbU+zkXYxXIDltLYMkVT10hgNgkFRUehgggg9ggg99aBTv9Ids6zcH4b+IVRccOFtVURAUYo/Nxz78yPnIQev8ALQg8r6bae3/ijRaJtdNZesufcLKKjLp9QVMSo+ktRCjyIyVIQojIAKE9d9N
1R9rdvxttHt6LQaS/Z7sRHFn0kKZeaKRhwq/tEjCvUzn+1nOpP9Mymxt1urpKjrVdlUbKVCx8XPm34xrxa1RiikAgCe8/LHruHdq27f2xl3+Joqlsx4v1n1VNKXvUbzjKOwCc9YyMYI0KbG88dqb5r8OkNzqjRpMxYbjuVeJ6LTij7D1ApSU94GVEDJHels2onr/2QvIOkwpDsu16bOdbpDq3CsBpSgSlP2GAhXXuVk/OqG9nNx7j8cNtDdNiRY21tA+imO1umymXZ7kYANpIT6nJvkHOwE5zxyRg56W06Qy4GtRuGJIqaFOoKYKBx5T8TSYgYVe9q+Vl9JO3vGPpxnPtrnVZbFxwrvtyl1ynLU5AqUVuWwpSeJKFpCk5HwcH21Z4z1rxyohpOyHkbfbF2DqEjG
s7g7mWxtTbzlbuusR6PTkngHHiSpxeCeCEDKlqwD0kE9aFNu+bu2tbrMSBNVWLZRNOIc+vU9UWJJ6JylwkgDrGVY7I++tU31ixLk8xdlKLcLbUi30xJ0tiLIIU07LCFlIUk9ZBQ0RnOT1j30V/J2g0Wv7BX23W2Y7kePSJMllx9HL0nkNKW2tPyFBYTjHv7fOu3oWGXUKdrTukZnriZUgBQWKiBB1HaTv7YQapVYuUIAX84tN4d66BslbFPrtcanzIk+c3T4zdLYD7rjriFrRhPIZBDZ9u8kdap9uvJezdx7lNuMiqUC4i36zVJuGCuFIfRjJU2lXS+s+xz+2li3JqlaleHHjxMDIm1pFy0n6Zh90APKQ1JSyFKI6BCUZJ9sn7a2q56/eS/JbaC4N1LSYtWmNSH6
XSn6RMRNS5OkI4JS+vIKU+xSAPfPZGcXSdNWn6VlbeoPFAIYCTTmAE5MxvHGIDcuX9tu3r74L24vlpaG2l/SrPnUu4qlWYzLch1NJp31KEtrAIUcKzgZ761te1O/Fk70NSf6r1hMmZE6lU+Q2piUx7fqaWAcZIHIZTnIznQmsrB8/9wf8AxKL/APdjVXurDh2t5xbRy6AhqHV67Fmt1luLhBlR0tqKFugfq7CzyI79IfyjCZyjL6qrbIrLV8EVdUyCdOogiNhzBnB+NUU6idtURG/ODxZO8FCv68rutimJlpqVrvtx55faCWypYUU8CFHkPyn4Gs9p926JvLb0ys0BuWiHEnO09z6xtKFeq3x5YAUcj8wwdBHxkJHkn5E/GapE6/we/wBf6GvV4Af9Ibj/APK6h/
8ADWlcyye2taFxUpzKCjG/71lvzxg6dZ2ZQe+r8HB4vzcG3tsrckV256rHpFLZ6Lz6u1qwSEISMlayAcJSCTg6D9I839u51TgsVKLcVs0+esNw61XaUqNAkKIyOLuT137kAfJOO9az5LxotweT2wdDrzaHrcdfnSVMPkKZekobSWkqQejhQRjOc8z+4O1eTW5lStSm1KnTtoHdwLKRTxNqE5yc01HQEqUSgoUgklIQFAj7jA1NY5VZtSt0qoXqVgW2dUCjUVEati20wT7YF6zyxBgL7T/Bg9R325bLbzDiXmXEhSHGzlKgRkEH5BHzoY7VeR9mbyXTctAtuU+/NoKyl9bqUpbfSFqR6jKgo80ZT+rA6Un76HG4O+9LpvhM5edNgotlqqUj8PpNMZdSfQW5yZbQ2Ql
IPFIUvAA6QftnQFtC9LG2bu/YCfatz0edN+j/AKu3SzCkggpfIcK3COilDzi1cj/Kn49mMv6a8e2uDWVvEBZU9AUBJ1Rtv8I3iTgal0VZdPHJ+R/k4d67N2aJZl/WjaFQTKNWuhUhMAtNhTYLKQpfM5BT0Rjo667/AN4aFttcloUOrIlqnXRNMCB9M0FpDgKB+clQ4jK099/Og/5AH/ey8eSTgF6rDPQ/7LY14/Lc8t7vHVI7UblWriM5/Ux/r/R0ra5PbVatmjz/ALlN2bfuuuPl8Iwb12Af2IH3jBm3Y33s3ZaJFXc9TLMyWeMSmxW1Py5Jzj8jae8fGTgZ6znGtZ2/8srGv25WbddRV7Tr8kJVFp1zwTCdlA+3p9lKicjAzk/AOh1tRGjXN5vbuTa+Ey6xQYkG
PRUSVczEjKbytTKSfyglQJKR7uq+VnPi8hN93LHuWHVbx2KVVKZQ6r6FHuOZUmQFOlR4LbSWyQSEc8HOCn9sh2lklqWSyWmz1WQOW1qu7CQFVo1ASJ3nmMRmu27yAJjgnj1jjBi3l8krY2PrVFpNbg1mo1CrtuuRWKPDEhag3jlkcgf7XwD0D9tWe0G99I3nbqq6VSK9Sfw4tBxNcp5ilfqc+PDs8v0HP2yPvoDeUtWr9C8p9lJtrUBNz15qLU/pqUqWiKl8lkhX8RfScJKld+/HA7I0xO1Vx3lc9uyJV8Wg3ZdWblqabp7VRbnBbIQgh3mjoZUVp4+44g/Okb3Lbe0yqjcBPO4knWAQdRGyckQOeMHTqs9VlnYe3t64l4be25fzUdu4aUzVExyoteoVAozjOCCCM4
H+Q0O6r4oWVUqq7LQ1IjMvLC3GUuKUf34qJyOXzkKPZIIOjLrIe2qDJ+t+pen6PhZZf1KSAEaQxgA8wDIE+3fF4tRk+E40eDshYdPUst2tT3FLJKlSG/XP+BWSR/cNWTe2FoN/ptajAf8AoWv/AM62fU0jc9V5/ctNe/qt86jf9TGMFWp+4/fGso2ztJDiVotmkIUk5SUwmwQf2wnWoUbxxtWjXAxU2m1L9B8PttK7GR2lJycYBCT0Aeuye9FXUOnrDrbqTLadSla39RVqCG85Mj6zHJ4wxTvLmkCEqETjrix2YbDTDDSWWW0hCG0JCUoSBgAAew13ax1kPbXIFmdizGScJEknfEPelx388LaPvtuXTrsk116jIQw1GqMKNGCvrm0Ocu18xxJThOcKxxScdaY7U1aZ
dml3lNY3Fk+liCJ9j88QVaSVV0uJGB1vhtK7u7tbNsiBWRbESZ6SHXmogeAZQpKvTSkKTgEpSPfGMjBzrxUbxf2xplrQqM9ZdDnGPDREXNeprPrvYQElxSuOeR7Oc5yc50UtZj20xTze+o0Ft6VUqobVttuYkkjc/WcRNSps2or7YWem+FEVrZB/bip3hMqLEaqfilEqaI3pPUtf8qRzIUCSskZHayRg4I1+7/Be49zYbEa9956zcjEJC/oG1U5DaWVlOErV/EVzPXZPZHyM9Nxqat6fVmcUXNRKo1SWnSsgkCSNtp7xE4A2VEwCPycDGnbHQ52xrO2V2zUXFTm4KKf9YzH+lcLbfH0lBPJYC08UnlnGUjrs6CafBe6Y1O/AYm+t0MWlx9D8ILSiPQ9vT5B4Jxjr9G
MfGOtN19tTS9t1JmVmahpVBDHUQVUjUe4BBAPywTWtJ9mHGBPTfGWx6Zsk/tg3TyaBJZIkvdfUPP8AR+oK8f8AECkpIOMDiBjiMaDw8F7oapyqExvpdLVpqR9OaR6aiPQxj0uXrBOOPWOGMfGOtNyPbU1Ja9SZpbltFWdZ1GQG83qNQMH3EY01rScCRx6bfTAkkeN1vw/H+o7VW+7+C06ZEMdc5TQddW4SkqecAKeazxHyPgDAAGg4PAy459uRLYrG9tfn2kw2hn8GZiFpr00EFKQC8pOBgYyk4wPtpvk/Gs9FbdSZpaa1pVd2YuSQpOriQSDB27Y0balUgkcbfTFZbVvQrRt2l0Omtlmn02M3EjtlRUUtoSEpBJ9zgDvVnqamucZ2qsXYySd8NAAbDtgab37E0fe2
k09EqbLolcpT/wBTS63TV8JMN3HeD8pOBkfsCCCNDKV4j3Xd4Ypl+bz1+6rUQpJco7UVMT6lAIPB5xKyVjI9yM/Yg+zMamr60z2/s6QoUXGlZiVUlZ/aSCV+hxA9vTc6mGBJvfsA1utYVsW1RKumzEW9U41SgPRoYkJZ9BtxDaEtlSR16gPZP6fnOtRg+KtyVq+bYuG/91ajezNuzE1CFTjTWobIfScoWoIUQSCB3jOBjODpik++udHQz/MLe38Gm4jzf4qSNXMMRIn54E0KbtqI3+fphfNwvGO5bj3eq9/WrubJsqdUoTUB5qPSkSCW0BPXJTg9ykHofb31e7P+NcXbe76leNduWpX1eM1oRxV6vjMdrOShpIJ4An9+h0MZOTNqax8+v6lD9KX8ukLsqglRwCwGoj
641+npB9Ub887fbAx2z2TRtzuTuHdoq6p6rulMyTE+n9MRuAX1y5Hnnn9k+2uzYPZlGxtp1Ghpq6qyJlUkVP11MejwLvH8nHkrOOPvn59tErU0tVzS7ukdaryH0zsP8BC9uw+/fBrRRSCBx/7ge71bJUXeygxIs5+RSqvTXhKpVbgK4SYD4IPNB+xwMj5wPYgEDCd4qXvdcJNGvHeytXHa6el0punNxVSU/wAj7yFlbic4yD7jPYPemSHvrLTVpnl/Y0hSoOIEkSqtp/4kgkfTAvb03ljhe3vESHPtnae3alcP4jRLGeU+9Cfp6S3VFZyjmkrISB2CCFZCj/js25fi7YV/WLWKBCtuh25MmtBLNVg0plD0ZwKC0rBSEn3AyAoZBI+dF7UPtqVs9zIulTxiCpJEbCSdR
JA2O57z6cY0LelpIjAV3M8blbm2tZDUq7qhTbxtMIXCueG0PVW6EJSta21KOeZQlRHLOR74yDV2d4vVRG5FJvXcPcOfuHU6IlX4VHehNw48VZGC56aFEFft312ATnAwfvnU0K59fpSNurwpkcCQG3IBiQDJ2BAxo29MsGI3wGd4fGyNuPdVNu+37knWHekJBZNZpSAoyWusIeQSPUAwMZOMdHIwAPrt8La/uhT303/u1VLrmspQaWo05EWNCcC0lbhYbc4rWpAUjJIwFk4PWGn1NS2/UWY2tNFpOPLsCVUkD0DESBvxMdsY9vSZiCPzgJb6+PFW3Yvm07roN8P2XWLeakNx32aemSo+qMKP5lpA/LkY799bVtBYN42K3VE3buDIv0yi0Yy5FPREMXjz5gcFHly5J9/bh++iH86g+NLVc5u69qLSoQUGw8qyBM7NGrk+uCFBA+sc4//Z"width="100%">
<h3 style='color:blue;'>Please choose file 'vaandcobobd2gauge.bin'</h3>
<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>
<input type='file' name='update' accept=".bin" id='file1' onchange='uploadFile()'>
</form>
<p style='align:center'>
<progress id='progressBar' value='0' max='100' style='width:100%'></progress>
<div id='status' style='text-align:center';>0%</div>
</p>
<script>
function _(el) {
return document.getElementById(el);
}
function uploadFile() {
let file = _('file1').files[0];
// alert(file.name+' | '+file.size+' | '+file.type);
let req = new XMLHttpRequest();
let formdata = new FormData();
formdata.append('file1', file);
req.upload.addEventListener('progress', progressHandler, false);
req.addEventListener('load', completeHandler, false);
req.addEventListener('error', errorHandler, false);
req.addEventListener('abort', abortHandler, false);
req.open('POST', '/update');
req.send(formdata);
}
function progressHandler(event) {
var percent = (event.loaded / event.total) * 100;
_('progressBar').value = Math.round(percent);
_('status').innerHTML = Math.round(percent) + '%';
}
function completeHandler(event) {
_('status').innerHTML = 'Restarting...';
}
function errorHandler(event) {
_('status').innerHTML = 'Upload Failed';
}
function abortHandler(event) {
_('status').innerHTML = 'Upload Aborted';
}
</script>
</body>
</html>
)";
/*----- OTA Web Server ------*/
void StartOTAserver() {
//open upload page http://192.168.4.1
server.on("/", HTTP_GET, []() {
Serial.println(F("Request upload firmware..."));
server.sendHeader("Connection", "close");
server.send(200, "text/html", uploadIndex);
});
//handling uploading firmware file http://192.168.4.1/update
server.on("/update", HTTP_POST, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
if (Update.hasError()) {//error
tft.setTextColor(TFT_WHITE,TFT_RED);
tft.drawCentreString("Error: bad firmware file!",159,170,4);
beep();
}
else {
esp_ota_mark_app_valid_cancel_rollback();//prevent from boot old firmware
delay(3000);
ESP.restart();//successful upload restart esp
}
}, []() {
HTTPUpload& upload = server.upload();
if (upload.status == UPLOAD_FILE_START) {
beepbeep();
Serial.printf("Firmware: %s\n", upload.filename.c_str());
tft.setTextColor(TFT_BLACK,TFT_GREEN);
tft.drawCentreString("Updating... please wait",159,170,4);
if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_WRITE) {
// flashing firmware to ESP
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_END) {
if (Update.end(true)) { //true to set the size to the current progress
Serial.printf("Update Successful... Restart");
tft.setTextColor(TFT_BLACK,TFT_GREEN);
tft.drawCentreString("Update Successful... Restart",159,170,4);
beepbeep();
} else {
Update.printError(Serial);
}
}
});
server.begin();
}//startOTAserver
/*-------------- WiFi Updater----------------*/
void updateFirmwareWIFI() {
WiFi.mode(WIFI_AP);//set wifi mode soft access point
String pwd = String(random(99999999));//random new password at least 8 digit long to get it work
for (uint8_t i=pwd.length();i<8;i++) {
pwd = "0"+pwd;//add 0 prefix to set 8 char length password
}
password = pwd.c_str();
WiFi.softAP(ssid, password);//start ACCESS Point
if (!WiFi.softAPConfig(local_IP, gateway, subnet)) {//error start soft AP
Serial.println(F("STA Failed to configure"));
tft.setTextColor(TFT_WHITE,TFT_RED);
tft.drawCentreString("Failed to start WiFi!",159,120,4);
beep();
delay(3000);
} else {//softAP config OK
StartOTAserver();//start server
//show WiFi softAP information
tft.fillRect(0,30,320,239,TFT_BLACK);
tft.setTextColor(TFT_CYAN,TFT_BLACK);
tft.drawCentreString("> Connect to gauge Wi-Fi <",159,40,4);
tft.setTextColor(TFT_WHITE,TFT_BLACK);
String txt = "SSID: "+String(ssid);
Serial.println(txt);
tft.drawString(txt,0,80,4);
txt = "Password: "+String(password);
Serial.println(txt);
tft.drawString(txt,0,110,4);
txt = "IP Address: "+ WiFi.softAPIP().toString();
Serial.println(txt);
tft.drawString(txt,0,140,4);
tft.setTextColor(TFT_BLACK,TFT_WHITE);
tft.drawCentreString("[- Press button to exit -]",159,215,4);
while (digitalRead(SELECTOR_PIN) == HIGH) {//wait for button press to exit
autoDim();
checkCPUTemp();
server.handleClient();//update server handle
delay(300);//delay button press
} //exit wifi update
clickSound();
server.stop();
WiFi.mode(WIFI_MODE_STA);
WiFi.softAPdisconnect();//turn off WiFi
}//else WiFi.softapconfig
} //updateFirmwareWiFI
/*----------- SD Card Updater --------------*/
// perform the actual update from a given stream
void performUpdate(Stream &updateSource, size_t updateSize) {
if (Update.begin(updateSize, U_FLASH, LED_RED_PIN, LOW)) {
//add progressbar
tft.fillRoundRect(50,61, 218, 28, 14, TFT_LIGHTGREY);
tft.fillRect(59,67,200,16,TFT_BLACK);//0% progress bar
//update progress
Serial.print(F("Progress: "));
//progress callback
Update.onProgress([&](size_t written, size_t total) {
uint8_t progress = written * 100 / total;
tft.fillRectHGradient(59,67,progress*2,16,TFT_RED,TFT_GREEN);//progressbar
if (progress%10 == 0) Serial.print(F("*"));
ledcWriteTone(buzzerChannel,random(4000)+8000);//acceleraet sound effect
});
//write firmware from SDCard here
size_t written = Update.writeStream(updateSource);
Serial.printf("%d bytes written",written);
if (Update.end()) {//updaet is done
if (Update.isFinished()) {
Serial.println(F("Update Successful... Restart"));
tft.setTextColor(TFT_BLACK,TFT_GREEN);
tft.drawCentreString("Update Successful... Restart",159,120,4);
beepbeep();
esp_ota_mark_app_valid_cancel_rollback();//prevent from boot old firmware
delay(1000);
ESP.restart();//restart
}
else {
Serial.println(F("Error! Update not finished"));
tft.setTextColor(TFT_WHITE,TFT_RED);
tft.drawCentreString("Error! Update not finished",159,120,4);
}
} else {//update stop during updating
Serial.println("Error Occurred. Error #: " + String(Update.getError()));
}
}//if update.begin
else
{
Serial.println(F("Not enough space to load firmware"));
tft.setTextColor(TFT_WHITE,TFT_RED);
tft.drawCentreString("Not enough space to upload!",159,120,4);
}
}
/*------------------*/
// check given FS for valid update.bin and perform update if available
void updateFromFS(fs::FS &fs) {
Serial.println(F("Loading firmware..."));
tft.setTextColor(TFT_WHITE,TFT_BLUE);
tft.drawCentreString("Loading firmware...",159,120,4);
File updateBin = fs.open(firmware_filename);
if (updateBin) {
if(updateBin.isDirectory()){
Serial.println(F("\"VaandCobOBD2Gauge.bin\" is not a file"));
tft.setTextColor(TFT_WHITE,TFT_RED);
tft.drawCentreString("\"VaandCobOBD2Gauge.bin\" is not a file",159,120,4);
updateBin.close();
return;
}
size_t updateSize = updateBin.size();
if (updateSize > 0) {
Serial.println(F("Updating... please wait"));
tft.setTextColor(TFT_WHITE,TFT_BLUE);
tft.drawCentreString("Updating... please wait",159,120,4);
performUpdate(updateBin, updateSize);
}
else {
Serial.println(F("Error! file is empty"));
tft.setTextColor(TFT_WHITE,TFT_RED);
tft.drawCentreString("Error! file is empty",159,120,4);
}
updateBin.close();
// whe finished remove the binary from sd card to indicate end of the process
//fs.remove(firmware_filename);
} else {
Serial.println(F("Firmware not found!"));
tft.pushImage(130,44,60,60,nofile);//show fileicon
tft.setTextColor(TFT_WHITE,TFT_RED);
tft.drawCentreString("Firmware not found!",159,120,4);
}
}
/*------------------*/
void updateFirmwareSD() {
tft.fillRect(0,30,320,239,TFT_BLACK);
tft.setTextColor(TFT_BLACK,TFT_WHITE);
tft.drawCentreString("[- Press button to exit -]",159,215,4);
if(!SD.begin()) {//sdcard not attach
Serial.println(F("Micro SD Card not mounted!"));
tft.pushImage(129,44,60,60,sdcard);//show sdcard icon
tft.setTextColor(TFT_WHITE,TFT_RED);
tft.drawCentreString("Please insert Micro SD Card",159,120,4);
} else {//sd card attached
Serial.println(F("Micro SD Card..OK"));
uint8_t cardType = SD.cardType();
if (cardType == CARD_NONE) {//bad card
Serial.println(F("Micro SD Card Error!"));
tft.setTextColor(TFT_WHITE,TFT_RED);
tft.drawCentreString("Micro SD Card Error!",159,120,4);
} else {//good sd card attached
updateFromFS(SD);//update firmware from sd card
}//else
}//else
SD.end();
beep();
}//updatefirmware
/*----------------*/

View file

@ -33,8 +33,8 @@ String pidList[maxpidIndex] =
uint8_t pidReadSkip[maxpidIndex] = {}; // skip reading 0 - 3; 3 = max delay read
uint8_t pidCurrentSkip[maxpidIndex] = {}; // current skip counter
uint8_t engine_off_count = 0; // counter to indicate engine is off then sleep
float old_data[maxpidIndex] = {-999, -999, -999, -999}; // keep old data
float last_valid_data[maxpidIndex] = {-999, -999, -999, -999}; // keep last valid data for instant redraw
float old_data[maxpidIndex] =
{}; // keep old data for each gauge to improve speed for pidIndex 0-6
// backlight variable average counter
uint8_t low_count = 0;
@ -52,7 +52,7 @@ void drawPidIcon(int x, int y, const String &pidStr) {
tft.pushImage(x, y, 24, 24, icon_speed, TFT_BLACK);
} else if (pidStr == "010C") {
tft.pushImage(x, y, 24, 24, icon_rpm, TFT_BLACK);
} else if (pidStr == "0142" || pidStr == "ATRV") {
} else if (pidStr == "0142") {
tft.pushImage(x, y, 24, 24, icon_battery, TFT_BLACK);
}
}
@ -65,7 +65,7 @@ void drawPidIconHeader(int x, int y, const String &pidStr) {
tft.pushImage(x, y, 42, 42, icon_speed_42, TFT_BLACK);
} else if (pidStr == "010C") {
tft.pushImage(x, y, 42, 42, icon_rpm_42, TFT_BLACK);
} else if (pidStr == "0142" || pidStr == "ATRV") {
} else if (pidStr == "0142") {
tft.pushImage(x, y, 42, 42, icon_battery_42, TFT_BLACK);
}
}
@ -671,13 +671,6 @@ void drawQuadHeaderGradient(uint8_t cell) {
tft.endWrite();
}
// Forward declarations
void plotNumeric4(uint8_t cell, float data, int warn, bool digit, String unit);
void plotArc4(uint8_t cell, float data, int warn, int min, int max, bool digit,
String unit);
void plotFullScreen(uint8_t cell, float data, int warn, int min, int max,
bool digit, String unit);
// 4-quadrant Numeric Meter (160x120 px)
void numericMeter4(uint8_t cell, uint8_t pid, bool redrawHeader = true) {
int w = 160;
@ -695,13 +688,6 @@ void numericMeter4(uint8_t cell, uint8_t pid, bool redrawHeader = true) {
// Clear only the body below the header to avoid any header flickering
tft.fillRect(x, y + 25, 160, 95, TFT_BLACK);
if (last_valid_data[cell] != -999) {
old_data[cell] = -999;
String unit = pidConfig[pid][1];
bool digit = pidConfig[pid][7].toInt();
int warn = warningValue[pid].toInt();
plotNumeric4(cell, last_valid_data[cell], warn, digit, unit);
} else {
// Initial placeholder: right-aligned DSEG7 44pt number
tft.loadFont(DSEG7_Modern_BoldItalic_44);
tft.setTextColor(TFT_GREEN, TFT_BLACK);
@ -709,7 +695,6 @@ void numericMeter4(uint8_t cell, uint8_t pid, bool redrawHeader = true) {
tft.drawRightString("---", x + w - 10, y + 46, 1);
tft.setTextPadding(0);
tft.unloadFont();
}
}
void plotNumeric4(uint8_t cell, float data, int warn, bool digit, String unit) {
@ -753,16 +738,6 @@ void arcMeter4(uint8_t cell, uint8_t pid, bool redrawHeader = true) {
drawQuadBarBlock(cell, i, TFT_DARKGREY);
}
int min = pidConfig[pid][4].toInt();
int max = pidConfig[pid][5].toInt();
bool digit = pidConfig[pid][7].toInt();
int warn = warningValue[pid].toInt();
String unit = pidConfig[pid][1];
if (last_valid_data[cell] != -999) {
old_data[cell] = -999;
plotArc4(cell, last_valid_data[cell], warn, min, max, digit, unit);
} else {
// Value placeholder using DSEG7 Modern 44pt smooth font
tft.loadFont(DSEG7_Modern_BoldItalic_44);
tft.setTextColor(TFT_GREEN, TFT_BLACK);
@ -771,7 +746,6 @@ void arcMeter4(uint8_t cell, uint8_t pid, bool redrawHeader = true) {
tft.setTextPadding(0);
tft.unloadFont();
old_data[cell] = -999;
}
}
void plotArc4(uint8_t cell, float data, int warn, int min, int max, bool digit,
@ -882,15 +856,6 @@ void fullScreenMeter(uint8_t cell, uint8_t pid, bool redrawHeader = true) {
// Clear only below header
tft.fillRect(0, 51, 320, 189, TFT_BLACK);
int min = pidConfig[pid][4].toInt();
int max = pidConfig[pid][5].toInt();
bool digit = pidConfig[pid][7].toInt();
int warn = warningValue[pid].toInt();
if (last_valid_data[cell] != -999) {
old_data[cell] = -999;
plotFullScreen(cell, last_valid_data[cell], warn, min, max, digit, unit);
} else {
if (!cellIsNumeric[cell]) {
// Exponential segmented block mode full screen (18 discrete blocks, 3mm x 5mm, 1mm gap)
for (uint8_t i = 0; i < NUM_BAR_BLOCKS; i++) {
@ -913,7 +878,6 @@ void fullScreenMeter(uint8_t cell, uint8_t pid, bool redrawHeader = true) {
tft.setTextPadding(0);
tft.unloadFont();
}
}
}
void plotFullScreen(uint8_t cell, float data, int warn, int min, int max,
@ -1010,89 +974,67 @@ void initScreen() {
/*-------------------------------*/
// get A B from response return in global A B variable
void getAB(String elm_rsp, String currentPid) { // 41 05 2A 3C 01>
void getAB(String elm_rsp) { // 41 05 2A 3C 01>
if (elm_rsp == "NO DATA\r\r>") { // pid no data
A = 0;
B = 0;
if (currentPid == "ATRV") {
return;
}
if (elm_rsp.indexOf("NO DATA") != -1 ||
elm_rsp.indexOf("UNABLE") != -1 ||
elm_rsp.indexOf("ERROR") != -1 ||
elm_rsp.indexOf("STOPPED") != -1) {
return;
}
// Normalize: replace carriage returns, newlines, and prompt chars with spaces
elm_rsp.replace('\r', ' ');
elm_rsp.replace('\n', ' ');
elm_rsp.replace('>', ' ');
// Extract expected PID hex byte (e.g. "0105" -> "05", "010C" -> "0C", "010D" -> "0D")
String pidByte = (currentPid.length() >= 4) ? currentPid.substring(2) : currentPid;
pidByte.toUpperCase();
// 1. Tokenized search: look for "41" followed by PID byte
String tokens[16];
uint8_t tokenCount = 0;
int startIdx = 0;
while (startIdx < elm_rsp.length() && tokenCount < 16) {
while (startIdx < elm_rsp.length() && elm_rsp.charAt(startIdx) == ' ') {
startIdx++;
}
if (startIdx >= elm_rsp.length()) break;
int endIdx = elm_rsp.indexOf(' ', startIdx);
if (endIdx == -1) endIdx = elm_rsp.length();
tokens[tokenCount++] = elm_rsp.substring(startIdx, endIdx);
startIdx = endIdx + 1;
}
for (uint8_t i = 0; i < tokenCount; i++) {
tokens[i].toUpperCase();
}
for (uint8_t i = 0; i + 1 < tokenCount; i++) {
if (tokens[i] == "41" && tokens[i + 1] == pidByte) {
if (i + 2 < tokenCount) {
A = strtol(tokens[i + 2].c_str(), NULL, 16);
}
if (i + 3 < tokenCount) {
B = strtol(tokens[i + 3].c_str(), NULL, 16);
}
return;
}
}
// 2. Compact string fallback (in case adapter sends responses without spaces, e.g. "410D32")
String compact = "";
for (int i = 0; i < elm_rsp.length(); i++) {
char c = elm_rsp.charAt(i);
if (c != ' ') compact += (char)toupper(c);
}
String targetPrefix = "41" + pidByte;
int fIdx = compact.indexOf(targetPrefix);
if (fIdx != -1) {
int dataIdx = fIdx + targetPrefix.length();
if (dataIdx + 2 <= compact.length()) {
A = strtol(compact.substring(dataIdx, dataIdx + 2).c_str(), NULL, 16);
}
if (dataIdx + 4 <= compact.length()) {
B = strtol(compact.substring(dataIdx + 2, dataIdx + 4).c_str(), NULL, 16);
}
return;
}
// 3. Positional fallback as in original author code
uint8_t charcnt = currentPid.length() / 2;
if (tokenCount > charcnt + 1) {
A = strtol(tokens[charcnt].c_str(), NULL, 16);
B = strtol(tokens[charcnt + 1].c_str(), NULL, 16);
} else if (tokenCount > charcnt) {
A = strtol(tokens[charcnt].c_str(), NULL, 16);
B = 0;
} else {
// check if pid is 2 or 3 command length.
uint8_t charcnt = pidList[pidIndex].length() / 2; // 0105->2,221E1C->3
String strs[8];
uint8_t StringCount = 0;
while (elm_rsp.length() > 0) { // keep reading each char
int index = elm_rsp.indexOf(' '); // check space
if (index == -1) // No space found
{ // only data without space is now in strs {41,05,aa,bb}
strs[StringCount++] = elm_rsp; // last byte
A = strtol(strs[charcnt].c_str(), NULL, 16); // byte 3 save to A
B = strtol(strs[charcnt + 1].c_str(), NULL, 16); // byte 4 save to B
break;
} else { // found space
strs[StringCount++] =
elm_rsp.substring(0, index); // copy strings from 0 to space to strs
elm_rsp = elm_rsp.substring(index +
1); // copy the rest behind space to elm_rsp
}
} // while
} // else
} // getAB
/*-------------------------------*/
// check engine status if off then turn off gauge
void engine_onoff(float data, uint8_t pid) { // use pcm volt
if (pidList[pid] == "0142") { // pcm voltage
if (data > 0.5 && data < ecu_off_volt)
engine_off_count++;
else if (data >= ecu_off_volt)
engine_off_count = 0; // reset
if (engine_off_count > 20) { // engine is stopped
if (pref.getUShort("layout", false) != layout) {
pref.putUShort("layout", layout);
}
show_spiffs_jpeg_image("/mypic.jpg", 0, 0);
ledcWriteTone(buzzerChannel, 3136);
delay(100);
ledcWriteTone(buzzerChannel, 2637);
delay(100);
ledcWriteTone(buzzerChannel, 2093);
delay(100);
ledcWriteTone(buzzerChannel, 0);
for (int i = 255; i > 0; i--) {
ledcWrite(backlightChannel, i);
delay(10);
}
BTSerial.print("ATLP\r");
BTSerial.disconnect();
tft.fillScreen(TFT_BLACK);
tft.writecommand(0x10); // TFT sleep
esp_sleep_enable_ext0_wakeup(GPIO_NUM_27, LOW);
esp_deep_sleep_start();
}
}
}
/*-------------------------------*/
void updateMeter(uint8_t pidNo, String response) { // update parameter on screen
if (pidNo >= maxpidIndex || pidNo >= 4)
return;
@ -1107,7 +1049,7 @@ void updateMeter(uint8_t pidNo, String response) { // update parameter on screen
bool digit = pidConfig[pidIdx][7].toInt();
int warn = warningValue[pidIdx].toInt();
getAB(response, pidList[pidNo]);
getAB(response);
float data = 0.0;
switch (formula) {
case 0:
@ -1128,36 +1070,22 @@ void updateMeter(uint8_t pidNo, String response) { // update parameter on screen
case 5:
data = (256 * A + B) / 16.0;
if (data > 150 || data < 0)
data = old_data[pidNo];
data = old_data[pidIndex];
break;
case 6:
data = (A * 256 + B) * 5 / 72 - 18;
if (data > 150 || data < 0)
data = old_data[pidNo];
data = old_data[pidIndex];
break;
case 7:
data = A; // km/h (PID 010D Vehicle Speed)
break;
case 8: {
// Battery Voltage from ELM327 command "ATRV" (e.g. "14.2V\r\r>")
String s = response;
s.trim();
int vIdx = s.indexOf('V');
if (vIdx == -1) vIdx = s.indexOf('v');
if (vIdx != -1) s = s.substring(0, vIdx);
int lastSpace = s.lastIndexOf(' ');
if (lastSpace != -1) s = s.substring(lastSpace + 1);
int lastCr = s.lastIndexOf('\r');
if (lastCr != -1) s = s.substring(lastCr + 1);
int lastLf = s.lastIndexOf('\n');
if (lastLf != -1) s = s.substring(lastLf + 1);
s.trim();
data = s.toFloat();
break;
}
}
last_valid_data[pidNo] = data;
// Engine off check if PCM volt
if (pidConfig[pidIdx][2] == "0142") {
engine_onoff(data, pidNo);
}
// Alarm warning audio alert
if (warn > 0 && data >= warn) {
@ -1181,62 +1109,37 @@ void updateMeter(uint8_t pidNo, String response) { // update parameter on screen
}
/*-------------------------------*/
// Target and current brightness variables for smooth fade
uint8_t targetBacklight = 255;
float currentBacklight = 255.0f;
uint32_t lastBacklightStepTime = 0;
void updateBacklightFade() {
uint32_t now = millis();
if (now - lastBacklightStepTime >= 15) { // every 15ms step
lastBacklightStepTime = now;
if (abs(currentBacklight - (float)targetBacklight) > 0.5f) {
if (currentBacklight < targetBacklight) {
currentBacklight += 3.0f;
if (currentBacklight > targetBacklight)
currentBacklight = targetBacklight;
} else {
currentBacklight -= 3.0f;
if (currentBacklight < targetBacklight)
currentBacklight = targetBacklight;
}
ledcWrite(backlightChannel, (uint32_t)currentBacklight);
}
}
}
// auto dim backlight function
void autoDim() {
int light = analogRead(LDR_PIN); // read light
if (light > LIGHT_LEVEL) { // low light (dark)
if (light > LIGHT_LEVEL) { // low light
low_count++;
if (low_count > 6) {
low_count = 6;
if (low_count > 10) {
low_count = 10; // low amb light 10 times count
if (!dim) {
targetBacklight = 50; // smooth fade target: dim
ledcWrite(backlightChannel, 50); // dim light
dim = true;
#ifdef SERIAL_DEBUG
Serial.println(F("Backlight -> target dim (50)"));
Serial.println(F("Backlight -> dim"));
#endif
}
}
} // if !dim
} // if low_count
high_count = 0;
} else { // bright light (day)
} else {
high_count++;
if (high_count > 6) {
high_count = 6;
if (high_count > 10) {
high_count = 10; // high amb light 10 times count
if (dim) {
targetBacklight = 255; // smooth fade target: bright
ledcWrite(backlightChannel, 255); // brightest
dim = false;
#ifdef SERIAL_DEBUG
Serial.println(F("Backlight -> target bright (255)"));
Serial.println(F("Backlight -> bright"));
#endif
}
}
} // if dim
} // if high_count
low_count = 0;
}
updateBacklightFade();
} // if light > lightlevel
} // autodim
//---------------------------
/*############################################*/

126
sketch/obd2_gauge/music.h Normal file
View file

@ -0,0 +1,126 @@
static const uint8_t song[18316] PROGMEM = {
0x56, 0x67, 0x6D, 0x20, 0x88, 0x47, 0x00, 0x00, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x46, 0x00, 0x00, 0x8F, 0xEE, 0x19, 0x00, 0xFB, 0x00, 0x00, 0x00, 0x37, 0xCC, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8C, 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, 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, 0x4C, 0x4F, 0x1B, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x30, 0xB4, 0x04, 0x30, 0xB4, 0x08, 0x30, 0xB4, 0x0C, 0x30, 0xB4, 0x10, 0x00, 0xB4, 0x15, 0x00, 0xB4, 0x17, 0xC0, 0xB4, 0x15, 0x0F, 0x70, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x01, 0x08, 0xB4, 0x02, 0x55, 0x70, 0xB4, 0x03, 0x03, 0x70, 0xB4, 0x04, 0xB0, 0x61, 0xA7, 0x05, 0xB4, 0x00, 0xBD, 0x61, 0xB6, 0x05, 0xB4, 0x00, 0xBB, 0x61, 0xC1, 0x05, 0xB4, 0x00, 0xB9, 0x61, 0xBC, 0x05, 0xB4, 0x00, 0xB7, 0x62, 0x73, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0xF9, 0x70, 0xB4, 0x03, 0x02, 0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x62, 0x71, 0xB4, 0x15, 0x0F, 0x72, 0xB4, 0x04, 0xB9, 0xB4, 0x05, 0x08, 0x70, 0xB4, 0x06, 0x55, 0xB4, 0x07, 0x03, 0x61, 0xCA, 0x02, 0xB4,
0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x56, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x01, 0x08, 0xB4, 0x02, 0xA6, 0x70, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xF9, 0xB4, 0x07, 0x02, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xFA, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x3A, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xA6, 0x70, 0xB4, 0x07, 0x02, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04,
0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xA7, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xAA, 0xB4, 0x03, 0x01, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x3A, 0x70, 0xB4, 0x07, 0x02, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x3B, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x7C, 0xB4, 0x03, 0x01, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xAA, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6,
0xB4, 0x06, 0xAB, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x52, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x7C, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x7D, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x1C, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x52, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x53, 0x62, 0xB4, 0x00, 0xB7, 0x62,
0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xD5, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x1C, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x1D, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xBE, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xD5, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xD6, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xA9, 0x70, 0xB4, 0x03, 0x00,
0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xBE, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xBF, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x8E, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xA9, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xAA, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x6A, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD,
0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x8E, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x8F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x5E, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x6A, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x6B, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x54, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4,
0x06, 0x5E, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x5F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x46, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x54, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x55, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x34, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x46, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00,
0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x47, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x46, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x34, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x35, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x54, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x46, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9,
0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x47, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x5E, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x54, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x55, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x6A, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x5E, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x5F, 0x61, 0xDE, 0x02,
0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x8E, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x6A, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x6B, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xA9, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x8E, 0xB4, 0x07, 0x00, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x8F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xBE,
0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xA9, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xAA, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xD5, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xBE, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xBF, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x1C, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD,
0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xD5, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xD6, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x52, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x1C, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x1D, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x7C, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4,
0x06, 0x52, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x53, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xAA, 0xB4, 0x03, 0x01, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x7C, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x7D, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x3A, 0x70, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xAA, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB,
0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xAB, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xA6, 0x70, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x3A, 0x70, 0xB4, 0x07, 0x02, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x3B, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xF9, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xA6, 0x70, 0xB4, 0x07, 0x02, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC,
0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xA7, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xF7, 0xB4, 0x03, 0x03, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB2, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0xF9, 0x70, 0xB4, 0x07, 0x02, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xFA, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x88, 0xB4, 0x03, 0x03, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xF7, 0xB4, 0x07, 0x03, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06,
0xF8, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x55, 0x70, 0xB4, 0x03, 0x03, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x88, 0xB4, 0x07, 0x03, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x89, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0xA6, 0x70, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x55, 0x70, 0xB4, 0x07, 0x03, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x56, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00,
0xBF, 0x70, 0xB4, 0x02, 0xFB, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xA6, 0x70, 0xB4, 0x07, 0x02, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xA7, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xC4, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0xFB, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xFC, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xAA, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04,
0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xC4, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xC5, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x52, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xAA, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xAB, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0xFD, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04,
0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x52, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x53, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xE1, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xFD, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xFE, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xD5, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xE1,
0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xE2, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xA9, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xD5, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xD6, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x7E, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xA9, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04,
0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xAA, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x7E, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x7F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x6A, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB2, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x70, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4,
0x04, 0xB6, 0x70, 0xB4, 0x06, 0x71, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x54, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x6A, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x6B, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x3E, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x54, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x55, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7,
0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x54, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x3E, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x3F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x6A, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x54, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x55, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x70, 0xB4, 0x03,
0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x6A, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x6B, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x7E, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x71, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xA9, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4,
0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x7E, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x7F, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0xD5, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xA9, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xAA, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xE1, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4,
0x06, 0xD5, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xD6, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xFD, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xE1, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xE2, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x52, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xFD, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB,
0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xFE, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xAA, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x52, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x53, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xC4, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xAA, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9,
0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xAB, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xFB, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xC4, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xC5, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xA6, 0xB4, 0x03, 0x02, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xFB, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xFC, 0x62, 0xB4, 0x00,
0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x55, 0x70, 0xB4, 0x03, 0x03, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xA6, 0xB4, 0x07, 0x02, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xA7, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x88, 0xB4, 0x03, 0x03, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x55, 0xB4, 0x07, 0x03, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x56, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x78, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02,
0x55, 0x70, 0xB4, 0x03, 0x03, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB0, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x88, 0x70, 0xB4, 0x07, 0x03, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x89, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xF9, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x76, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x55, 0xB4, 0x07, 0x03, 0x61, 0xCC, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x56, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xA6, 0xB4, 0x03, 0x02, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4,
0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xF9, 0xB4, 0x07, 0x02, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xFA, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x3A, 0x70, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xA6, 0xB4, 0x07, 0x02, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xA7, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xAA, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04,
0xB9, 0x70, 0xB4, 0x06, 0x3A, 0x70, 0xB4, 0x07, 0x02, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x3B, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x7C, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xAA, 0xB4, 0x07, 0x01, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xAB, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x52, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x7C, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02,
0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x7D, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x1C, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x52, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x53, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0xD5, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x1C, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00,
0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x1D, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xBE, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0xD5, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xD6, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xA9, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0xBE, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06,
0xBF, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x8E, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xA9, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xAA, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x6A, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x8E, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x8F, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4,
0x02, 0x5E, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x6A, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x6B, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x54, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x5E, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x5F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x46, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5,
0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x54, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x55, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x34, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x46, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x47, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x46, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4,
0x04, 0xB9, 0x70, 0xB4, 0x06, 0x34, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x35, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x54, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x46, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x47, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x5E, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x54, 0x70, 0xB4, 0x07,
0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x55, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x6A, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x5E, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x5F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x8E, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x6A, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7,
0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x6B, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xA9, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x8E, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x8F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xBE, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xA9, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4,
0x04, 0xB6, 0x70, 0xB4, 0x06, 0xAA, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xD5, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xBE, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xBF, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x1C, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xD5, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xD6, 0x62, 0xB4, 0x00, 0xB7, 0x62,
0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x52, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x1C, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x1D, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x7C, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x52, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x53, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xAA, 0xB4, 0x03, 0x01, 0x70,
0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x7C, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x7D, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x3A, 0xB4, 0x03, 0x02, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB2, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0xAA, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xAB, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xA6, 0xB4, 0x03, 0x02, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4,
0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x3A, 0xB4, 0x07, 0x02, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x3B, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xF9, 0x70, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xA6, 0xB4, 0x07, 0x02, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xA7, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xF7, 0xB4, 0x03, 0x03, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06,
0xF9, 0xB4, 0x07, 0x02, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xFA, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x88, 0xB4, 0x03, 0x03, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0xF7, 0x70, 0xB4, 0x07, 0x03, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xF8, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x55, 0xB4, 0x03, 0x03, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x88, 0x70, 0xB4, 0x07, 0x03, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74,
0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x89, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xA6, 0xB4, 0x03, 0x02, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x55, 0xB4, 0x07, 0x03, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x56, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xFB, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xA6, 0xB4, 0x07, 0x02, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4,
0x04, 0xB6, 0x70, 0xB4, 0x06, 0xA7, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0xC4, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xFB, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xFC, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xAA, 0xB4, 0x03, 0x01, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB2, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xC4, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xC5, 0x62, 0xB4, 0x00,
0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x52, 0xB4, 0x03, 0x01, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xAA, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xAB, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xFD, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x52, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x53, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xE1, 0x70, 0xB4, 0x03,
0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xFD, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xFE, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xD5, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xE1, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xE2, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xA9, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD,
0x71, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xD5, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xD6, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x7E, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xA9, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xAA, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x70, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x7E,
0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x7F, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x6A, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x71, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x54, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x6A, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62,
0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x6B, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x3E, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x54, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x55, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x54, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x3E, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02,
0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x3F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x6A, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x54, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x55, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x6A, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x6B, 0x62, 0xB4,
0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x7E, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x70, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x71, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xA9, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x7E, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x7F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xD5, 0x70, 0xB4,
0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xA9, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xAA, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0xE1, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xD5, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xD6, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xFD, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71,
0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0xE1, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xE2, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x52, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0xFD, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xFE, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xAA, 0xB4, 0x03, 0x01, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x52,
0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x53, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0xC4, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xAA, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xAB, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0xFB, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xC4, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62,
0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xC5, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xA6, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xFB, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xFC, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x55, 0xB4, 0x03, 0x03, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0xA6, 0x70, 0xB4, 0x07, 0x02, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61,
0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xA7, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x88, 0x70, 0xB4, 0x03, 0x03, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x55, 0xB4, 0x07, 0x03, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x56, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xF7, 0x70, 0xB4, 0x03, 0x03, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB2, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x88, 0x70, 0xB4, 0x07, 0x03, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x89, 0x61, 0xDE,
0x02, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x55, 0xB4, 0x03, 0x03, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xF7, 0x70, 0xB4, 0x07, 0x03, 0x61, 0xCC, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xF8, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x80, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x55, 0xB4, 0x07, 0x03, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x56, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4,
0x02, 0x3A, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x80, 0xB4, 0x07, 0x02, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x81, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xFB, 0xB4, 0x03, 0x01, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x3A, 0xB4, 0x07, 0x02, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x3B, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xAA, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00,
0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xFB, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xFC, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x3F, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0xAA, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xAB, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x1C, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06,
0x3F, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x40, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xFD, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x1C, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x1D, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0xD5, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xFD, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75,
0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xFE, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x9F, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xD5, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xD6, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x8E, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x9F, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00,
0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xA0, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x7E, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x8E, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x8F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x6A, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x7E, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x7F, 0x62,
0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x4F, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x6A, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x6B, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x46, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x4F, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x50, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70,
0xB4, 0x02, 0x3E, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x46, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x47, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x46, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x3E, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x3F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x4F, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61,
0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x46, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x47, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x6A, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x4F, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x50, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x7E, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62,
0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x6A, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x6B, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x8E, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x7E, 0xB4, 0x07, 0x00, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x7F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x9F, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x8E, 0xB4, 0x07, 0x00,
0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x8F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xD5, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x9F, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xA0, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xFD, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xD5, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC,
0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xD6, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x1C, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0xFD, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xFE, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x3F, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x1C, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06,
0x1D, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xAA, 0xB4, 0x03, 0x01, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x3F, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x40, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0xFB, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xAA, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xAB, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4,
0x02, 0x3A, 0x70, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xFB, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xFC, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x80, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x3A, 0x70, 0xB4, 0x07, 0x02, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x3B, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x55, 0xB4, 0x03, 0x03, 0x70, 0xB4, 0x04, 0xB5,
0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x80, 0x70, 0xB4, 0x07, 0x02, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x81, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x88, 0x70, 0xB4, 0x03, 0x03, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x55, 0xB4, 0x07, 0x03, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x56, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0xF9, 0x70, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4,
0x04, 0xB9, 0x70, 0xB4, 0x06, 0x88, 0x70, 0xB4, 0x07, 0x03, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x89, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x3A, 0x70, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xF9, 0x70, 0xB4, 0x07, 0x02, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xFA, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xFB, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x3A, 0x70, 0xB4,
0x07, 0x02, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x3B, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xC4, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xFB, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xFC, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x7C, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xC4, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04,
0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xC5, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x1C, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x7C, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x7D, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xFD, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x1C, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02,
0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x1D, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xE1, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0xFD, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xFE, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xBE, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xE1, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xE2, 0x62, 0xB4, 0x00, 0xB7, 0x62,
0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x8E, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xBE, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xBF, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x7E, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x8E, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x8F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x70, 0xB4,
0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x7E, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x7F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x5E, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x70, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x71, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x46, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD,
0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x5E, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x5F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x3E, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x46, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x47, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x38, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70,
0xB4, 0x06, 0x3E, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x3F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x3E, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x38, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x39, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x46, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x3E, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4,
0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x3F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x5E, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x46, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x47, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x5E, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61,
0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x5F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x7E, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x70, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x71, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x8E, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x7E, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x7F, 0x62, 0xB4, 0x00,
0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xBE, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x8E, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x8F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0xE1, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xBE, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xBF, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0xFD, 0x70, 0xB4,
0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xE1, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xE2, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x1C, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xFD, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xFE, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x7C, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4,
0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x1C, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x1D, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xC4, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x7C, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x7D, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xFB, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70,
0xB4, 0x06, 0xC4, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xC5, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x3A, 0x70, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xFB, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xFC, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xF9, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x3A, 0x70, 0xB4, 0x07, 0x02, 0x61,
0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x3B, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x34, 0x70, 0xB4, 0x03, 0x04, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xF9, 0xB4, 0x07, 0x02, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xFA, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x55, 0x70, 0xB4, 0x03, 0x03, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x34, 0xB4, 0x07, 0x04, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61,
0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x35, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xCE, 0x70, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x55, 0x70, 0xB4, 0x07, 0x03, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x56, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x3A, 0x70, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xCE, 0x70, 0xB4, 0x07, 0x02, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04,
0xB6, 0x70, 0xB4, 0x06, 0xCF, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x19, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x3A, 0x70, 0xB4, 0x07, 0x02, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x3B, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xAA, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x19, 0xB4, 0x07, 0x02, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x1A, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75,
0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x67, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xAA, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xAB, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x1C, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x67, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x68, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x0C, 0xB4, 0x03,
0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x1C, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x1D, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xD5, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB2, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x0C, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x0D, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xB3, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD,
0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xD5, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xD6, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x8E, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xB3, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xB4, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x86, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70,
0xB4, 0x06, 0x8E, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x8F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x6A, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x86, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x87, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x59, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x6A, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4,
0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x6B, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x46, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x59, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x5A, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x42, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x46, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9,
0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x47, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x46, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x42, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x43, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x59, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x46, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06,
0x47, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x6A, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x59, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x5A, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x86, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x6A, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x6B, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x8E, 0x70,
0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x86, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x87, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xB3, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x8E, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x8F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xD5, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05,
0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0xB3, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xB4, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x0C, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xD5, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xD6, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x1C, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04,
0xB9, 0x70, 0xB4, 0x06, 0x0C, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x0D, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x67, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x1C, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x1D, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xAA, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x67, 0x70, 0xB4, 0x07, 0x01, 0x61,
0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x68, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x19, 0xB4, 0x03, 0x02, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0xAA, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xAB, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x3A, 0xB4, 0x03, 0x02, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x19, 0xB4, 0x07, 0x02, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02,
0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x1A, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xCE, 0x70, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x3A, 0xB4, 0x07, 0x02, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x3B, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x55, 0x70, 0xB4, 0x03, 0x03, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xCE, 0x70, 0xB4, 0x07, 0x02, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6,
0x70, 0xB4, 0x06, 0xCF, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xBE, 0xB4, 0x03, 0x03, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB2, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x55, 0x70, 0xB4, 0x07, 0x03, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x56, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xF9, 0x70, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xBE, 0xB4, 0x07, 0x03, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xBF, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4,
0x00, 0xBF, 0x70, 0xB4, 0x02, 0x80, 0x70, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xF9, 0xB4, 0x07, 0x02, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xFA, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xFB, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x80, 0xB4, 0x07, 0x02, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x81, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xDE, 0xB4, 0x03, 0x01, 0x70, 0xB4,
0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xFB, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xFC, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x7C, 0xB4, 0x03, 0x01, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB2, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0xDE, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xDF, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x3F, 0xB4, 0x03, 0x01, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4,
0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x7C, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x7D, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xFD, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x3F, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x40, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0xEF, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xFD, 0xB4,
0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xFE, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xBE, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xEF, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xF0, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x9F, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xBE, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4,
0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xBF, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x7E, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x9F, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xA0, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x77, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x7E, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04,
0xB6, 0x70, 0xB4, 0x06, 0x7F, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x77, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x5E, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x77, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x78, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x4F, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x5E, 0xB4, 0x07, 0x00, 0x61, 0xCD, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x5F, 0x62, 0xB4, 0x00, 0xB7,
0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x3E, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x4F, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x50, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x3B, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x3E, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x3F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x3E, 0x70, 0xB4, 0x03, 0x00, 0x70,
0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x3B, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x3C, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x4F, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x3E, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x3F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x5E, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4,
0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0x4F, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x50, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x77, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x5E, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0x5F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x7E, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x77,
0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x78, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x9F, 0x70, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x7E, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x7F, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xBE, 0xB4, 0x03, 0x00, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x9F, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB,
0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xA0, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xEF, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0xB4, 0x06, 0xBE, 0x70, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xBF, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xFD, 0xB4, 0x03, 0x00, 0x71, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x73, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xEF, 0xB4, 0x07, 0x00, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC,
0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xF0, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x3F, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xFD, 0xB4, 0x07, 0x00, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xFE, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0xB4, 0x02, 0x7C, 0x70, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x3F, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x40, 0x62,
0xB4, 0x00, 0xB7, 0x62, 0x76, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xDE, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB3, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x7C, 0x70, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x7D, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xFB, 0xB4, 0x03, 0x01, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB5, 0x05, 0xB4, 0x00, 0xBD, 0x70, 0xB4, 0x04, 0xB4, 0x62, 0x74, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xDE, 0xB4, 0x07, 0x01, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDD, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xDF, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x80,
0x70, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xFB, 0xB4, 0x07, 0x01, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x74, 0xB4, 0x04, 0xB7, 0x61, 0xDD, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0xB4, 0x06, 0xFC, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xF9, 0x70, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0x80, 0xB4, 0x07, 0x02, 0x61, 0xCF, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0x81, 0x61, 0xDE, 0x02, 0xB4, 0x00, 0xB7, 0x62, 0x7A, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0x55, 0x70, 0xB4, 0x03, 0x03, 0x70, 0xB4, 0x04, 0xB5, 0x61,
0xAF, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x72, 0xB4, 0x04, 0xB9, 0x70, 0xB4, 0x06, 0xF9, 0x70, 0xB4, 0x07, 0x02, 0x61, 0xCE, 0x02, 0xB4, 0x00, 0xBB, 0x62, 0x75, 0xB4, 0x04, 0xB7, 0x61, 0xDC, 0x02, 0xB4, 0x00, 0xB9, 0x61, 0xDC, 0x02, 0xB4, 0x04, 0xB6, 0x70, 0xB4, 0x06, 0xFA, 0x62, 0xB4, 0x00, 0xB7, 0x62, 0x75, 0xB4, 0x00, 0xBF, 0x70, 0xB4, 0x02, 0xF9, 0xB4, 0x03, 0x02, 0x70, 0xB4, 0x04, 0xB5, 0x61, 0xB4, 0x05, 0xB4, 0x00, 0xBD, 0x71, 0xB4, 0x04, 0xB4, 0x62, 0x75, 0x66, 0x47, 0x64, 0x33, 0x20, 0x00, 0x01, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, 0x50, 0x00, 0x72, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x75, 0x00, 0x64, 0x00, 0x65, 0x00, 0x00, 0x00, 0xD7, 0x30, 0xEC, 0x30, 0xEA, 0x30, 0xE5, 0x30, 0xFC, 0x30, 0xC9, 0x30, 0x00, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x61, 0x00, 0x6C, 0x00, 0x20, 0x00, 0x46, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x74, 0x00, 0x61, 0x00, 0x73, 0x00, 0x79, 0x00,
0x20, 0x00, 0x49, 0x00, 0x49, 0x00, 0x00, 0x00, 0xD5, 0x30, 0xA1, 0x30, 0xA4, 0x30, 0xCA, 0x30, 0xEB, 0x30, 0xD5, 0x30, 0xA1, 0x30, 0xF3, 0x30, 0xBF, 0x30, 0xB8, 0x30, 0xFC, 0x30, 0x49, 0x00, 0x49, 0x00, 0x00, 0x00, 0x46, 0x00, 0x61, 0x00, 0x6D, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x79, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x6D, 0x00, 0x70, 0x00, 0x75, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0xD5, 0x30, 0xA1, 0x30, 0xDF, 0x30, 0xEA, 0x30, 0xFC, 0x30, 0xB3, 0x30, 0xF3, 0x30, 0xD4, 0x30, 0xE5, 0x30, 0xFC, 0x30, 0xBF, 0x30, 0x00, 0x00, 0x4E, 0x00, 0x6F, 0x00, 0x62, 0x00, 0x75, 0x00, 0x6F, 0x00, 0x20, 0x00, 0x55, 0x00, 0x65, 0x00, 0x6D, 0x00, 0x61, 0x00, 0x74, 0x00, 0x73, 0x00, 0x75, 0x00, 0x00, 0x00, 0x0D, 0x69, 0x7E, 0x67, 0x38, 0x4F, 0x2B, 0x59, 0x00, 0x00, 0x31, 0x00, 0x39, 0x00, 0x38, 0x00, 0x38, 0x00, 0x2D, 0x00, 0x31, 0x00, 0x32, 0x00, 0x2D, 0x00, 0x31, 0x00, 0x37, 0x00,
0x00, 0x00, 0x32, 0x00, 0x63, 0x00, 0x68, 0x00, 0x2D, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
};

View file

@ -0,0 +1,710 @@
#include "nes_audio.h"
static void (*fc_callback)();
Cartridge::Cartridge(uint8_t audio_pin) {
single_output = audio_pin;//only single 1 pin use
}
void Cartridge::frame_counter_cb(void (*action)()){
fc_callback = action;
}
void Cartridge::init(){//call for 4 channel use only
sigmaDeltaSetup(p1_pin, p1_channel, 88200);
sigmaDeltaWrite(p1_channel, 0);
sigmaDeltaSetup(p2_pin, p2_channel, 88200);
sigmaDeltaWrite(p2_channel, 0);
sigmaDeltaSetup(n_pin, n_channel, 88200);
sigmaDeltaWrite(n_channel, 0);
sigmaDeltaSetup(t_pin, t_channel, 88200);
sigmaDeltaWrite(t_channel, 0);
}
void Cartridge::play_nes(const uint8_t* music, bool looping, float volume){
NES_PLAYING = true;//variable to control playback
read_vgm_header(music);
next_cycle = ESP.getCycleCount();
next_audio = ESP.getCycleCount();
while (NES_PLAYING) {
uint32_t t_now = ESP.getCycleCount();
if (t_last > t_now) {
next_cycle = t_now;
next_audio = t_now;
}
if (t_now >= next_cycle) {
next_cycle += cycle_period;
clock_apu();
}
if (t_now >= next_audio) {
next_audio += audio_period;
parse_vgm(music, looping);
audio_counter++;
if (audio_counter >= audio_divisor) {
audio_counter = 0;
sample_audio();
render_audio(volume);
}
}
t_last = t_now;
// if (digitalRead(27) == LOW) NES_PLAYING = false;//button press then stop
}//while nes playing
}
void Cartridge::parse_vgm(const uint8_t* music, bool looping){
uint8_t extra = 0;
if (vgm_wait == 0) {
uint8_t command = music[vgm_index];
if (command == 0x61) { // Wait nL nH samples
uint16_t result = music[vgm_index + 2];
result = result << 8;
result += music[vgm_index + 1];
vgm_wait = result;
extra = 2;
}
else if (command == 0x62) { // Wait 735 samples
vgm_wait = 735;
}
else if (command == 0x63) { // Wait 882 samples
vgm_wait = 882;
}
else if (command == 0x67 && music[vgm_index + 1] == 0x66) { // Start of data block
uint32_t block_size = (music[vgm_index + 3] ) +
(music[vgm_index + 4] << 8) +
(music[vgm_index + 5] << 16) +
(music[vgm_index + 6] << 24);
vgm_index += block_size - 1; // Basically ignore all data block contents
}
else if (command == 0x66 || vgm_index == VGM_EOF_OFFSET){
Serial.println("END");
if(looping) {
if(VGM_LOOP_OFFSET == 0) { // Loop offset is not built into file
vgm_index = VGM_DATA_OFFSET - 1; // Restart the song entirely
}
else {
vgm_index = VGM_LOOP_OFFSET - 1; // Music loops, reset to looping byte
}
}
else {
reset_nes(); // Reset if loop opt-out
}
}
else if (command >= 0x70 && command < 0x80) { // Wait (0x7)n+1 samples
uint8_t result = command;
result = result << 4;
result = result >> 4;
vgm_wait = result + 1;
}
else if (command == 0xB4) { // NES APU write dd to aa
uint8_t value = music[vgm_index + 2];
uint8_t reg = music[vgm_index + 1];
write_reg(reg, value);
extra = 2;
}
vgm_index += 1;
vgm_index += extra;
}
else {
vgm_wait--;
}
}
void Cartridge::read_vgm_header(const uint8_t* music){
VGM_EOF_OFFSET = get_32_bit(music, 0x04) + 0x04;
VGM_TOTAL_NUM_SAMPLES = get_32_bit(music, 0x18);
VGM_RATE = get_32_bit(music, 0x24);
VGM_DATA_OFFSET = get_32_bit(music, 0x34) + 0x34;
VGM_NES_APU_CLOCK = get_32_bit(music, 0x84);
VGM_LOOP_OFFSET = get_32_bit(music, 0x1C) + 0x1C;
vgm_index = VGM_DATA_OFFSET;
}
uint32_t Cartridge::get_32_bit(const uint8_t* music, uint32_t index){
uint32_t result = music[index + 3];
result = result << 8;
result += music[index + 2];
result = result << 8;
result += music[index + 1];
result = result << 8;
result += music[index];
return result;
}
void Cartridge::reset_nes(){
for (uint8_t i = 0; i < 24; i++) {
NES_REG[i] = B00000000;
}
single_output = 0;
// Pulse 1 Variables
p1_output = 0;
p1_11_bit_timer = 0;
p1_wave_index = 0;
p1_length_counter = 0;
p1_envelope_divider = 0;
p1_decay_counter = 0;
p1_volume = 0;
p1_channel = 0;
// Pulse 2 Variables
p2_output = 0;
p2_11_bit_timer = 0;
p2_wave_index = 0;
p2_length_counter = 0;
p2_envelope_divider = 0;
p2_decay_counter = 0;
p2_volume = 0;
p2_channel = 1;
// Noise Variables
n_output = 0;
n_timer = 0;
n_length_counter = 0;
n_envelope_divider = 0;
n_decay_counter = 0;
n_volume = 0;
n_xor = 0;
n_lsfr = 1;
n_channel = 2;
// Triangle Variables
t_output = 0;
t_11_bit_timer = 0;
t_wave_index = 0;
t_length_counter = 0;
t_linear_counter = 0;
t_channel = 3;
vgm_index = 0;
vgm_wait = 0;
NES_PLAYING = false;
next_audio = 0;
next_cycle = 0;
cpu_cycles = 0;
apu_cycles = 0;
t_last = 0;
audio_counter = 0;
}
void Cartridge::sample_audio(){
// Pulse 1
if (p1_length_counter > 0) {
if (p1_11_bit_timer >= 8) {
p1_output = p1_volume * duty_table[get_duty(0x00)][p1_wave_index];
}
}
else {
p1_output = 0;
}
// Pulse 2
if (p2_length_counter > 0) {
if (p2_11_bit_timer >= 8) {
p2_output = p2_volume * duty_table[get_duty(0x04)][p2_wave_index];
}
}
else {
p2_output = 0;
}
// Noise
if (n_length_counter > 0) {
n_output = n_volume * n_xor;
}
else {
n_output = 0;
}
// Triangle
if (t_length_counter > 0) {
t_output = tri_table[t_wave_index];
}
else {
t_output = 0;
}
}
void Cartridge::render_audio(float gain){
// four channel
/*
sigmaDeltaWrite(p1_channel, p1_output * 12);
sigmaDeltaWrite(p2_channel, p2_output * 12);
sigmaDeltaWrite(n_channel, n_output * 6);
sigmaDeltaWrite(t_channel, t_output * 16);
*/
// single channel
uint8_t sum = 0;
sum+=p1_output*0.8;
sum+=p2_output*0.8;
sum+=n_output*0.7;
sum+=t_output;
//sigmaDeltaWrite(t_pin,sum);
dacWrite(single_output,sum * gain);//gain volume to 0.5 or can be to 1.5
}
void Cartridge::clock_apu(){
clock_frame_counter();
decrement_timers();
apu_cycles += 2;
}
void Cartridge::decrement_timers(){
// Pulse 1
if (p1_11_bit_timer <= 0) {
p1_11_bit_timer = get_11_bit_timer(0x02, 0x03);
if (p1_wave_index == 0) {
p1_wave_index = 7;
}
else {
p1_wave_index--;
}
}
else {
p1_11_bit_timer -= 2;
}
// Pulse 2
if (p2_11_bit_timer <= 0) {
p2_11_bit_timer = get_11_bit_timer(0x06, 0x07);
if (p2_wave_index == 0) {
p2_wave_index = 7;
}
else {
p2_wave_index--;
}
}
else {
p2_11_bit_timer -= 2;
}
// Noise
if (n_timer <= 0) {
uint8_t index = get_reg(0x0E);
index = index << 4;
index = index >> 4;
n_timer = noise_table[index];
clock_lsfr();
}
else {
n_timer -= 2;
}
// Triangle
if (t_11_bit_timer <= 0) {
t_11_bit_timer = get_11_bit_timer(0x0A, 0x0B) + 1;
if (t_length_counter > 0 && t_linear_counter > 0) {
if (t_wave_index == 0) {
t_wave_index = 31;
}
else {
t_wave_index--;
}
}
}
else {
t_11_bit_timer -= 2;
t_11_bit_timer -= 2; // Triangle timer clocked on CPU not APU (2x speed)
}
}
void Cartridge::clock_lsfr(){
uint8_t bit1 = 0;
uint8_t bit2 = 1;
if (get_bit(0x0E, 7) == 1) {
bit2 = 6;
}
uint8_t val1 = bitRead(n_lsfr, bit1);
uint8_t val2 = bitRead(n_lsfr, bit2);
n_xor = val1 ^ val2;
n_lsfr = n_lsfr >> 1;
bitWrite(n_lsfr, 14, n_xor);
}
void Cartridge::clock_frame_counter(){
if (frame_counter_mode() == 0) { // 4-step sequence
if (apu_cycles == 3728) {
clock_envelopes();
clock_linear_counter();
if (fc_callback)
fc_callback();
}
else if (apu_cycles == 7456) {
clock_envelopes();
clock_linear_counter();
clock_length_counters();
clock_sweep_units();
}
else if (apu_cycles == 11186) {
clock_envelopes();
clock_linear_counter();
}
else if (apu_cycles == 14914) {
clock_envelopes();
clock_linear_counter();
clock_length_counters();
clock_sweep_units();
apu_cycles = 0;
}
}
else if (frame_counter_mode() == 1) { // 5-step sequence
if (apu_cycles == 3728) {
clock_envelopes();
clock_linear_counter();
if (fc_callback)
fc_callback();
}
else if (apu_cycles == 7456) {
clock_envelopes();
clock_linear_counter();
clock_length_counters();
clock_sweep_units();
}
else if (apu_cycles == 11186) {
clock_envelopes();
clock_linear_counter();
}
else if (apu_cycles == 18640) {
clock_envelopes();
clock_linear_counter();
clock_length_counters();
clock_sweep_units();
apu_cycles = 0;
}
}
}
uint8_t Cartridge::frame_counter_mode(){
return get_bit(0x17, 7);
}
uint8_t Cartridge::get_bit(uint8_t reg, uint8_t b){
return bitRead(get_reg(reg), b);
}
void Cartridge::write_bit(uint8_t reg, uint8_t b, uint8_t val){
uint8_t r = get_reg(reg);
bitWrite(r, b, val);
write_reg(reg, r); // used to make sure conditions defined in write_reg() are used here also
}
uint8_t Cartridge::get_reg(uint8_t reg){
return NES_REG[reg];
}
void Cartridge::write_reg(uint8_t reg, uint8_t val){
// PULSE 1 ----------------------------------------
if (reg == 0x03) {
// Pulse 1 load length counter from table address
uint8_t level = bitRead(val, 3);
uint8_t index = val >> 4;
p1_length_counter = length_table[level][index];
p1_wave_index = 0;
p1_decay_counter = 15;
p1_envelope_divider = 0;
}
else if (reg == 0x15) {
// Pulse 1
if (bitRead(val, 0) == 0) { // if p1 enabled bit clear, empty length counter
write_length_counter(0x03, 0);
}
//clear DMC interrupt flag
}
// PULSE 2 ----------------------------------------
if (reg == 0x07) {
// Pulse 2 load length counter from table address
uint8_t level = bitRead(val, 3);
uint8_t index = val >> 4;
p2_length_counter = length_table[level][index];
p2_wave_index = 0;
p2_decay_counter = 15;
p2_envelope_divider = 0;
}
else if (reg == 0x15) {
// Pulse 2
if (bitRead(val, 1) == 0) { // if p2 enabled bit clear, empty length counter
write_length_counter(0x07, 0);
}
//clear DMC interrupt flag
}
// NOISE ----------------------------------------
if (reg == 0x0F) {
// Noise load length counter from table address
uint8_t level = bitRead(val, 3);
uint8_t index = val >> 4;
n_length_counter = length_table[level][index];
n_decay_counter = 15;
n_envelope_divider = 0;
}
else if (reg == 0x15) {
// Noise
if (bitRead(val, 3) == 0) { // if noise enabled bit clear, empty length counter
write_length_counter(0x0F, 0);
}
//clear DMC interrupt flag
}
// TRIANGLE ----------------------------------------
if (reg == 0x0B) {
// Triangle load length counter from table address
uint8_t level = bitRead(val, 3);
uint8_t index = val >> 4;
t_length_counter = length_table[level][index];
// Triangle load linear counter from register
uint8_t linc = get_reg(0x08);
linc = linc << 1;
linc = linc >> 1;
t_linear_counter = linc;
write_bit(0x08, 7, 1);
}
else if (reg == 0x15) {
//clear DMC interrupt flag
}
NES_REG[reg] = val;
}
void Cartridge::clock_envelopes(){
// Pulse 1
uint8_t p1_envelope_disable = bitRead(get_reg(0x00), 4);
if (p1_envelope_disable) {
uint8_t v = get_reg(0x00);
v = v << 4;
v = v >> 4;
p1_volume = v;
}
else {
uint8_t p1_envelope_loop = bitRead(get_reg(0x00), 5);
if (p1_envelope_divider > 0) {
p1_envelope_divider--;
}
else {
uint8_t d = get_reg(0x00);
d = d << 4;
d = d >> 4;
p1_envelope_divider = d;
//clock decay counter
if (p1_decay_counter > 0) {
p1_decay_counter--;
}
else {
if (p1_envelope_loop == 1) {
p1_decay_counter = 15;
}
}
}
p1_volume = p1_decay_counter;
}
// Pulse 2
uint8_t p2_envelope_disable = bitRead(get_reg(0x04), 4);
if (p2_envelope_disable) {
uint8_t v = get_reg(0x04);
v = v << 4;
v = v >> 4;
p2_volume = v;
}
else {
uint8_t p2_envelope_loop = bitRead(get_reg(0x04), 5);
if (p2_envelope_divider > 0) {
p2_envelope_divider--;
}
else {
uint8_t d = get_reg(0x04);
d = d << 4;
d = d >> 4;
p2_envelope_divider = d;
//clock decay counter
if (p2_decay_counter > 0) {
p2_decay_counter--;
}
else {
if (p2_envelope_loop == 1) {
p2_decay_counter = 15;
}
}
}
p2_volume = p2_decay_counter;
}
// Noise
uint8_t n_envelope_disable = bitRead(get_reg(0x0C), 4);
if (n_envelope_disable) {
uint8_t v = get_reg(0x0C);
v = v << 4;
v = v >> 4;
n_volume = v;
}
else {
uint8_t n_envelope_loop = bitRead(get_reg(0x0C), 5);
if (n_envelope_divider > 0) {
n_envelope_divider--;
}
else {
uint8_t d = get_reg(0x0C);
d = d << 4;
d = d >> 4;
n_envelope_divider = d;
//clock decay counter
if (n_decay_counter > 0) {
n_decay_counter--;
}
else {
if (n_envelope_loop == 1) {
n_decay_counter = 15;
}
}
}
n_volume = n_decay_counter;
}
}
void Cartridge::clock_linear_counter(){
if (get_bit(0x08, 7) == 1) {
if (t_linear_counter > 0) {
t_linear_counter--;
}
}
}
void Cartridge::clock_length_counters(){
uint8_t length_counter_halt_flag = 0;
// Pulse 1
length_counter_halt_flag = get_bit(0x00, 5);
if (length_counter_halt_flag == 0) { // Pulse 1 halt flag not set? decrement length counter
if (p1_length_counter > 0) {
p1_length_counter--;
}
}
// Pulse 2
length_counter_halt_flag = get_bit(0x04, 5);
if (length_counter_halt_flag == 0) { // Pulse 2 halt flag not set? decrement length counter
if (p2_length_counter > 0) {
p2_length_counter--;
}
}
// Noise
length_counter_halt_flag = get_bit(0x0C, 5);
if (length_counter_halt_flag == 0) { // Noise halt flag not set? decrement length counter
if (n_length_counter > 0) {
n_length_counter--;
}
}
// Triangle
length_counter_halt_flag = get_bit(0x08, 7);
if (length_counter_halt_flag == 0) { // Triangle halt flag not set? decrement length counter
if (t_length_counter > 0) {
t_length_counter--;
}
}
}
uint8_t Cartridge::get_duty(uint8_t reg){
uint8_t r = get_reg(reg);
r = r >> 6;
return r;
}
uint16_t Cartridge::get_11_bit_timer(uint8_t reg_low, uint8_t reg_high){
uint8_t rlow = get_reg(reg_low);
uint8_t rhigh = get_reg(reg_high);
rhigh = rhigh << 5;
rhigh = rhigh >> 5;
uint16_t r16 = rhigh;
r16 = r16 << 8;
r16 = r16 + rlow;
return r16;
}
void Cartridge::set_11_bit_timer(uint8_t reg_low, uint8_t reg_high, uint16_t val){
uint16_t out_low = val;
out_low = out_low << 8;
out_low = out_low >> 8;
uint8_t ol = out_low;
uint16_t out_high = val;
out_high = out_high >> 8;
uint8_t oh = out_high;
uint8_t r_high = get_reg(reg_high);
uint16_t val_high = r_high;
val_high = val_high >> 3;
val_high = val_high << 3;
val_high = val_high + oh;
write_reg(reg_low, ol);
write_reg(reg_high, val_high);
}
uint8_t Cartridge::get_length_counter(uint8_t reg){
uint8_t r = get_reg(reg);
r = r >> 3;
return r;
}
uint8_t Cartridge::write_length_counter(uint8_t reg, uint8_t val){
uint8_t r = get_reg(reg);
r = r << 5;
r = r >> 5;
val = val << 3;
uint8_t result = r + val;
write_reg(reg, result);
return result;
}
void Cartridge::clock_sweep_units(){
}

View file

@ -0,0 +1,187 @@
/*
https://github.com/connornishijima/Cartridge
Cartridge.cpp - Library for parsing VGM into an NES APU emulation!
Created by Connor Nishijima, October 14th 2018.
Released under the GPLv3 license.
*/
#ifndef cartridge_h
#define cartridge_h
#include "Arduino.h"
class Cartridge
{
public:
Cartridge(uint8_t audio_pin);
void init();
void play_nes(const uint8_t* music, bool looping = false, float volume = 1.0);
void frame_counter_cb(void (*action)());
private:
void parse_vgm(const uint8_t* music, bool looping);
void read_vgm_header(const uint8_t* music);
uint32_t get_32_bit(const uint8_t* music, uint32_t index);
void reset_nes();
void sample_audio();
void render_audio(float gain);
void clock_apu();
void decrement_timers();
void clock_lsfr();
void clock_frame_counter();
uint8_t frame_counter_mode();
uint8_t get_bit(uint8_t reg, uint8_t b);
void write_bit(uint8_t reg, uint8_t b, uint8_t val);
uint8_t get_reg(uint8_t reg);
void write_reg(uint8_t reg, uint8_t val);
void clock_envelopes();
void clock_linear_counter();
void clock_length_counters();
uint8_t get_duty(uint8_t reg);
uint16_t get_11_bit_timer(uint8_t reg_low, uint8_t reg_high);
void set_11_bit_timer(uint8_t reg_low, uint8_t reg_high, uint16_t val);
uint8_t get_length_counter(uint8_t reg);
uint8_t write_length_counter(uint8_t reg, uint8_t val);
void clock_sweep_units();
uint8_t NES_REG[24] = {
// PULSE 1
B00000000, // $4000
B00000000, // $4001
B00000000, // $4002
B00000000, // $4003
// PULSE 2
B00000000, // $4004
B00000000, // $4005
B00000000, // $4006
B00000000, // $4007
// TRIANGLE
B00000000, // $4008
B00000000, // $4009 (UNUSED)
B00000000, // $400A
B00000000, // $400B
// NOISE
B00000000, // $400C
B00000000, // $400E
B00000000, // $400F
// DMC
B00000000, // $4010
B00000000, // $4011
B00000000, // $4012
B00000000, // $4013
B00000000, // $4014 (UNUSED)
// Control/Status
B00000000, // $4015
B00000000, // $4016 (UNUSED)
// Frame Counter
B00000000, // $4017
};
const uint32_t NES_APU_FREQ = 1789773 / 2 / 2; // APU is half speed of NES CPU, and we are running half the resolution of that to stay light.
const uint32_t cycle_period = F_CPU / NES_APU_FREQ;
const uint16_t audio_rate = 44100;
const uint32_t audio_period = F_CPU / audio_rate;
uint32_t next_audio = 0;
uint32_t next_cycle = 0;
uint32_t cpu_cycles = 0;
uint32_t apu_cycles = 0;
uint32_t t_last = 0;
uint32_t cycles_delta = 0;
uint32_t cycles_so_far = 0;
const uint8_t audio_divisor = 2;
uint8_t audio_counter = 0;
const uint8_t length_table[2][16] = {
{0x0A, 0x14, 0x28, 0x50, 0xA0, 0x3C, 0x0E, 0x1A, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x48, 0x10, 0x20},
{0xFE, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E}
};
const uint8_t duty_table[4][8] = {
{0, 0, 0, 0, 0, 0, 0, 1}, // 12.5%
{0, 0, 0, 0, 0, 0, 1, 1}, // 25%
{0, 0, 0, 0, 1, 1, 1, 1}, // 50%
{1, 1, 1, 1, 1, 1, 0, 0}, // 25% (inv.)
};
const uint16_t noise_table[16] = {
4, 8, 16, 32, 64, 96, 128, 160, 202, 254, 380, 508, 762, 1016, 2034, 4068
};
const uint8_t tri_table[32] = {
15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};
uint8_t single_output = 0;
// Pulse 1 Variables
uint8_t p1_output = 0;
int16_t p1_11_bit_timer = 0;
uint8_t p1_wave_index = 0;
uint16_t p1_length_counter = 0;
uint8_t p1_envelope_divider = 0;
uint8_t p1_decay_counter = 0;
uint8_t p1_volume = 0;
uint8_t p1_channel = 0;
uint8_t p1_pin = 12;
// Pulse 2 Variables
uint8_t p2_output = 0;
int16_t p2_11_bit_timer = 0;
uint8_t p2_wave_index = 0;
uint16_t p2_length_counter = 0;
uint8_t p2_envelope_divider = 0;
uint8_t p2_decay_counter = 0;
uint8_t p2_volume = 0;
uint8_t p2_channel = 1;
uint8_t p2_pin = 14;
// Noise Variables
uint8_t n_output = 0;
int16_t n_timer = 0;
uint16_t n_length_counter = 0;
uint8_t n_envelope_divider = 0;
uint8_t n_decay_counter = 0;
uint8_t n_volume = 0;
uint8_t n_xor = 0;
uint16_t n_lsfr = 1;
uint8_t n_channel = 2;
uint8_t n_pin = 27;
// Triangle Variables
uint8_t t_output = 0;
int16_t t_11_bit_timer = 0;
uint8_t t_wave_index = 0;
uint16_t t_length_counter = 0;
uint16_t t_linear_counter = 0;
uint8_t t_channel = 3;
uint8_t t_pin = 26;
uint32_t vgm_index = 0;
uint16_t vgm_wait = 0;
bool NES_PLAYING = false;
uint32_t VGM_EOF_OFFSET = 0;
uint32_t VGM_TOTAL_NUM_SAMPLES = 0;
uint32_t VGM_RATE = 0;
uint32_t VGM_DATA_OFFSET = 0;
uint32_t VGM_NES_APU_CLOCK = 0;
uint32_t VGM_LOOP_OFFSET = 0;
};
#endif

View file

@ -120,11 +120,21 @@ const uint32_t SLEEP_DURATION = 180 * 1000000; //180 sec
String line[12] = { "", "", "", "", "", "", "", "", "", "", "", "" }; //buffer for each line in terminal function
bool dim = false; //back light dim flag
const uint8_t LIGHT_LEVEL = 40; //backlight control by light level Higher = darker light
long runtime = 0; //to check FPS
long holdtime = 0; //hold time for button pressed check
const String compile_date = __DATE__ " - " __TIME__; //get built date and time
bool press = false; // button press flag
bool showsystem = false; //show fps and temp EEPROM 0x01
uint8_t pidRead = 0; //counter that hold number of pids been read to check pid/sec
String serial_no = ""; //keep serial no.
//CPU Temp
const uint8_t tempOverheat = 60; //max operating cpu temp 60c
const int8_t factoryTempOffset = -50; //default offset adjustment temp up to each tested esp32 max at -50
float tempRead = 0.0; //current reading cpu temp
int8_t tempOffset = 0; //offset adjustment temp up to each tested esp32
uint8_t temp_read_delay = 0; //hold delay counter to read temp
uint8_t temp_overheat_count = 0; //counter to read continuiosly overheat
//BLUETOOTH
String bt_message = ""; //bluetooth message buffer
@ -150,7 +160,43 @@ XPT2046_TouchscreenSOFTSPI ts(XPT2046_CS);
/*----------- global function ---------*/
//------------------------------------------------------------------------------------------
void checkCPUTemp() { //temperature can read only when BT or Wifi Connected
temp_read_delay++;
if ((temp_read_delay >= 50) && (foundOBD2)) { //delay loop 50 then read temp, avoid error eading
temp_read_delay = 0;
uint8_t temperature = temprature_sens_read(); //read internal temp sensor
tempRead = (temperature - 32) / 1.8 + tempOffset; //change unit F to C
#ifdef SERIAL_DEBUG
Serial.print(tempRead, 1); //print Celsius temperature and tab
Serial.println("°c");
#endif
//read 10 times to confirm it's really overtemp.
if (tempRead >= tempOverheat) temp_overheat_count++; //count overheat time
else temp_overheat_count = 0; //reset
if (temp_overheat_count > 10) { //overheat read more than 10 times.
Serial.printf("CPU Overheat Shutdown at %d°C\n", tempOverheat);
tft.fillRectVGradient(0, 0, 320, 240, TFT_RED, TFT_BLACK);
tft.pushImage(127, 5, 64, 64, overheat, TFT_RED); //show sdcard icon
tft.setTextColor(TFT_WHITE);
tft.drawCentreString("CPU Overheat Shutdown!", 159, 75, 4);
tft.setTextColor(TFT_WHITE, TFT_BLUE);
tft.drawCentreString("Auto-restart within 3 minutes", 159, 140, 4);
tft.drawCentreString("OR", 159, 170, 4);
tft.drawCentreString("Press button to restart", 159, 200, 4);
ledcWriteTone(buzzerChannel, 1500);
delay(5000);
ledcWriteTone(buzzerChannel, 0);
BTSerial.disconnect(); //disconnect bluetooth
tft.fillScreen(TFT_BLACK);
tft.writecommand(0x10); //TFT sleep
//enter deep sleep
esp_sleep_enable_timer_wakeup(SLEEP_DURATION); //sleep timer 3 min
esp_sleep_enable_ext0_wakeup(GPIO_NUM_27, LOW); //wake when button pressed
esp_deep_sleep_start(); //sleep shutdown backlight auto off with esp32
} //if temp_overheat_coun
} //if temp_read_delay
} //check CPU Temp
/*------------------*/
//TERMINAL terminal for debugging display text
void Terminal(String texts, uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
@ -284,10 +330,17 @@ recent_client_addr : {0x00,0x00,0x00,0x00,0x00,0x00} array of bytes[6]
}*/
layout = 0;
pref.putUShort("layout", 0);
showsystem = pref.getBool("showsystem", false); //load showsytem
tempOffset = pref.getInt("tempOffset", factoryTempOffset); //load defaultTempoffset
#ifdef SERIAL_DEBUG
Serial.printf("Show System: %d\n", showsystem);
Serial.printf("Temp Offset: %d\n", tempOffset);
#endif
for (uint8_t i = 0; i < maxpidIndex; i++) { //read warning value from pid name if not found load from default
warningValue[i] = pref.getString(pidConfig[i][0].c_str(), pidConfig[i][8]);
}
pref.getBytes("recent_client", recent_client_addr, pref.getBytesLength("recent_client")); //read last bt address
ecu_off_volt = pref.getFloat("ecu_off_volt", factoryECUOff); //read ecu 0ff voltage
//start bluetooth
@ -299,7 +352,7 @@ recent_client_addr : {0x00,0x00,0x00,0x00,0x00,0x00} array of bytes[6]
Serial.println(F("Bluetooth..OK"));
Terminal("Bluetooth..OK", 0, 48, 320, 191);
}
runtime = millis();
#ifdef SKIP_CONNECTION
foundOBD2 = true;
#endif
@ -309,7 +362,7 @@ recent_client_addr : {0x00,0x00,0x00,0x00,0x00,0x00} array of bytes[6]
while (!foundOBD2) { //not success try scan and connect another OBD2
scanBTdevice();
autoDim(); //auto backlight handle
//checkCPUTemp(); //check temp never work if BT or WIFI not connected
if (digitalRead(SELECTOR_PIN) == LOW) { //button pressed
if (!press) {
press = true; //set flag
@ -355,8 +408,6 @@ recent_client_addr : {0x00,0x00,0x00,0x00,0x00,0x00} array of bytes[6]
/*###################################*/
void loop() {
updateBacklightFade(); // non-blocking smooth backlight fade handler
// SCAN TOUCHSCREEN & BUTTON
// - Single click on a quadrant: toggles between clock (arc) and number
// - Double click on a quadrant: puts that instrument in full screen (or exits full screen)
@ -442,6 +493,7 @@ void loop() {
// In full screen: single click toggles between arc and number mode without header flicker
cellIsNumeric[fullScreenCell] = !cellIsNumeric[fullScreenCell];
fullScreenMeter(fullScreenCell, pidInCell[fullScreenCell], false);
old_data[fullScreenCell] = -999;
} else if (clickQuadrant >= 0 && clickQuadrant < 4) {
// In 4 quadrants: single click toggles between arc and number for this quadrant without header flicker
cellIsNumeric[clickQuadrant] = !cellIsNumeric[clickQuadrant];
@ -451,22 +503,11 @@ void loop() {
} else {
arcMeter4(clickQuadrant, pid, false);
}
old_data[clickQuadrant] = -999;
}
}
//----------------------
//BLUETOOTH read
static uint32_t lastPidSendTime = 0;
// Watchdog: If waiting for prompt for more than 6000ms (standard OBD2 maximum ECU timeout), recover!
if (!prompt && (millis() - lastPidSendTime > 6000)) {
#ifdef SERIAL_DEBUG
Serial.printf("PID timeout for %s, recovering...\n", pidList[pidIndex].c_str());
#endif
BTSerial.flush();
bt_message = "";
prompt = true;
skip = true;
}
while (BTSerial.available() > 0) {
char incomingChar = BTSerial.read();
if (incomingChar == '>') { //check prompt
@ -475,7 +516,7 @@ void loop() {
Serial.println(bt_message);
#endif
#ifdef TERMINAL //for degbugging
getAB(bt_message, pidList[pidIndex]);
getAB(bt_message);
Terminal(bt_message + "->" + String(A) + "," + String(B), 0, 48, 320, 191);
#endif
prompt = true; //pid response ready to calculate & display
@ -508,19 +549,27 @@ void loop() {
//Send another PID to elm327
if (prompt) { //> ELM327 ready! -> request next PID
prompt = false; //no prompt from ELM327
checkCPUTemp(); //check temperature.
if (!skip) {
updateMeter(pidIndex, bt_message); //update meter screen
pidRead++; //for calculate pid/s
}
pidIndex++; //point to next pid
if (pidIndex >= maxpidIndex) {
pidIndex = 0; //back to pid 0
autoDim(); //auto backlight handle
if (showsystem && fullScreenCell == -1) {
String status = String(pidRead * 1000.0 / (millis() - runtime), 0) + " p/s " + String(tempRead, 1) + "`c";
tft.setTextColor(TFT_YELLOW, TFT_BLACK);
tft.drawCentreString(status.c_str(), 159, 0, 2);
runtime = millis();
} //if showsystem
pidRead = 0; //reset pid read counter
}
if (pidCurrentSkip[pidIndex] <= 0) { //end of skip loop , go next index
pidCurrentSkip[pidIndex] = pidReadSkip[pidIndex]; //read max delay loop to current
skip = false;
BTSerial.print(pidList[pidIndex] + "\r"); //send PID request
lastPidSendTime = millis();
} else { //skip sending request
pidCurrentSkip[pidIndex] = pidCurrentSkip[pidIndex] - 1; //decrese loop count
prompt = true;