#include "stm32_sam.h"
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////
//
//           All
//
////////////////////////////////////////////////////////////////////////////////////////////

char input[256 + 1] = {0}; //tab39445
//standard sam sound

unsigned char wait1 = 7;
unsigned char wait2 = 6;

unsigned char A, X, Y;
unsigned char mem44;
unsigned char mem47;
unsigned char mem49;
unsigned char mem39;
unsigned char mem50;
unsigned char mem51;
unsigned char mem53;
unsigned char mem56;
unsigned char mem59 = 0;

unsigned char phonemeIndexOutput[60]; //tab47296
unsigned char stressOutput[60]; //tab47365
unsigned char phonemeLengthOutput[60]; //tab47416

// contains the soundbuffer position
int bufferpos;

////////////////////////////////////////////////////////////////////////////////////////////
//
//           Sam Tabs
//
////////////////////////////////////////////////////////////////////////////////////////////

//tab40672
const unsigned char stressInputTable[] = {'*', '1', '2', '3', '4', '5', '6', '7', '8'};

//tab40682
const unsigned char signInputTable1[] = {
    ' ', '.', '?', ',', '-', 'I', 'I', 'E', 'A', 'A', 'A', 'A', 'U', 'A', 'I', 'E', 'U',
    'O', 'R', 'L', 'W', 'Y', 'W', 'R', 'L', 'W', 'Y', 'M', 'N', 'N', 'D', 'Q', 'S', 'S',
    'F', 'T', '/', '/', 'Z', 'Z', 'V', 'D', 'C', '*', 'J', '*', '*', '*', 'E', 'A', 'O',
    'A', 'O', 'U', 'B', '*', '*', 'D', '*', '*', 'G', '*', '*', 'G', '*', '*', 'P', '*',
    '*', 'T', '*', '*', 'K', '*', '*', 'K', '*', '*', 'U', 'U', 'U'};

//tab40763
const unsigned char signInputTable2[] = {
    '*', '*', '*', '*', '*', 'Y', 'H', 'H', 'E', 'A', 'H', 'O', 'H', 'X', 'X', 'R', 'X',
    'H', 'X', 'X', 'X', 'X', 'H', '*', '*', '*', '*', '*', '*', 'X', 'X', '*', '*', 'H',
    '*', 'H', 'H', 'X', '*', 'H', '*', 'H', 'H', '*', '*', '*', '*', '*', 'Y', 'Y', 'Y',
    'W', 'W', 'W', '*', '*', '*', '*', '*', '*', '*', '*', '*', 'X', '*', '*', '*', '*',
    '*', '*', '*', '*', '*', '*', '*', 'X', '*', '*', 'L', 'M', 'N'};

//loc_9F8C
const unsigned char flags[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x84, 0x84, 0xA4,
    0xA4, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x44, 0x44, 0x44, 0x44, 0x44, 0x4C,
    0x4C, 0x4C, 0x48, 0x4C, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x44, 0x44, 0x44,
    0x48, 0x40, 0x4C, 0x44, 0x00, 0x00, 0xB4, 0xB4, 0xB4, 0x94, 0x94, 0x94, 0x4E, 0x4E,
    0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4B, 0x4B, 0x4B, 0x4B,
    0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x80, 0xC1, 0xC1

};

//??? flags overlap flags2
//loc_9FDA
const unsigned char flags2[] = {
    0x80, 0xC1, 0xC1, 0xC1, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0C, 0x08, 0x04, 0x40,
    0x24, 0x20, 0x20, 0x24, 0x00, 0x00, 0x24, 0x20, 0x20, 0x24, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

//tab45616???
const unsigned char phonemeStressedLengthTable[] = {
    0x00, 0x12, 0x12, 0x12, 8,   0xB, 9,   0xB, 0xE, 0xF, 0xB, 0x10, 0xC, 6, 6, 0xE,
    0xC,  0xE,  0xC,  0xB,  8,   8,   0xB, 0xA, 9,   8,   8,   8,    8,   8, 3, 5,
    2,    2,    2,    2,    2,   2,   6,   6,   8,   6,   6,   2,    9,   4, 2, 1,
    0xE,  0xF,  0xF,  0xF,  0xE, 0xE, 8,   2,   2,   7,   2,   1,    7,   2, 2, 7,
    2,    2,    8,    2,    2,   6,   2,   2,   7,   2,   4,   7,    1,   4, 5, 5};

//tab45536???
const unsigned char phonemeLengthTable[] = {
    0, 0x12, 0x12, 0x12, 8, 8, 8, 8,    8,   0xB, 6,   0xC, 0xA, 5, 5, 0xB, 0xA, 0xA, 0xA,  9,
    8, 7,    9,    7,    6, 8, 6, 7,    7,   7,   2,   5,   2,   2, 2, 2,   2,   2,   6,    6,
    7, 6,    6,    2,    8, 3, 1, 0x1E, 0xD, 0xC, 0xC, 0xC, 0xE, 9, 6, 1,   2,   5,   1,    1,
    6, 1,    2,    6,    1, 2, 8, 2,    2,   4,   2,   2,   6,   1, 4, 6,   1,   4,   0xC7, 0xFF};

/*

  Ind  | phoneme |  flags   |
  -----|---------|----------|
  0    |   *     | 00000000 |
  1    |  .*     | 00000000 |
  2    |  ?*     | 00000000 |
  3    |  ,*     | 00000000 |
  4    |  -*     | 00000000 |

  VOWELS
  5    |  IY     | 10100100 |
  6    |  IH     | 10100100 |
  7    |  EH     | 10100100 |
  8    |  AE     | 10100100 |
  9    |  AA     | 10100100 |
  10   |  AH     | 10100100 |
  11   |  AO     | 10000100 |
  17   |  OH     | 10000100 |
  12   |  UH     | 10000100 |
  16   |  UX     | 10000100 |
  15   |  ER     | 10000100 |
  13   |  AX     | 10100100 |
  14   |  IX     | 10100100 |

  DIPHTONGS
  48   |  EY     | 10110100 |
  49   |  AY     | 10110100 |
  50   |  OY     | 10110100 |
  51   |  AW     | 10010100 |
  52   |  OW     | 10010100 |
  53   |  UW     | 10010100 |


  21   |  YX     | 10000100 |
  20   |  WX     | 10000100 |
  18   |  RX     | 10000100 |
  19   |  LX     | 10000100 |
  37   |  /X     | 01000000 |
  30   |  DX     | 01001000 |


  22   |  WH     | 01000100 |


  VOICED CONSONANTS
  23   |  R*     | 01000100 |
  24   |  L*     | 01000100 |
  25   |  W*     | 01000100 |
  26   |  Y*     | 01000100 |
  27   |  M*     | 01001100 |
  28   |  N*     | 01001100 |
  29   |  NX     | 01001100 |
  54   |  B*     | 01001110 |
  57   |  D*     | 01001110 |
  60   |  G*     | 01001110 |
  44   |  J*     | 01001100 |
  38   |  Z*     | 01000100 |
  39   |  ZH     | 01000100 |
  40   |  V*     | 01000100 |
  41   |  DH     | 01000100 |

  unvoiced CONSONANTS
  32   |  S*     | 01000000 |
  33   |  SH     | 01000000 |
  34   |  F*     | 01000000 |
  35   |  TH     | 01000000 |
  66   |  P*     | 01001011 |
  69   |  T*     | 01001011 |
  72   |  K*     | 01001011 |
  42   |  CH     | 01001000 |
  36   |  /H     | 01000000 |

  43   |  **     | 01000000 |
  45   |  **     | 01000100 |
  46   |  **     | 00000000 |
  47   |  **     | 00000000 |


  55   |  **     | 01001110 |
  56   |  **     | 01001110 |
  58   |  **     | 01001110 |
  59   |  **     | 01001110 |
  61   |  **     | 01001110 |
  62   |  **     | 01001110 |
  63   |  GX     | 01001110 |
  64   |  **     | 01001110 |
  65   |  **     | 01001110 |
  67   |  **     | 01001011 |
  68   |  **     | 01001011 |
  70   |  **     | 01001011 |
  71   |  **     | 01001011 |
  73   |  **     | 01001011 |
  74   |  **     | 01001011 |
  75   |  KX     | 01001011 |
  76   |  **     | 01001011 |
  77   |  **     | 01001011 |


  SPECIAL
  78   |  UL     | 10000000 |
  79   |  UM     | 11000001 |
  80   |  UN     | 11000001 |
  31   |  Q*     | 01001100 |

*/

////////////////////////////////////////////////////////////////////////////////////////////
//
//           RenderTabs
//
////////////////////////////////////////////////////////////////////////////////////////////

const unsigned char tab48426[5] = {0x18, 0x1A, 0x17, 0x17, 0x17};

const unsigned char tab47492[] = {0, 0, 0xE0, 0xE6, 0xEC, 0xF3, 0xF9, 0, 6, 0xC, 6};

const unsigned char amplitudeRescale[] = {
    0,
    1,
    2,
    2,
    2,
    3,
    3,
    4,
    4,
    5,
    6,
    8,
    9,
    0xB,
    0xD,
    0xF,
    0 //17 elements?
};

// Used to decide which phoneme's blend lengths. The candidate with the lower score is selected.
// tab45856
const unsigned char blendRank[] = {0,    0x1F, 0x1F, 0x1F, 0x1F, 2,    2,    2,    2,    2,
                                   2,    2,    2,    2,    5,    5,    2,    0xA,  2,    8,
                                   5,    5,    0xB,  0xA,  9,    8,    8,    0xA0, 8,    8,
                                   0x17, 0x1F, 0x12, 0x12, 0x12, 0x12, 0x1E, 0x1E, 0x14, 0x14,
                                   0x14, 0x14, 0x17, 0x17, 0x1A, 0x1A, 0x1D, 0x1D, 2,    2,
                                   2,    2,    2,    2,    0x1A, 0x1D, 0x1B, 0x1A, 0x1D, 0x1B,
                                   0x1A, 0x1D, 0x1B, 0x1A, 0x1D, 0x1B, 0x17, 0x1D, 0x17, 0x17,
                                   0x1D, 0x17, 0x17, 0x1D, 0x17, 0x17, 0x1D, 0x17, 0x17, 0x17};

// Number of frames at the end of a phoneme devoted to interpolating to next phoneme's final value
//tab45696
const unsigned char outBlendLength[] = {0, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,    4,
                                        4, 4, 3, 2, 4, 4, 2, 2, 2, 2, 2, 1, 1, 1, 1,    1,
                                        1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 0, 1, 0, 1, 0,    5,
                                        5, 5, 5, 5, 4, 4, 2, 0, 1, 2, 0, 1, 2, 0, 1,    2,
                                        0, 1, 2, 0, 2, 2, 0, 1, 3, 0, 2, 3, 0, 2, 0xA0, 0xA0};

// Number of frames at beginning of a phoneme devoted to interpolating to phoneme's final value
// tab45776
const unsigned char inBlendLength[] = {0, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,    4,
                                       4, 4, 3, 3, 4, 4, 3, 3, 3, 3, 3, 1, 2, 3, 2,    1,
                                       3, 3, 3, 3, 1, 1, 3, 3, 3, 2, 2, 3, 2, 3, 0,    0,
                                       5, 5, 5, 5, 4, 4, 2, 0, 2, 2, 0, 3, 2, 0, 4,    2,
                                       0, 3, 2, 0, 2, 2, 0, 2, 3, 0, 3, 3, 0, 3, 0xB0, 0xA0};

// Looks like it's used as bit flags
// High bits masked by 248 (11111000)
//
// 32: S*    241         11110001
// 33: SH    226         11100010
// 34: F*    211         11010011
// 35: TH    187         10111011
// 36: /H    124         01111100
// 37: /X    149         10010101
// 38: Z*    1           00000001
// 39: ZH    2           00000010
// 40: V*    3           00000011
// 41: DH    3           00000011
// 43: **    114         01110010
// 45: **    2           00000010
// 67: **    27          00011011
// 70: **    25          00011001
// tab45936
const unsigned char sampledConsonantFlags[] = {
    0, 0, 0, 0,    0, 0, 0, 0,    0, 0, 0,    0, 0,    0,    0,    0,    0,    0,    0, 0,
    0, 0, 0, 0,    0, 0, 0, 0,    0, 0, 0,    0, 0xF1, 0xE2, 0xD3, 0xBB, 0x7C, 0x95, 1, 2,
    3, 3, 0, 0x72, 0, 2, 0, 0,    0, 0, 0,    0, 0,    0,    0,    0,    0,    0,    0, 0,
    0, 0, 0, 0,    0, 0, 0, 0x1B, 0, 0, 0x19, 0, 0,    0,    0,    0,    0,    0,    0, 0};

//tab45056
unsigned char freq1data[] = {
    0x00, 0x13, 0x13, 0x13, 0x13, 0xA,  0xE, 0x12, 0x18, 0x1A, 0x16, 0x14, 0x10, 0x14, 0xE,  0x12,
    0xE,  0x12, 0x12, 0x10, 0xC,  0xE,  0xA, 0x12, 0xE,  0xA,  8,    6,    6,    6,    6,    0x11,
    6,    6,    6,    6,    0xE,  0x10, 9,   0xA,  8,    0xA,  6,    6,    6,    5,    6,    0,
    0x12, 0x1A, 0x14, 0x1A, 0x12, 0xC,  6,   6,    6,    6,    6,    6,    6,    6,    6,    6,
    6,    6,    6,    6,    6,    6,    6,   6,    6,    0xA,  0xA,  6,    6,    6,    0x2C, 0x13};

//tab451356
unsigned char freq2data[] = {0x00, 0x43, 0x43, 0x43, 0x43, 0x54, 0x48, 0x42, 0x3E, 0x28,
                             0x2C, 0x1E, 0x24, 0x2C, 0x48, 0x30, 0x24, 0x1E, 0x32, 0x24,
                             0x1C, 0x44, 0x18, 0x32, 0x1E, 0x18, 0x52, 0x2E, 0x36, 0x56,
                             0x36, 0x43, 0x49, 0x4F, 0x1A, 0x42, 0x49, 0x25, 0x33, 0x42,
                             0x28, 0x2F, 0x4F, 0x4F, 0x42, 0x4F, 0x6E, 0x00, 0x48, 0x26,
                             0x1E, 0x2A, 0x1E, 0x22, 0x1A, 0x1A, 0x1A, 0x42, 0x42, 0x42,
                             0x6E, 0x6E, 0x6E, 0x54, 0x54, 0x54, 0x1A, 0x1A, 0x1A, 0x42,
                             0x42, 0x42, 0x6D, 0x56, 0x6D, 0x54, 0x54, 0x54, 0x7F, 0x7F};
//tab45216
unsigned char freq3data[] = {0x00, 0x5B, 0x5B, 0x5B, 0x5B, 0x6E, 0x5D, 0x5B, 0x58, 0x59,
                             0x57, 0x58, 0x52, 0x59, 0x5D, 0x3E, 0x52, 0x58, 0x3E, 0x6E,
                             0x50, 0x5D, 0x5A, 0x3C, 0x6E, 0x5A, 0x6E, 0x51, 0x79, 0x65,
                             0x79, 0x5B, 0x63, 0x6A, 0x51, 0x79, 0x5D, 0x52, 0x5D, 0x67,
                             0x4C, 0x5D, 0x65, 0x65, 0x79, 0x65, 0x79, 0x00, 0x5A, 0x58,
                             0x58, 0x58, 0x58, 0x52, 0x51, 0x51, 0x51, 0x79, 0x79, 0x79,
                             0x70, 0x6E, 0x6E, 0x5E, 0x5E, 0x5E, 0x51, 0x51, 0x51, 0x79,
                             0x79, 0x79, 0x65, 0x65, 0x70, 0x5E, 0x5E, 0x5E, 0x08, 0x01};

////////////////////////////////////////////////////////////////////////////////////////////
//
//           Reciter
//
////////////////////////////////////////////////////////////////////////////////////////////

unsigned char inputtemp[256]; // secure copy of input tab36096

////////////////////////////////////////////////////////////////////////////////////////////
//
//           Render
//
////////////////////////////////////////////////////////////////////////////////////////////

//timetable for more accurate c64 simulation
int timetable[5][5] = {
    {162, 167, 167, 127, 128},
    {226, 60, 60, 0, 0},
    {225, 60, 59, 0, 0},
    {200, 0, 0, 54, 55},
    {199, 0, 0, 54, 54}};

unsigned oldtimetableindex;

const unsigned char ampl1data[] = {0,   0,   0,   0,   0,   0xD, 0xD, 0xE, 0xF, 0xF, 0xF, 0xF,
                                   0xF, 0xC, 0xD, 0xC, 0xF, 0xF, 0xD, 0xD, 0xD, 0xE, 0xD, 0xC,
                                   0xD, 0xD, 0xD, 0xC, 9,   9,   0,   0,   0,   0,   0,   0,
                                   0,   0,   0xB, 0xB, 0xB, 0xB, 0,   0,   1,   0xB, 0,   2,
                                   0xE, 0xF, 0xF, 0xF, 0xF, 0xD, 2,   4,   0,   2,   4,   0,
                                   1,   4,   0,   1,   4,   0,   0,   0,   0,   0,   0,   0,
                                   0,   0xC, 0,   0,   0,   0,   0xF, 0xF};

const unsigned char ampl2data[] = {
    0, 0,   0, 0,   0, 0xA, 0xB, 0xD, 0xE, 0xD, 0xC, 0xC, 0xB, 9,   0xB, 0xB, 0xC, 0xC, 0xC, 8,
    8, 0xC, 8, 0xA, 8, 8,   0xA, 3,   9,   6,   0,   0,   0,   0,   0,   0,   0,   0,   3,   5,
    3, 4,   0, 0,   0, 5,   0xA, 2,   0xE, 0xD, 0xC, 0xD, 0xC, 8,   0,   1,   0,   0,   1,   0,
    0, 1,   0, 0,   1, 0,   0,   0,   0,   0,   0,   0,   0,   0xA, 0,   0,   0xA, 0,   0,   0};

const unsigned char ampl3data[] = {0, 0, 0, 0, 0, 8, 7, 8, 8, 1, 1, 0, 1, 0, 7,    5,
                                   1, 0, 6, 1, 0, 7, 0, 5, 1, 0, 8, 0, 0, 3, 0,    0,
                                   0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0xE,  1,
                                   9, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    0,
                                   0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 5, 0, 0x13, 0x10};

//tab42240
const signed char sinus[256] = {
    0,    3,    6,    9,    12,   16,   19,   22,   25,   28,   31,   34,   37,   40,   43,   46,
    49,   51,   54,   57,   60,   63,   65,   68,   71,   73,   76,   78,   81,   83,   85,   88,
    90,   92,   94,   96,   98,   100,  102,  104,  106,  107,  109,  111,  112,  113,  115,  116,
    117,  118,  120,  121,  122,  122,  123,  124,  125,  125,  126,  126,  126,  127,  127,  127,
    127,  127,  127,  127,  126,  126,  126,  125,  125,  124,  123,  122,  122,  121,  120,  118,
    117,  116,  115,  113,  112,  111,  109,  107,  106,  104,  102,  100,  98,   96,   94,   92,
    90,   88,   85,   83,   81,   78,   76,   73,   71,   68,   65,   63,   60,   57,   54,   51,
    49,   46,   43,   40,   37,   34,   31,   28,   25,   22,   19,   16,   12,   9,    6,    3,
    0,    -3,   -6,   -9,   -12,  -16,  -19,  -22,  -25,  -28,  -31,  -34,  -37,  -40,  -43,  -46,
    -49,  -51,  -54,  -57,  -60,  -63,  -65,  -68,  -71,  -73,  -76,  -78,  -81,  -83,  -85,  -88,
    -90,  -92,  -94,  -96,  -98,  -100, -102, -104, -106, -107, -109, -111, -112, -113, -115, -116,
    -117, -118, -120, -121, -122, -122, -123, -124, -125, -125, -126, -126, -126, -127, -127, -127,
    -127, -127, -127, -127, -126, -126, -126, -125, -125, -124, -123, -122, -122, -121, -120, -118,
    -117, -116, -115, -113, -112, -111, -109, -107, -106, -104, -102, -100, -98,  -96,  -94,  -92,
    -90,  -88,  -85,  -83,  -81,  -78,  -76,  -73,  -71,  -68,  -65,  -63,  -60,  -57,  -54,  -51,
    -49,  -46,  -43,  -40,  -37,  -34,  -31,  -28,  -25,  -22,  -19,  -16,  -12,  -9,   -6,   -3};

//tab42496
const unsigned char rectangle[] = {
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70};

//random data ?
const unsigned char sampleTable[0x500] = {
    //00

    0x38,
    0x84,
    0x6B,
    0x19,
    0xC6,
    0x63,
    0x18,
    0x86,
    0x73,
    0x98,
    0xC6,
    0xB1,
    0x1C,
    0xCA,
    0x31,
    0x8C,
    0xC7,
    0x31,
    0x88,
    0xC2,
    0x30,
    0x98,
    0x46,
    0x31,
    0x18,
    0xC6,
    0x35,
    0xC,
    0xCA,
    0x31,
    0xC,
    0xC6
    //20
    ,
    0x21,
    0x10,
    0x24,
    0x69,
    0x12,
    0xC2,
    0x31,
    0x14,
    0xC4,
    0x71,
    8,
    0x4A,
    0x22,
    0x49,
    0xAB,
    0x6A,
    0xA8,
    0xAC,
    0x49,
    0x51,
    0x32,
    0xD5,
    0x52,
    0x88,
    0x93,
    0x6C,
    0x94,
    0x22,
    0x15,
    0x54,
    0xD2,
    0x25
    //40
    ,
    0x96,
    0xD4,
    0x50,
    0xA5,
    0x46,
    0x21,
    8,
    0x85,
    0x6B,
    0x18,
    0xC4,
    0x63,
    0x10,
    0xCE,
    0x6B,
    0x18,
    0x8C,
    0x71,
    0x19,
    0x8C,
    0x63,
    0x35,
    0xC,
    0xC6,
    0x33,
    0x99,
    0xCC,
    0x6C,
    0xB5,
    0x4E,
    0xA2,
    0x99
    //60
    ,
    0x46,
    0x21,
    0x28,
    0x82,
    0x95,
    0x2E,
    0xE3,
    0x30,
    0x9C,
    0xC5,
    0x30,
    0x9C,
    0xA2,
    0xB1,
    0x9C,
    0x67,
    0x31,
    0x88,
    0x66,
    0x59,
    0x2C,
    0x53,
    0x18,
    0x84,
    0x67,
    0x50,
    0xCA,
    0xE3,
    0xA,
    0xAC,
    0xAB,
    0x30
    //80
    ,
    0xAC,
    0x62,
    0x30,
    0x8C,
    0x63,
    0x10,
    0x94,
    0x62,
    0xB1,
    0x8C,
    0x82,
    0x28,
    0x96,
    0x33,
    0x98,
    0xD6,
    0xB5,
    0x4C,
    0x62,
    0x29,
    0xA5,
    0x4A,
    0xB5,
    0x9C,
    0xC6,
    0x31,
    0x14,
    0xD6,
    0x38,
    0x9C,
    0x4B,
    0xB4
    //A0
    ,
    0x86,
    0x65,
    0x18,
    0xAE,
    0x67,
    0x1C,
    0xA6,
    0x63,
    0x19,
    0x96,
    0x23,
    0x19,
    0x84,
    0x13,
    8,
    0xA6,
    0x52,
    0xAC,
    0xCA,
    0x22,
    0x89,
    0x6E,
    0xAB,
    0x19,
    0x8C,
    0x62,
    0x34,
    0xC4,
    0x62,
    0x19,
    0x86,
    0x63
    //C0
    ,
    0x18,
    0xC4,
    0x23,
    0x58,
    0xD6,
    0xA3,
    0x50,
    0x42,
    0x54,
    0x4A,
    0xAD,
    0x4A,
    0x25,
    0x11,
    0x6B,
    0x64,
    0x89,
    0x4A,
    0x63,
    0x39,
    0x8A,
    0x23,
    0x31,
    0x2A,
    0xEA,
    0xA2,
    0xA9,
    0x44,
    0xC5,
    0x12,
    0xCD,
    0x42
    //E0
    ,
    0x34,
    0x8C,
    0x62,
    0x18,
    0x8C,
    0x63,
    0x11,
    0x48,
    0x66,
    0x31,
    0x9D,
    0x44,
    0x33,
    0x1D,
    0x46,
    0x31,
    0x9C,
    0xC6,
    0xB1,
    0xC,
    0xCD,
    0x32,
    0x88,
    0xC4,
    0x73,
    0x18,
    0x86,
    0x73,
    8,
    0xD6,
    0x63,
    0x58
    //100
    ,
    7,
    0x81,
    0xE0,
    0xF0,
    0x3C,
    7,
    0x87,
    0x90,
    0x3C,
    0x7C,
    0xF,
    0xC7,
    0xC0,
    0xC0,
    0xF0,
    0x7C,
    0x1E,
    7,
    0x80,
    0x80,
    0,
    0x1C,
    0x78,
    0x70,
    0xF1,
    0xC7,
    0x1F,
    0xC0,
    0xC,
    0xFE,
    0x1C,
    0x1F
    //120
    ,
    0x1F,
    0xE,
    0xA,
    0x7A,
    0xC0,
    0x71,
    0xF2,
    0x83,
    0x8F,
    3,
    0xF,
    0xF,
    0xC,
    0,
    0x79,
    0xF8,
    0x61,
    0xE0,
    0x43,
    0xF,
    0x83,
    0xE7,
    0x18,
    0xF9,
    0xC1,
    0x13,
    0xDA,
    0xE9,
    0x63,
    0x8F,
    0xF,
    0x83
    //140
    ,
    0x83,
    0x87,
    0xC3,
    0x1F,
    0x3C,
    0x70,
    0xF0,
    0xE1,
    0xE1,
    0xE3,
    0x87,
    0xB8,
    0x71,
    0xE,
    0x20,
    0xE3,
    0x8D,
    0x48,
    0x78,
    0x1C,
    0x93,
    0x87,
    0x30,
    0xE1,
    0xC1,
    0xC1,
    0xE4,
    0x78,
    0x21,
    0x83,
    0x83,
    0xC3
    //160
    ,
    0x87,
    6,
    0x39,
    0xE5,
    0xC3,
    0x87,
    7,
    0xE,
    0x1C,
    0x1C,
    0x70,
    0xF4,
    0x71,
    0x9C,
    0x60,
    0x36,
    0x32,
    0xC3,
    0x1E,
    0x3C,
    0xF3,
    0x8F,
    0xE,
    0x3C,
    0x70,
    0xE3,
    0xC7,
    0x8F,
    0xF,
    0xF,
    0xE,
    0x3C
    //180
    ,
    0x78,
    0xF0,
    0xE3,
    0x87,
    6,
    0xF0,
    0xE3,
    7,
    0xC1,
    0x99,
    0x87,
    0xF,
    0x18,
    0x78,
    0x70,
    0x70,
    0xFC,
    0xF3,
    0x10,
    0xB1,
    0x8C,
    0x8C,
    0x31,
    0x7C,
    0x70,
    0xE1,
    0x86,
    0x3C,
    0x64,
    0x6C,
    0xB0,
    0xE1
    //1A0
    ,
    0xE3,
    0xF,
    0x23,
    0x8F,
    0xF,
    0x1E,
    0x3E,
    0x38,
    0x3C,
    0x38,
    0x7B,
    0x8F,
    7,
    0xE,
    0x3C,
    0xF4,
    0x17,
    0x1E,
    0x3C,
    0x78,
    0xF2,
    0x9E,
    0x72,
    0x49,
    0xE3,
    0x25,
    0x36,
    0x38,
    0x58,
    0x39,
    0xE2,
    0xDE
    //1C0
    ,
    0x3C,
    0x78,
    0x78,
    0xE1,
    0xC7,
    0x61,
    0xE1,
    0xE1,
    0xB0,
    0xF0,
    0xF0,
    0xC3,
    0xC7,
    0xE,
    0x38,
    0xC0,
    0xF0,
    0xCE,
    0x73,
    0x73,
    0x18,
    0x34,
    0xB0,
    0xE1,
    0xC7,
    0x8E,
    0x1C,
    0x3C,
    0xF8,
    0x38,
    0xF0,
    0xE1
    //1E0
    ,
    0xC1,
    0x8B,
    0x86,
    0x8F,
    0x1C,
    0x78,
    0x70,
    0xF0,
    0x78,
    0xAC,
    0xB1,
    0x8F,
    0x39,
    0x31,
    0xDB,
    0x38,
    0x61,
    0xC3,
    0xE,
    0xE,
    0x38,
    0x78,
    0x73,
    0x17,
    0x1E,
    0x39,
    0x1E,
    0x38,
    0x64,
    0xE1,
    0xF1,
    0xC1
    //200
    ,
    0x4E,
    0xF,
    0x40,
    0xA2,
    2,
    0xC5,
    0x8F,
    0x81,
    0xA1,
    0xFC,
    0x12,
    8,
    0x64,
    0xE0,
    0x3C,
    0x22,
    0xE0,
    0x45,
    7,
    0x8E,
    0xC,
    0x32,
    0x90,
    0xF0,
    0x1F,
    0x20,
    0x49,
    0xE0,
    0xF8,
    0xC,
    0x60,
    0xF0
    //220
    ,
    0x17,
    0x1A,
    0x41,
    0xAA,
    0xA4,
    0xD0,
    0x8D,
    0x12,
    0x82,
    0x1E,
    0x1E,
    3,
    0xF8,
    0x3E,
    3,
    0xC,
    0x73,
    0x80,
    0x70,
    0x44,
    0x26,
    3,
    0x24,
    0xE1,
    0x3E,
    4,
    0x4E,
    4,
    0x1C,
    0xC1,
    9,
    0xCC
    //240
    ,
    0x9E,
    0x90,
    0x21,
    7,
    0x90,
    0x43,
    0x64,
    0xC0,
    0xF,
    0xC6,
    0x90,
    0x9C,
    0xC1,
    0x5B,
    3,
    0xE2,
    0x1D,
    0x81,
    0xE0,
    0x5E,
    0x1D,
    3,
    0x84,
    0xB8,
    0x2C,
    0xF,
    0x80,
    0xB1,
    0x83,
    0xE0,
    0x30,
    0x41
    //260
    ,
    0x1E,
    0x43,
    0x89,
    0x83,
    0x50,
    0xFC,
    0x24,
    0x2E,
    0x13,
    0x83,
    0xF1,
    0x7C,
    0x4C,
    0x2C,
    0xC9,
    0xD,
    0x83,
    0xB0,
    0xB5,
    0x82,
    0xE4,
    0xE8,
    6,
    0x9C,
    7,
    0xA0,
    0x99,
    0x1D,
    7,
    0x3E,
    0x82,
    0x8F
    //280
    ,
    0x70,
    0x30,
    0x74,
    0x40,
    0xCA,
    0x10,
    0xE4,
    0xE8,
    0xF,
    0x92,
    0x14,
    0x3F,
    6,
    0xF8,
    0x84,
    0x88,
    0x43,
    0x81,
    0xA,
    0x34,
    0x39,
    0x41,
    0xC6,
    0xE3,
    0x1C,
    0x47,
    3,
    0xB0,
    0xB8,
    0x13,
    0xA,
    0xC2
    //2A0
    ,
    0x64,
    0xF8,
    0x18,
    0xF9,
    0x60,
    0xB3,
    0xC0,
    0x65,
    0x20,
    0x60,
    0xA6,
    0x8C,
    0xC3,
    0x81,
    0x20,
    0x30,
    0x26,
    0x1E,
    0x1C,
    0x38,
    0xD3,
    1,
    0xB0,
    0x26,
    0x40,
    0xF4,
    0xB,
    0xC3,
    0x42,
    0x1F,
    0x85,
    0x32
    //2C0
    ,
    0x26,
    0x60,
    0x40,
    0xC9,
    0xCB,
    1,
    0xEC,
    0x11,
    0x28,
    0x40,
    0xFA,
    4,
    0x34,
    0xE0,
    0x70,
    0x4C,
    0x8C,
    0x1D,
    7,
    0x69,
    3,
    0x16,
    0xC8,
    4,
    0x23,
    0xE8,
    0xC6,
    0x9A,
    0xB,
    0x1A,
    3,
    0xE0
    //2E0
    ,
    0x76,
    6,
    5,
    0xCF,
    0x1E,
    0xBC,
    0x58,
    0x31,
    0x71,
    0x66,
    0,
    0xF8,
    0x3F,
    4,
    0xFC,
    0xC,
    0x74,
    0x27,
    0x8A,
    0x80,
    0x71,
    0xC2,
    0x3A,
    0x26,
    6,
    0xC0,
    0x1F,
    5,
    0xF,
    0x98,
    0x40,
    0xAE
    //300
    ,
    1,
    0x7F,
    0xC0,
    7,
    0xFF,
    0,
    0xE,
    0xFE,
    0,
    3,
    0xDF,
    0x80,
    3,
    0xEF,
    0x80,
    0x1B,
    0xF1,
    0xC2,
    0,
    0xE7,
    0xE0,
    0x18,
    0xFC,
    0xE0,
    0x21,
    0xFC,
    0x80,
    0x3C,
    0xFC,
    0x40,
    0xE,
    0x7E
    //320
    ,
    0,
    0x3F,
    0x3E,
    0,
    0xF,
    0xFE,
    0,
    0x1F,
    0xFF,
    0,
    0x3E,
    0xF0,
    7,
    0xFC,
    0,
    0x7E,
    0x10,
    0x3F,
    0xFF,
    0,
    0x3F,
    0x38,
    0xE,
    0x7C,
    1,
    0x87,
    0xC,
    0xFC,
    0xC7,
    0,
    0x3E,
    4
    //340
    ,
    0xF,
    0x3E,
    0x1F,
    0xF,
    0xF,
    0x1F,
    0xF,
    2,
    0x83,
    0x87,
    0xCF,
    3,
    0x87,
    0xF,
    0x3F,
    0xC0,
    7,
    0x9E,
    0x60,
    0x3F,
    0xC0,
    3,
    0xFE,
    0,
    0x3F,
    0xE0,
    0x77,
    0xE1,
    0xC0,
    0xFE,
    0xE0,
    0xC3
    //360
    ,
    0xE0,
    1,
    0xDF,
    0xF8,
    3,
    7,
    0,
    0x7E,
    0x70,
    0,
    0x7C,
    0x38,
    0x18,
    0xFE,
    0xC,
    0x1E,
    0x78,
    0x1C,
    0x7C,
    0x3E,
    0xE,
    0x1F,
    0x1E,
    0x1E,
    0x3E,
    0,
    0x7F,
    0x83,
    7,
    0xDB,
    0x87,
    0x83
    //380
    ,
    7,
    0xC7,
    7,
    0x10,
    0x71,
    0xFF,
    0,
    0x3F,
    0xE2,
    1,
    0xE0,
    0xC1,
    0xC3,
    0xE1,
    0,
    0x7F,
    0xC0,
    5,
    0xF0,
    0x20,
    0xF8,
    0xF0,
    0x70,
    0xFE,
    0x78,
    0x79,
    0xF8,
    2,
    0x3F,
    0xC,
    0x8F,
    3
    //3a0
    ,
    0xF,
    0x9F,
    0xE0,
    0xC1,
    0xC7,
    0x87,
    3,
    0xC3,
    0xC3,
    0xB0,
    0xE1,
    0xE1,
    0xC1,
    0xE3,
    0xE0,
    0x71,
    0xF0,
    0,
    0xFC,
    0x70,
    0x7C,
    0xC,
    0x3E,
    0x38,
    0xE,
    0x1C,
    0x70,
    0xC3,
    0xC7,
    3,
    0x81,
    0xC1
    //3c0
    ,
    0xC7,
    0xE7,
    0,
    0xF,
    0xC7,
    0x87,
    0x19,
    9,
    0xEF,
    0xC4,
    0x33,
    0xE0,
    0xC1,
    0xFC,
    0xF8,
    0x70,
    0xF0,
    0x78,
    0xF8,
    0xF0,
    0x61,
    0xC7,
    0,
    0x1F,
    0xF8,
    1,
    0x7C,
    0xF8,
    0xF0,
    0x78,
    0x70,
    0x3C
    //3e0
    ,
    0x7C,
    0xCE,
    0xE,
    0x21,
    0x83,
    0xCF,
    8,
    7,
    0x8F,
    8,
    0xC1,
    0x87,
    0x8F,
    0x80,
    0xC7,
    0xE3,
    0,
    7,
    0xF8,
    0xE0,
    0xEF,
    0,
    0x39,
    0xF7,
    0x80,
    0xE,
    0xF8,
    0xE1,
    0xE3,
    0xF8,
    0x21,
    0x9F
    //400
    ,
    0xC0,
    0xFF,
    3,
    0xF8,
    7,
    0xC0,
    0x1F,
    0xF8,
    0xC4,
    4,
    0xFC,
    0xC4,
    0xC1,
    0xBC,
    0x87,
    0xF0,
    0xF,
    0xC0,
    0x7F,
    5,
    0xE0,
    0x25,
    0xEC,
    0xC0,
    0x3E,
    0x84,
    0x47,
    0xF0,
    0x8E,
    3,
    0xF8,
    3
    //420
    ,
    0xFB,
    0xC0,
    0x19,
    0xF8,
    7,
    0x9C,
    0xC,
    0x17,
    0xF8,
    7,
    0xE0,
    0x1F,
    0xA1,
    0xFC,
    0xF,
    0xFC,
    1,
    0xF0,
    0x3F,
    0,
    0xFE,
    3,
    0xF0,
    0x1F,
    0,
    0xFD,
    0,
    0xFF,
    0x88,
    0xD,
    0xF9,
    1
    //440
    ,
    0xFF,
    0,
    0x70,
    7,
    0xC0,
    0x3E,
    0x42,
    0xF3,
    0xD,
    0xC4,
    0x7F,
    0x80,
    0xFC,
    7,
    0xF0,
    0x5E,
    0xC0,
    0x3F,
    0,
    0x78,
    0x3F,
    0x81,
    0xFF,
    1,
    0xF8,
    1,
    0xC3,
    0xE8,
    0xC,
    0xE4,
    0x64,
    0x8F
    ////460
    ,
    0xE4,
    0xF,
    0xF0,
    7,
    0xF0,
    0xC2,
    0x1F,
    0,
    0x7F,
    0xC0,
    0x6F,
    0x80,
    0x7E,
    3,
    0xF8,
    7,
    0xF0,
    0x3F,
    0xC0,
    0x78,
    0xF,
    0x82,
    7,
    0xFE,
    0x22,
    0x77,
    0x70,
    2,
    0x76,
    3,
    0xFE,
    0
    //480
    ,
    0xFE,
    0x67,
    0,
    0x7C,
    0xC7,
    0xF1,
    0x8E,
    0xC6,
    0x3B,
    0xE0,
    0x3F,
    0x84,
    0xF3,
    0x19,
    0xD8,
    3,
    0x99,
    0xFC,
    9,
    0xB8,
    0xF,
    0xF8,
    0,
    0x9D,
    0x24,
    0x61,
    0xF9,
    0xD,
    0,
    0xFD,
    3,
    0xF0
    //4a0
    ,
    0x1F,
    0x90,
    0x3F,
    1,
    0xF8,
    0x1F,
    0xD0,
    0xF,
    0xF8,
    0x37,
    1,
    0xF8,
    7,
    0xF0,
    0xF,
    0xC0,
    0x3F,
    0,
    0xFE,
    3,
    0xF8,
    0xF,
    0xC0,
    0x3F,
    0,
    0xFA,
    3,
    0xF0,
    0xF,
    0x80,
    0xFF,
    1
    //4c0
    ,
    0xB8,
    7,
    0xF0,
    1,
    0xFC,
    1,
    0xBC,
    0x80,
    0x13,
    0x1E,
    0,
    0x7F,
    0xE1,
    0x40,
    0x7F,
    0xA0,
    0x7F,
    0xB0,
    0,
    0x3F,
    0xC0,
    0x1F,
    0xC0,
    0x38,
    0xF,
    0xF0,
    0x1F,
    0x80,
    0xFF,
    1,
    0xFC,
    3
    //4e0
    ,
    0xF1,
    0x7E,
    1,
    0xFE,
    1,
    0xF0,
    0xFF,
    0,
    0x7F,
    0xC0,
    0x1D,
    7,
    0xF0,
    0xF,
    0xC0,
    0x7E,
    6,
    0xE0,
    7,
    0xE0,
    0xF,
    0xF8,
    6,
    0xC1,
    0xFE,
    1,
    0xFC,
    3,
    0xE0,
    0xF,
    0,
    0xFC};

////////////////////////////////////////////////////////////////////////////////////////////
//
//           Render
//
////////////////////////////////////////////////////////////////////////////////////////////

unsigned char pitches[256]; // tab43008

unsigned char frequency1[256];
unsigned char frequency2[256];
unsigned char frequency3[256];

unsigned char amplitude1[256];
unsigned char amplitude2[256];
unsigned char amplitude3[256];

unsigned char sampledConsonantFlag[256]; // tab44800

////////////////////////////////////////////////////////////////////////////////////////////
//
//           Sam
//
////////////////////////////////////////////////////////////////////////////////////////////

unsigned char stress[256]; //numbers from 0 to 8
unsigned char phonemeLength[256]; //tab40160
unsigned char phonemeindex[256];

////////////////////////////////////////////////////////////////////////////////////////////
//
//           ReciterTabs
//
////////////////////////////////////////////////////////////////////////////////////////////

//some flags
const unsigned char tab36376[] = {
    0,   0,   0,   0,   0,   0,   0,   0, // 0-7
    0,   0,   0,   0,   0,   0,   0,   0, // 8-15
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   2,   2,   2,   2,   2,   2,   130, // ' ', '!'
    0,   0,   2,   2,   2,   2,   2,   2,   3,   3,   3,   3,   3,   3,   3,   3,
    3,   3,   2,   2,   2,   2,   2,   2,   2,   192, 168, 176, 172, 192, 160, 184, // '@', 'A'
    160, 192, 188, 160, 172, 168, 172, 192, 160, 160, 172, 180, 164, 192, 168, 168,
    176, 192, 188, 0,   0,   0,   2,   0, // 'X', 'Y', 'Z', '[',
    32,  32,  155, 32,  192, 185, 32,  205, 163, 76,  138, 142};

const unsigned char rules[] = {
    ']',        'A' | 0x80, ' ',        '(',        'A',        '.',        ')',        '=',
    'E',        'H',        '4',        'Y',        '.',        ' ' | 0x80, '(',        'A',
    ')',        ' ',        '=',        'A',        'H' | 0x80, ' ',        '(',        'A',
    'R',        'E',        ')',        ' ',        '=',        'A',        'A',        'R' | 0x80,
    ' ',        '(',        'A',        'R',        ')',        'O',        '=',        'A',
    'X',        'R' | 0x80, '(',        'A',        'R',        ')',        '#',        '=',
    'E',        'H',        '4',        'R' | 0x80, ' ',        '^',        '(',        'A',
    'S',        ')',        '#',        '=',        'E',        'Y',        '4',        'S' | 0x80,
    '(',        'A',        ')',        'W',        'A',        '=',        'A',        'X' | 0x80,
    '(',        'A',        'W',        ')',        '=',        'A',        'O',        '5' | 0x80,
    ' ',        ':',        '(',        'A',        'N',        'Y',        ')',        '=',
    'E',        'H',        '4',        'N',        'I',        'Y' | 0x80, '(',        'A',
    ')',        '^',        '+',        '#',        '=',        'E',        'Y',        '5' | 0x80,
    '#',        ':',        '(',        'A',        'L',        'L',        'Y',        ')',
    '=',        'U',        'L',        'I',        'Y' | 0x80, ' ',        '(',        'A',
    'L',        ')',        '#',        '=',        'U',        'L' | 0x80, '(',        'A',
    'G',        'A',        'I',        'N',        ')',        '=',        'A',        'X',
    'G',        'E',        'H',        '4',        'N' | 0x80, '#',        ':',        '(',
    'A',        'G',        ')',        'E',        '=',        'I',        'H',        'J' | 0x80,
    '(',        'A',        ')',        '^',        '%',        '=',        'E',        'Y' | 0x80,
    '(',        'A',        ')',        '^',        '+',        ':',        '#',        '=',
    'A',        'E' | 0x80, ' ',        ':',        '(',        'A',        ')',        '^',
    '+',        ' ',        '=',        'E',        'Y',        '4' | 0x80, ' ',        '(',
    'A',        'R',        'R',        ')',        '=',        'A',        'X',        'R' | 0x80,
    '(',        'A',        'R',        'R',        ')',        '=',        'A',        'E',
    '4',        'R' | 0x80, ' ',        '^',        '(',        'A',        'R',        ')',
    ' ',        '=',        'A',        'A',        '5',        'R' | 0x80, '(',        'A',
    'R',        ')',        '=',        'A',        'A',        '5',        'R' | 0x80, '(',
    'A',        'I',        'R',        ')',        '=',        'E',        'H',        '4',
    'R' | 0x80, '(',        'A',        'I',        ')',        '=',        'E',        'Y',
    '4' | 0x80, '(',        'A',        'Y',        ')',        '=',        'E',        'Y',
    '5' | 0x80, '(',        'A',        'U',        ')',        '=',        'A',        'O',
    '4' | 0x80, '#',        ':',        '(',        'A',        'L',        ')',        ' ',
    '=',        'U',        'L' | 0x80, '#',        ':',        '(',        'A',        'L',
    'S',        ')',        ' ',        '=',        'U',        'L',        'Z' | 0x80, '(',
    'A',        'L',        'K',        ')',        '=',        'A',        'O',        '4',
    'K' | 0x80, '(',        'A',        'L',        ')',        '^',        '=',        'A',
    'O',        'L' | 0x80, ' ',        ':',        '(',        'A',        'B',        'L',
    'E',        ')',        '=',        'E',        'Y',        '4',        'B',        'U',
    'L' | 0x80, '(',        'A',        'B',        'L',        'E',        ')',        '=',
    'A',        'X',        'B',        'U',        'L' | 0x80, '(',        'A',        ')',
    'V',        'O',        '=',        'E',        'Y',        '4' | 0x80, '(',        'A',
    'N',        'G',        ')',        '+',        '=',        'E',        'Y',        '4',
    'N',        'J' | 0x80, '(',        'A',        'T',        'A',        'R',        'I',
    ')',        '=',        'A',        'H',        'T',        'A',        'A',        '4',
    'R',        'I',        'Y' | 0x80, '(',        'A',        ')',        'T',        'O',
    'M',        '=',        'A',        'E' | 0x80, '(',        'A',        ')',        'T',
    'T',        'I',        '=',        'A',        'E' | 0x80, ' ',        '(',        'A',
    'T',        ')',        ' ',        '=',        'A',        'E',        'T' | 0x80, ' ',
    '(',        'A',        ')',        'T',        '=',        'A',        'H' | 0x80, '(',
    'A',        ')',        '=',        'A',        'E' | 0x80,

    ']',        'B' | 0x80, ' ',        '(',        'B',        ')',        ' ',        '=',
    'B',        'I',        'Y',        '4' | 0x80, ' ',        '(',        'B',        'E',
    ')',        '^',        '#',        '=',        'B',        'I',        'H' | 0x80, '(',
    'B',        'E',        'I',        'N',        'G',        ')',        '=',        'B',
    'I',        'Y',        '4',        'I',        'H',        'N',        'X' | 0x80, ' ',
    '(',        'B',        'O',        'T',        'H',        ')',        ' ',        '=',
    'B',        'O',        'W',        '4',        'T',        'H' | 0x80, ' ',        '(',
    'B',        'U',        'S',        ')',        '#',        '=',        'B',        'I',
    'H',        '4',        'Z' | 0x80, '(',        'B',        'R',        'E',        'A',
    'K',        ')',        '=',        'B',        'R',        'E',        'Y',        '5',
    'K' | 0x80, '(',        'B',        'U',        'I',        'L',        ')',        '=',
    'B',        'I',        'H',        '4',        'L' | 0x80, '(',        'B',        ')',
    '=',        'B' | 0x80,

    ']',        'C' | 0x80, ' ',        '(',        'C',        ')',        ' ',        '=',
    'S',        'I',        'Y',        '4' | 0x80, ' ',        '(',        'C',        'H',
    ')',        '^',        '=',        'K' | 0x80, '^',        'E',        '(',        'C',
    'H',        ')',        '=',        'K' | 0x80, '(',        'C',        'H',        'A',
    ')',        'R',        '#',        '=',        'K',        'E',        'H',        '5' | 0x80,
    '(',        'C',        'H',        ')',        '=',        'C',        'H' | 0x80, ' ',
    'S',        '(',        'C',        'I',        ')',        '#',        '=',        'S',
    'A',        'Y',        '4' | 0x80, '(',        'C',        'I',        ')',        'A',
    '=',        'S',        'H' | 0x80, '(',        'C',        'I',        ')',        'O',
    '=',        'S',        'H' | 0x80, '(',        'C',        'I',        ')',        'E',
    'N',        '=',        'S',        'H' | 0x80, '(',        'C',        'I',        'T',
    'Y',        ')',        '=',        'S',        'I',        'H',        'T',        'I',
    'Y' | 0x80, '(',        'C',        ')',        '+',        '=',        'S' | 0x80, '(',
    'C',        'K',        ')',        '=',        'K' | 0x80, '(',        'C',        'O',
    'M',        'M',        'O',        'D',        'O',        'R',        'E',        ')',
    '=',        'K',        'A',        'A',        '4',        'M',        'A',        'H',
    'D',        'O',        'H',        'R' | 0x80, '(',        'C',        'O',        'M',
    ')',        '=',        'K',        'A',        'H',        'M' | 0x80, '(',        'C',
    'U',        'I',        'T',        ')',        '=',        'K',        'I',        'H',
    'T' | 0x80, '(',        'C',        'R',        'E',        'A',        ')',        '=',
    'K',        'R',        'I',        'Y',        'E',        'Y' | 0x80, '(',        'C',
    ')',        '=',        'K' | 0x80,

    ']',        'D' | 0x80, ' ',        '(',        'D',        ')',        ' ',        '=',
    'D',        'I',        'Y',        '4' | 0x80, ' ',        '(',        'D',        'R',
    '.',        ')',        ' ',        '=',        'D',        'A',        'A',        '4',
    'K',        'T',        'E',        'R' | 0x80, '#',        ':',        '(',        'D',
    'E',        'D',        ')',        ' ',        '=',        'D',        'I',        'H',
    'D' | 0x80, '.',        'E',        '(',        'D',        ')',        ' ',        '=',
    'D' | 0x80, '#',        ':',        '^',        'E',        '(',        'D',        ')',
    ' ',        '=',        'T' | 0x80, ' ',        '(',        'D',        'E',        ')',
    '^',        '#',        '=',        'D',        'I',        'H' | 0x80, ' ',        '(',
    'D',        'O',        ')',        ' ',        '=',        'D',        'U',        'W' | 0x80,
    ' ',        '(',        'D',        'O',        'E',        'S',        ')',        '=',
    'D',        'A',        'H',        'Z' | 0x80, '(',        'D',        'O',        'N',
    'E',        ')',        ' ',        '=',        'D',        'A',        'H',        '5',
    'N' | 0x80, '(',        'D',        'O',        'I',        'N',        'G',        ')',
    '=',        'D',        'U',        'W',        '4',        'I',        'H',        'N',
    'X' | 0x80, ' ',        '(',        'D',        'O',        'W',        ')',        '=',
    'D',        'A',        'W' | 0x80, '#',        '(',        'D',        'U',        ')',
    'A',        '=',        'J',        'U',        'W' | 0x80, '#',        '(',        'D',
    'U',        ')',        '^',        '#',        '=',        'J',        'A',        'X' | 0x80,
    '(',        'D',        ')',        '=',        'D' | 0x80,

    ']',        'E' | 0x80, ' ',        '(',        'E',        ')',        ' ',        '=',
    'I',        'Y',        'I',        'Y',        '4' | 0x80, '#',        ':',        '(',
    'E',        ')',        ' ',        '=' | 0x80, '\'',       ':',        '^',        '(',
    'E',        ')',        ' ',        '=' | 0x80, ' ',        ':',        '(',        'E',
    ')',        ' ',        '=',        'I',        'Y' | 0x80, '#',        '(',        'E',
    'D',        ')',        ' ',        '=',        'D' | 0x80, '#',        ':',        '(',
    'E',        ')',        'D',        ' ',        '=' | 0x80, '(',        'E',        'V',
    ')',        'E',        'R',        '=',        'E',        'H',        '4',        'V' | 0x80,
    '(',        'E',        ')',        '^',        '%',        '=',        'I',        'Y',
    '4' | 0x80, '(',        'E',        'R',        'I',        ')',        '#',        '=',
    'I',        'Y',        '4',        'R',        'I',        'Y' | 0x80, '(',        'E',
    'R',        'I',        ')',        '=',        'E',        'H',        '4',        'R',
    'I',        'H' | 0x80, '#',        ':',        '(',        'E',        'R',        ')',
    '#',        '=',        'E',        'R' | 0x80, '(',        'E',        'R',        'R',
    'O',        'R',        ')',        '=',        'E',        'H',        '4',        'R',
    'O',        'H',        'R' | 0x80, '(',        'E',        'R',        'A',        'S',
    'E',        ')',        '=',        'I',        'H',        'R',        'E',        'Y',
    '5',        'S' | 0x80, '(',        'E',        'R',        ')',        '#',        '=',
    'E',        'H',        'R' | 0x80, '(',        'E',        'R',        ')',        '=',
    'E',        'R' | 0x80, ' ',        '(',        'E',        'V',        'E',        'N',
    ')',        '=',        'I',        'Y',        'V',        'E',        'H',        'N' | 0x80,
    '#',        ':',        '(',        'E',        ')',        'W',        '=' | 0x80, '@',
    '(',        'E',        'W',        ')',        '=',        'U',        'W' | 0x80, '(',
    'E',        'W',        ')',        '=',        'Y',        'U',        'W' | 0x80, '(',
    'E',        ')',        'O',        '=',        'I',        'Y' | 0x80, '#',        ':',
    '&',        '(',        'E',        'S',        ')',        ' ',        '=',        'I',
    'H',        'Z' | 0x80, '#',        ':',        '(',        'E',        ')',        'S',
    ' ',        '=' | 0x80, '#',        ':',        '(',        'E',        'L',        'Y',
    ')',        ' ',        '=',        'L',        'I',        'Y' | 0x80, '#',        ':',
    '(',        'E',        'M',        'E',        'N',        'T',        ')',        '=',
    'M',        'E',        'H',        'N',        'T' | 0x80, '(',        'E',        'F',
    'U',        'L',        ')',        '=',        'F',        'U',        'H',        'L' | 0x80,
    '(',        'E',        'E',        ')',        '=',        'I',        'Y',        '4' | 0x80,
    '(',        'E',        'A',        'R',        'N',        ')',        '=',        'E',
    'R',        '5',        'N' | 0x80, ' ',        '(',        'E',        'A',        'R',
    ')',        '^',        '=',        'E',        'R',        '5' | 0x80, '(',        'E',
    'A',        'D',        ')',        '=',        'E',        'H',        'D' | 0x80, '#',
    ':',        '(',        'E',        'A',        ')',        ' ',        '=',        'I',
    'Y',        'A',        'X' | 0x80, '(',        'E',        'A',        ')',        'S',
    'U',        '=',        'E',        'H',        '5' | 0x80, '(',        'E',        'A',
    ')',        '=',        'I',        'Y',        '5' | 0x80, '(',        'E',        'I',
    'G',        'H',        ')',        '=',        'E',        'Y',        '4' | 0x80, '(',
    'E',        'I',        ')',        '=',        'I',        'Y',        '4' | 0x80, ' ',
    '(',        'E',        'Y',        'E',        ')',        '=',        'A',        'Y',
    '4' | 0x80, '(',        'E',        'Y',        ')',        '=',        'I',        'Y' | 0x80,
    '(',        'E',        'U',        ')',        '=',        'Y',        'U',        'W',
    '5' | 0x80, '(',        'E',        'Q',        'U',        'A',        'L',        ')',
    '=',        'I',        'Y',        '4',        'K',        'W',        'U',        'L' | 0x80,
    '(',        'E',        ')',        '=',        'E',        'H' | 0x80,

    ']',        'F' | 0x80, ' ',        '(',        'F',        ')',        ' ',        '=',
    'E',        'H',        '4',        'F' | 0x80, '(',        'F',        'U',        'L',
    ')',        '=',        'F',        'U',        'H',        'L' | 0x80, '(',        'F',
    'R',        'I',        'E',        'N',        'D',        ')',        '=',        'F',
    'R',        'E',        'H',        '5',        'N',        'D' | 0x80, '(',        'F',
    'A',        'T',        'H',        'E',        'R',        ')',        '=',        'F',
    'A',        'A',        '4',        'D',        'H',        'E',        'R' | 0x80, '(',
    'F',        ')',        'F',        '=' | 0x80, '(',        'F',        ')',        '=',
    'F' | 0x80,

    ']',        'G' | 0x80, ' ',        '(',        'G',        ')',        ' ',        '=',
    'J',        'I',        'Y',        '4' | 0x80, '(',        'G',        'I',        'V',
    ')',        '=',        'G',        'I',        'H',        '5',        'V' | 0x80, ' ',
    '(',        'G',        ')',        'I',        '^',        '=',        'G' | 0x80, '(',
    'G',        'E',        ')',        'T',        '=',        'G',        'E',        'H',
    '5' | 0x80, 'S',        'U',        '(',        'G',        'G',        'E',        'S',
    ')',        '=',        'G',        'J',        'E',        'H',        '4',        'S' | 0x80,
    '(',        'G',        'G',        ')',        '=',        'G' | 0x80, ' ',        'B',
    '#',        '(',        'G',        ')',        '=',        'G' | 0x80, '(',        'G',
    ')',        '+',        '=',        'J' | 0x80, '(',        'G',        'R',        'E',
    'A',        'T',        ')',        '=',        'G',        'R',        'E',        'Y',
    '4',        'T' | 0x80, '(',        'G',        'O',        'N',        ')',        'E',
    '=',        'G',        'A',        'O',        '5',        'N' | 0x80, '#',        '(',
    'G',        'H',        ')',        '=' | 0x80, ' ',        '(',        'G',        'N',
    ')',        '=',        'N' | 0x80, '(',        'G',        ')',        '=',        'G' | 0x80,

    ']',        'H' | 0x80, ' ',        '(',        'H',        ')',        ' ',        '=',
    'E',        'Y',        '4',        'C',        'H' | 0x80, ' ',        '(',        'H',
    'A',        'V',        ')',        '=',        '/',        'H',        'A',        'E',
    '6',        'V' | 0x80, ' ',        '(',        'H',        'E',        'R',        'E',
    ')',        '=',        '/',        'H',        'I',        'Y',        'R' | 0x80, ' ',
    '(',        'H',        'O',        'U',        'R',        ')',        '=',        'A',
    'W',        '5',        'E',        'R' | 0x80, '(',        'H',        'O',        'W',
    ')',        '=',        '/',        'H',        'A',        'W' | 0x80, '(',        'H',
    ')',        '#',        '=',        '/',        'H' | 0x80, '(',        'H',        ')',
    '=' | 0x80,

    ']',        'I' | 0x80, ' ',        '(',        'I',        'N',        ')',        '=',
    'I',        'H',        'N' | 0x80, ' ',        '(',        'I',        ')',        ' ',
    '=',        'A',        'Y',        '4' | 0x80, '(',        'I',        ')',        ' ',
    '=',        'A',        'Y' | 0x80, '(',        'I',        'N',        ')',        'D',
    '=',        'A',        'Y',        '5',        'N' | 0x80, 'S',        'E',        'M',
    '(',        'I',        ')',        '=',        'I',        'Y' | 0x80, ' ',        'A',
    'N',        'T',        '(',        'I',        ')',        '=',        'A',        'Y' | 0x80,
    '(',        'I',        'E',        'R',        ')',        '=',        'I',        'Y',
    'E',        'R' | 0x80, '#',        ':',        'R',        '(',        'I',        'E',
    'D',        ')',        ' ',        '=',        'I',        'Y',        'D' | 0x80, '(',
    'I',        'E',        'D',        ')',        ' ',        '=',        'A',        'Y',
    '5',        'D' | 0x80, '(',        'I',        'E',        'N',        ')',        '=',
    'I',        'Y',        'E',        'H',        'N' | 0x80, '(',        'I',        'E',
    ')',        'T',        '=',        'A',        'Y',        '4',        'E',        'H' | 0x80,
    '(',        'I',        '\'',       ')',        '=',        'A',        'Y',        '5' | 0x80,
    ' ',        ':',        '(',        'I',        ')',        '^',        '%',        '=',
    'A',        'Y',        '5' | 0x80, ' ',        ':',        '(',        'I',        'E',
    ')',        ' ',        '=',        'A',        'Y',        '4' | 0x80, '(',        'I',
    ')',        '%',        '=',        'I',        'Y' | 0x80, '(',        'I',        'E',
    ')',        '=',        'I',        'Y',        '4' | 0x80, ' ',        '(',        'I',
    'D',        'E',        'A',        ')',        '=',        'A',        'Y',        'D',
    'I',        'Y',        '5',        'A',        'H' | 0x80, '(',        'I',        ')',
    '^',        '+',        ':',        '#',        '=',        'I',        'H' | 0x80, '(',
    'I',        'R',        ')',        '#',        '=',        'A',        'Y',        'R' | 0x80,
    '(',        'I',        'Z',        ')',        '%',        '=',        'A',        'Y',
    'Z' | 0x80, '(',        'I',        'S',        ')',        '%',        '=',        'A',
    'Y',        'Z' | 0x80, 'I',        '^',        '(',        'I',        ')',        '^',
    '#',        '=',        'I',        'H' | 0x80, '+',        '^',        '(',        'I',
    ')',        '^',        '+',        '=',        'A',        'Y' | 0x80, '#',        ':',
    '^',        '(',        'I',        ')',        '^',        '+',        '=',        'I',
    'H' | 0x80, '(',        'I',        ')',        '^',        '+',        '=',        'A',
    'Y' | 0x80, '(',        'I',        'R',        ')',        '=',        'E',        'R' | 0x80,
    '(',        'I',        'G',        'H',        ')',        '=',        'A',        'Y',
    '4' | 0x80, '(',        'I',        'L',        'D',        ')',        '=',        'A',
    'Y',        '5',        'L',        'D' | 0x80, ' ',        '(',        'I',        'G',
    'N',        ')',        '=',        'I',        'H',        'G',        'N' | 0x80, '(',
    'I',        'G',        'N',        ')',        ' ',        '=',        'A',        'Y',
    '4',        'N' | 0x80, '(',        'I',        'G',        'N',        ')',        '^',
    '=',        'A',        'Y',        '4',        'N' | 0x80, '(',        'I',        'G',
    'N',        ')',        '%',        '=',        'A',        'Y',        '4',        'N' | 0x80,
    '(',        'I',        'C',        'R',        'O',        ')',        '=',        'A',
    'Y',        '4',        'K',        'R',        'O',        'H' | 0x80, '(',        'I',
    'Q',        'U',        'E',        ')',        '=',        'I',        'Y',        '4',
    'K' | 0x80, '(',        'I',        ')',        '=',        'I',        'H' | 0x80,

    ']',        'J' | 0x80, ' ',        '(',        'J',        ')',        ' ',        '=',
    'J',        'E',        'Y',        '4' | 0x80, '(',        'J',        ')',        '=',
    'J' | 0x80,

    ']',        'K' | 0x80, ' ',        '(',        'K',        ')',        ' ',        '=',
    'K',        'E',        'Y',        '4' | 0x80, ' ',        '(',        'K',        ')',
    'N',        '=' | 0x80, '(',        'K',        ')',        '=',        'K' | 0x80,

    ']',        'L' | 0x80, ' ',        '(',        'L',        ')',        ' ',        '=',
    'E',        'H',        '4',        'L' | 0x80, '(',        'L',        'O',        ')',
    'C',        '#',        '=',        'L',        'O',        'W' | 0x80, 'L',        '(',
    'L',        ')',        '=' | 0x80, '#',        ':',        '^',        '(',        'L',
    ')',        '%',        '=',        'U',        'L' | 0x80, '(',        'L',        'E',
    'A',        'D',        ')',        '=',        'L',        'I',        'Y',        'D' | 0x80,
    ' ',        '(',        'L',        'A',        'U',        'G',        'H',        ')',
    '=',        'L',        'A',        'E',        '4',        'F' | 0x80, '(',        'L',
    ')',        '=',        'L' | 0x80,

    ']',        'M' | 0x80, ' ',        '(',        'M',        ')',        ' ',        '=',
    'E',        'H',        '4',        'M' | 0x80, ' ',        '(',        'M',        'R',
    '.',        ')',        ' ',        '=',        'M',        'I',        'H',        '4',
    'S',        'T',        'E',        'R' | 0x80, ' ',        '(',        'M',        'S',
    '.',        ')',        '=',        'M',        'I',        'H',        '5',        'Z' | 0x80,
    ' ',        '(',        'M',        'R',        'S',        '.',        ')',        ' ',
    '=',        'M',        'I',        'H',        '4',        'S',        'I',        'X',
    'Z' | 0x80, '(',        'M',        'O',        'V',        ')',        '=',        'M',
    'U',        'W',        '4',        'V' | 0x80, '(',        'M',        'A',        'C',
    'H',        'I',        'N',        ')',        '=',        'M',        'A',        'H',
    'S',        'H',        'I',        'Y',        '5',        'N' | 0x80, 'M',        '(',
    'M',        ')',        '=' | 0x80, '(',        'M',        ')',        '=',        'M' | 0x80,

    ']',        'N' | 0x80, ' ',        '(',        'N',        ')',        ' ',        '=',
    'E',        'H',        '4',        'N' | 0x80, 'E',        '(',        'N',        'G',
    ')',        '+',        '=',        'N',        'J' | 0x80, '(',        'N',        'G',
    ')',        'R',        '=',        'N',        'X',        'G' | 0x80, '(',        'N',
    'G',        ')',        '#',        '=',        'N',        'X',        'G' | 0x80, '(',
    'N',        'G',        'L',        ')',        '%',        '=',        'N',        'X',
    'G',        'U',        'L' | 0x80, '(',        'N',        'G',        ')',        '=',
    'N',        'X' | 0x80, '(',        'N',        'K',        ')',        '=',        'N',
    'X',        'K' | 0x80, ' ',        '(',        'N',        'O',        'W',        ')',
    ' ',        '=',        'N',        'A',        'W',        '4' | 0x80, 'N',        '(',
    'N',        ')',        '=' | 0x80, '(',        'N',        'O',        'N',        ')',
    'E',        '=',        'N',        'A',        'H',        '4',        'N' | 0x80, '(',
    'N',        ')',        '=',        'N' | 0x80,

    ']',        'O' | 0x80, ' ',        '(',        'O',        ')',        ' ',        '=',
    'O',        'H',        '4',        'W' | 0x80, '(',        'O',        'F',        ')',
    ' ',        '=',        'A',        'H',        'V' | 0x80, ' ',        '(',        'O',
    'H',        ')',        ' ',        '=',        'O',        'W',        '5' | 0x80, '(',
    'O',        'R',        'O',        'U',        'G',        'H',        ')',        '=',
    'E',        'R',        '4',        'O',        'W' | 0x80, '#',        ':',        '(',
    'O',        'R',        ')',        ' ',        '=',        'E',        'R' | 0x80, '#',
    ':',        '(',        'O',        'R',        'S',        ')',        ' ',        '=',
    'E',        'R',        'Z' | 0x80, '(',        'O',        'R',        ')',        '=',
    'A',        'O',        'R' | 0x80, ' ',        '(',        'O',        'N',        'E',
    ')',        '=',        'W',        'A',        'H',        'N' | 0x80, '#',        '(',
    'O',        'N',        'E',        ')',        ' ',        '=',        'W',        'A',
    'H',        'N' | 0x80, '(',        'O',        'W',        ')',        '=',        'O',
    'W' | 0x80, ' ',        '(',        'O',        'V',        'E',        'R',        ')',
    '=',        'O',        'W',        '5',        'V',        'E',        'R' | 0x80, 'P',
    'R',        '(',        'O',        ')',        'V',        '=',        'U',        'W',
    '4' | 0x80, '(',        'O',        'V',        ')',        '=',        'A',        'H',
    '4',        'V' | 0x80, '(',        'O',        ')',        '^',        '%',        '=',
    'O',        'W',        '5' | 0x80, '(',        'O',        ')',        '^',        'E',
    'N',        '=',        'O',        'W' | 0x80, '(',        'O',        ')',        '^',
    'I',        '#',        '=',        'O',        'W',        '5' | 0x80, '(',        'O',
    'L',        ')',        'D',        '=',        'O',        'W',        '4',        'L' | 0x80,
    '(',        'O',        'U',        'G',        'H',        'T',        ')',        '=',
    'A',        'O',        '5',        'T' | 0x80, '(',        'O',        'U',        'G',
    'H',        ')',        '=',        'A',        'H',        '5',        'F' | 0x80, ' ',
    '(',        'O',        'U',        ')',        '=',        'A',        'W' | 0x80, 'H',
    '(',        'O',        'U',        ')',        'S',        '#',        '=',        'A',
    'W',        '4' | 0x80, '(',        'O',        'U',        'S',        ')',        '=',
    'A',        'X',        'S' | 0x80, '(',        'O',        'U',        'R',        ')',
    '=',        'O',        'H',        'R' | 0x80, '(',        'O',        'U',        'L',
    'D',        ')',        '=',        'U',        'H',        '5',        'D' | 0x80, '(',
    'O',        'U',        ')',        '^',        'L',        '=',        'A',        'H',
    '5' | 0x80, '(',        'O',        'U',        'P',        ')',        '=',        'U',
    'W',        '5',        'P' | 0x80, '(',        'O',        'U',        ')',        '=',
    'A',        'W' | 0x80, '(',        'O',        'Y',        ')',        '=',        'O',
    'Y' | 0x80, '(',        'O',        'I',        'N',        'G',        ')',        '=',
    'O',        'W',        '4',        'I',        'H',        'N',        'X' | 0x80, '(',
    'O',        'I',        ')',        '=',        'O',        'Y',        '5' | 0x80, '(',
    'O',        'O',        'R',        ')',        '=',        'O',        'H',        '5',
    'R' | 0x80, '(',        'O',        'O',        'K',        ')',        '=',        'U',
    'H',        '5',        'K' | 0x80, 'F',        '(',        'O',        'O',        'D',
    ')',        '=',        'U',        'W',        '5',        'D' | 0x80, 'L',        '(',
    'O',        'O',        'D',        ')',        '=',        'A',        'H',        '5',
    'D' | 0x80, 'M',        '(',        'O',        'O',        'D',        ')',        '=',
    'U',        'W',        '5',        'D' | 0x80, '(',        'O',        'O',        'D',
    ')',        '=',        'U',        'H',        '5',        'D' | 0x80, 'F',        '(',
    'O',        'O',        'T',        ')',        '=',        'U',        'H',        '5',
    'T' | 0x80, '(',        'O',        'O',        ')',        '=',        'U',        'W',
    '5' | 0x80, '(',        'O',        '\'',       ')',        '=',        'O',        'H' | 0x80,
    '(',        'O',        ')',        'E',        '=',        'O',        'W' | 0x80, '(',
    'O',        ')',        ' ',        '=',        'O',        'W' | 0x80, '(',        'O',
    'A',        ')',        '=',        'O',        'W',        '4' | 0x80, ' ',        '(',
    'O',        'N',        'L',        'Y',        ')',        '=',        'O',        'W',
    '4',        'N',        'L',        'I',        'Y' | 0x80, ' ',        '(',        'O',
    'N',        'C',        'E',        ')',        '=',        'W',        'A',        'H',
    '4',        'N',        'S' | 0x80, '(',        'O',        'N',        '\'',       'T',
    ')',        '=',        'O',        'W',        '4',        'N',        'T' | 0x80, 'C',
    '(',        'O',        ')',        'N',        '=',        'A',        'A' | 0x80, '(',
    'O',        ')',        'N',        'G',        '=',        'A',        'O' | 0x80, ' ',
    ':',        '^',        '(',        'O',        ')',        'N',        '=',        'A',
    'H' | 0x80, 'I',        '(',        'O',        'N',        ')',        '=',        'U',
    'N' | 0x80, '#',        ':',        '(',        'O',        'N',        ')',        '=',
    'U',        'N' | 0x80, '#',        '^',        '(',        'O',        'N',        ')',
    '=',        'U',        'N' | 0x80, '(',        'O',        ')',        'S',        'T',
    '=',        'O',        'W' | 0x80, '(',        'O',        'F',        ')',        '^',
    '=',        'A',        'O',        '4',        'F' | 0x80, '(',        'O',        'T',
    'H',        'E',        'R',        ')',        '=',        'A',        'H',        '5',
    'D',        'H',        'E',        'R' | 0x80, 'R',        '(',        'O',        ')',
    'B',        '=',        'R',        'A',        'A' | 0x80, '^',        'R',        '(',
    'O',        ')',        ':',        '#',        '=',        'O',        'W',        '5' | 0x80,
    '(',        'O',        'S',        'S',        ')',        ' ',        '=',        'A',
    'O',        '5',        'S' | 0x80, '#',        ':',        '^',        '(',        'O',
    'M',        ')',        '=',        'A',        'H',        'M' | 0x80, '(',        'O',
    ')',        '=',        'A',        'A' | 0x80,

    ']',        'P' | 0x80, ' ',        '(',        'P',        ')',        ' ',        '=',
    'P',        'I',        'Y',        '4' | 0x80, '(',        'P',        'H',        ')',
    '=',        'F' | 0x80, '(',        'P',        'E',        'O',        'P',        'L',
    ')',        '=',        'P',        'I',        'Y',        '5',        'P',        'U',
    'L' | 0x80, '(',        'P',        'O',        'W',        ')',        '=',        'P',
    'A',        'W',        '4' | 0x80, '(',        'P',        'U',        'T',        ')',
    ' ',        '=',        'P',        'U',        'H',        'T' | 0x80, '(',        'P',
    ')',        'P',        '=' | 0x80, '(',        'P',        ')',        'S',        '=' | 0x80,
    '(',        'P',        ')',        'N',        '=' | 0x80, '(',        'P',        'R',
    'O',        'F',        '.',        ')',        '=',        'P',        'R',        'O',
    'H',        'F',        'E',        'H',        '4',        'S',        'E',        'R' | 0x80,
    '(',        'P',        ')',        '=',        'P' | 0x80,

    ']',        'Q' | 0x80, ' ',        '(',        'Q',        ')',        ' ',        '=',
    'K',        'Y',        'U',        'W',        '4' | 0x80, '(',        'Q',        'U',
    'A',        'R',        ')',        '=',        'K',        'W',        'O',        'H',
    '5',        'R' | 0x80, '(',        'Q',        'U',        ')',        '=',        'K',
    'W' | 0x80, '(',        'Q',        ')',        '=',        'K' | 0x80, ']',        'R' | 0x80,
    ' ',        '(',        'R',        ')',        ' ',        '=',        'A',        'A',
    '5',        'R' | 0x80, ' ',        '(',        'R',        'E',        ')',        '^',
    '#',        '=',        'R',        'I',        'Y' | 0x80, '(',        'R',        ')',
    'R',        '=' | 0x80, '(',        'R',        ')',        '=',        'R' | 0x80,

    ']',        'S' | 0x80, ' ',        '(',        'S',        ')',        ' ',        '=',
    'E',        'H',        '4',        'S' | 0x80, '(',        'S',        'H',        ')',
    '=',        'S',        'H' | 0x80, '#',        '(',        'S',        'I',        'O',
    'N',        ')',        '=',        'Z',        'H',        'U',        'N' | 0x80, '(',
    'S',        'O',        'M',        'E',        ')',        '=',        'S',        'A',
    'H',        'M' | 0x80, '#',        '(',        'S',        'U',        'R',        ')',
    '#',        '=',        'Z',        'H',        'E',        'R' | 0x80, '(',        'S',
    'U',        'R',        ')',        '#',        '=',        'S',        'H',        'E',
    'R' | 0x80, '#',        '(',        'S',        'U',        ')',        '#',        '=',
    'Z',        'H',        'U',        'W' | 0x80, '#',        '(',        'S',        'S',
    'U',        ')',        '#',        '=',        'S',        'H',        'U',        'W' | 0x80,
    '#',        '(',        'S',        'E',        'D',        ')',        '=',        'Z',
    'D' | 0x80, '#',        '(',        'S',        ')',        '#',        '=',        'Z' | 0x80,
    '(',        'S',        'A',        'I',        'D',        ')',        '=',        'S',
    'E',        'H',        'D' | 0x80, '^',        '(',        'S',        'I',        'O',
    'N',        ')',        '=',        'S',        'H',        'U',        'N' | 0x80, '(',
    'S',        ')',        'S',        '=' | 0x80, '.',        '(',        'S',        ')',
    ' ',        '=',        'Z' | 0x80, '#',        ':',        '.',        'E',        '(',
    'S',        ')',        ' ',        '=',        'Z' | 0x80, '#',        ':',        '^',
    '#',        '(',        'S',        ')',        ' ',        '=',        'S' | 0x80, 'U',
    '(',        'S',        ')',        ' ',        '=',        'S' | 0x80, ' ',        ':',
    '#',        '(',        'S',        ')',        ' ',        '=',        'Z' | 0x80, '#',
    '#',        '(',        'S',        ')',        ' ',        '=',        'Z' | 0x80, ' ',
    '(',        'S',        'C',        'H',        ')',        '=',        'S',        'K' | 0x80,
    '(',        'S',        ')',        'C',        '+',        '=' | 0x80, '#',        '(',
    'S',        'M',        ')',        '=',        'Z',        'U',        'M' | 0x80, '#',
    '(',        'S',        'N',        ')',        '\'',       '=',        'Z',        'U',
    'M' | 0x80, '(',        'S',        'T',        'L',        'E',        ')',        '=',
    'S',        'U',        'L' | 0x80, '(',        'S',        ')',        '=',        'S' | 0x80,

    ']',        'T' | 0x80, ' ',        '(',        'T',        ')',        ' ',        '=',
    'T',        'I',        'Y',        '4' | 0x80, ' ',        '(',        'T',        'H',
    'E',        ')',        ' ',        '#',        '=',        'D',        'H',        'I',
    'Y' | 0x80, ' ',        '(',        'T',        'H',        'E',        ')',        ' ',
    '=',        'D',        'H',        'A',        'X' | 0x80, '(',        'T',        'O',
    ')',        ' ',        '=',        'T',        'U',        'X' | 0x80, ' ',        '(',
    'T',        'H',        'A',        'T',        ')',        '=',        'D',        'H',
    'A',        'E',        'T' | 0x80, ' ',        '(',        'T',        'H',        'I',
    'S',        ')',        ' ',        '=',        'D',        'H',        'I',        'H',
    'S' | 0x80, ' ',        '(',        'T',        'H',        'E',        'Y',        ')',
    '=',        'D',        'H',        'E',        'Y' | 0x80, ' ',        '(',        'T',
    'H',        'E',        'R',        'E',        ')',        '=',        'D',        'H',
    'E',        'H',        'R' | 0x80, '(',        'T',        'H',        'E',        'R',
    ')',        '=',        'D',        'H',        'E',        'R' | 0x80, '(',        'T',
    'H',        'E',        'I',        'R',        ')',        '=',        'D',        'H',
    'E',        'H',        'R' | 0x80, ' ',        '(',        'T',        'H',        'A',
    'N',        ')',        ' ',        '=',        'D',        'H',        'A',        'E',
    'N' | 0x80, ' ',        '(',        'T',        'H',        'E',        'M',        ')',
    ' ',        '=',        'D',        'H',        'A',        'E',        'N' | 0x80, '(',
    'T',        'H',        'E',        'S',        'E',        ')',        ' ',        '=',
    'D',        'H',        'I',        'Y',        'Z' | 0x80, ' ',        '(',        'T',
    'H',        'E',        'N',        ')',        '=',        'D',        'H',        'E',
    'H',        'N' | 0x80, '(',        'T',        'H',        'R',        'O',        'U',
    'G',        'H',        ')',        '=',        'T',        'H',        'R',        'U',
    'W',        '4' | 0x80, '(',        'T',        'H',        'O',        'S',        'E',
    ')',        '=',        'D',        'H',        'O',        'H',        'Z' | 0x80, '(',
    'T',        'H',        'O',        'U',        'G',        'H',        ')',        ' ',
    '=',        'D',        'H',        'O',        'W' | 0x80, '(',        'T',        'O',
    'D',        'A',        'Y',        ')',        '=',        'T',        'U',        'X',
    'D',        'E',        'Y' | 0x80, '(',        'T',        'O',        'M',        'O',
    ')',        'R',        'R',        'O',        'W',        '=',        'T',        'U',
    'M',        'A',        'A',        '5' | 0x80, '(',        'T',        'O',        ')',
    'T',        'A',        'L',        '=',        'T',        'O',        'W',        '5' | 0x80,
    ' ',        '(',        'T',        'H',        'U',        'S',        ')',        '=',
    'D',        'H',        'A',        'H',        '4',        'S' | 0x80, '(',        'T',
    'H',        ')',        '=',        'T',        'H' | 0x80, '#',        ':',        '(',
    'T',        'E',        'D',        ')',        '=',        'T',        'I',        'X',
    'D' | 0x80, 'S',        '(',        'T',        'I',        ')',        '#',        'N',
    '=',        'C',        'H' | 0x80, '(',        'T',        'I',        ')',        'O',
    '=',        'S',        'H' | 0x80, '(',        'T',        'I',        ')',        'A',
    '=',        'S',        'H' | 0x80, '(',        'T',        'I',        'E',        'N',
    ')',        '=',        'S',        'H',        'U',        'N' | 0x80, '(',        'T',
    'U',        'R',        ')',        '#',        '=',        'C',        'H',        'E',
    'R' | 0x80, '(',        'T',        'U',        ')',        'A',        '=',        'C',
    'H',        'U',        'W' | 0x80, ' ',        '(',        'T',        'W',        'O',
    ')',        '=',        'T',        'U',        'W' | 0x80, '&',        '(',        'T',
    ')',        'E',        'N',        ' ',        '=' | 0x80, '(',        'T',        ')',
    '=',        'T' | 0x80,

    ']',        'U' | 0x80, ' ',        '(',        'U',        ')',        ' ',        '=',
    'Y',        'U',        'W',        '4' | 0x80, ' ',        '(',        'U',        'N',
    ')',        'I',        '=',        'Y',        'U',        'W',        'N' | 0x80, ' ',
    '(',        'U',        'N',        ')',        '=',        'A',        'H',        'N' | 0x80,
    ' ',        '(',        'U',        'P',        'O',        'N',        ')',        '=',
    'A',        'X',        'P',        'A',        'O',        'N' | 0x80, '@',        '(',
    'U',        'R',        ')',        '#',        '=',        'U',        'H',        '4',
    'R' | 0x80, '(',        'U',        'R',        ')',        '#',        '=',        'Y',
    'U',        'H',        '4',        'R' | 0x80, '(',        'U',        'R',        ')',
    '=',        'E',        'R' | 0x80, '(',        'U',        ')',        '^',        ' ',
    '=',        'A',        'H' | 0x80, '(',        'U',        ')',        '^',        '^',
    '=',        'A',        'H',        '5' | 0x80, '(',        'U',        'Y',        ')',
    '=',        'A',        'Y',        '5' | 0x80, ' ',        'G',        '(',        'U',
    ')',        '#',        '=' | 0x80, 'G',        '(',        'U',        ')',        '%',
    '=' | 0x80, 'G',        '(',        'U',        ')',        '#',        '=',        'W' | 0x80,
    '#',        'N',        '(',        'U',        ')',        '=',        'Y',        'U',
    'W' | 0x80, '@',        '(',        'U',        ')',        '=',        'U',        'W' | 0x80,
    '(',        'U',        ')',        '=',        'Y',        'U',        'W' | 0x80,

    ']',        'V' | 0x80, ' ',        '(',        'V',        ')',        ' ',        '=',
    'V',        'I',        'Y',        '4' | 0x80, '(',        'V',        'I',        'E',
    'W',        ')',        '=',        'V',        'Y',        'U',        'W',        '5' | 0x80,
    '(',        'V',        ')',        '=',        'V' | 0x80,

    ']',        'W' | 0x80, ' ',        '(',        'W',        ')',        ' ',        '=',
    'D',        'A',        'H',        '4',        'B',        'U',        'L',        'Y',
    'U',        'W' | 0x80, ' ',        '(',        'W',        'E',        'R',        'E',
    ')',        '=',        'W',        'E',        'R' | 0x80, '(',        'W',        'A',
    ')',        'S',        'H',        '=',        'W',        'A',        'A' | 0x80, '(',
    'W',        'A',        ')',        'S',        'T',        '=',        'W',        'E',
    'Y' | 0x80, '(',        'W',        'A',        ')',        'S',        '=',        'W',
    'A',        'H' | 0x80, '(',        'W',        'A',        ')',        'T',        '=',
    'W',        'A',        'A' | 0x80, '(',        'W',        'H',        'E',        'R',
    'E',        ')',        '=',        'W',        'H',        'E',        'H',        'R' | 0x80,
    '(',        'W',        'H',        'A',        'T',        ')',        '=',        'W',
    'H',        'A',        'H',        'T' | 0x80, '(',        'W',        'H',        'O',
    'L',        ')',        '=',        '/',        'H',        'O',        'W',        'L' | 0x80,
    '(',        'W',        'H',        'O',        ')',        '=',        '/',        'H',
    'U',        'W' | 0x80, '(',        'W',        'H',        ')',        '=',        'W',
    'H' | 0x80, '(',        'W',        'A',        'R',        ')',        '#',        '=',
    'W',        'E',        'H',        'R' | 0x80, '(',        'W',        'A',        'R',
    ')',        '=',        'W',        'A',        'O',        'R' | 0x80, '(',        'W',
    'O',        'R',        ')',        '^',        '=',        'W',        'E',        'R' | 0x80,
    '(',        'W',        'R',        ')',        '=',        'R' | 0x80, '(',        'W',
    'O',        'M',        ')',        'A',        '=',        'W',        'U',        'H',
    'M' | 0x80, '(',        'W',        'O',        'M',        ')',        'E',        '=',
    'W',        'I',        'H',        'M' | 0x80, '(',        'W',        'E',        'A',
    ')',        'R',        '=',        'W',        'E',        'H' | 0x80, '(',        'W',
    'A',        'N',        'T',        ')',        '=',        'W',        'A',        'A',
    '5',        'N',        'T' | 0x80, 'A',        'N',        'S',        '(',        'W',
    'E',        'R',        ')',        '=',        'E',        'R' | 0x80, '(',        'W',
    ')',        '=',        'W' | 0x80,

    ']',        'X' | 0x80, ' ',        '(',        'X',        ')',        ' ',        '=',
    'E',        'H',        '4',        'K',        'R' | 0x80, ' ',        '(',        'X',
    ')',        '=',        'Z' | 0x80, '(',        'X',        ')',        '=',        'K',
    'S' | 0x80,

    ']',        'Y' | 0x80, ' ',        '(',        'Y',        ')',        ' ',        '=',
    'W',        'A',        'Y',        '4' | 0x80, '(',        'Y',        'O',        'U',
    'N',        'G',        ')',        '=',        'Y',        'A',        'H',        'N',
    'X' | 0x80, ' ',        '(',        'Y',        'O',        'U',        'R',        ')',
    '=',        'Y',        'O',        'H',        'R' | 0x80, ' ',        '(',        'Y',
    'O',        'U',        ')',        '=',        'Y',        'U',        'W' | 0x80, ' ',
    '(',        'Y',        'E',        'S',        ')',        '=',        'Y',        'E',
    'H',        'S' | 0x80, ' ',        '(',        'Y',        ')',        '=',        'Y' | 0x80,
    'F',        '(',        'Y',        ')',        '=',        'A',        'Y' | 0x80, 'P',
    'S',        '(',        'Y',        'C',        'H',        ')',        '=',        'A',
    'Y',        'K' | 0x80, '#',        ':',        '^',        '(',        'Y',        ')',
    '=',        'I',        'Y' | 0x80, '#',        ':',        '^',        '(',        'Y',
    ')',        'I',        '=',        'I',        'Y' | 0x80, ' ',        ':',        '(',
    'Y',        ')',        ' ',        '=',        'A',        'Y' | 0x80, ' ',        ':',
    '(',        'Y',        ')',        '#',        '=',        'A',        'Y' | 0x80, ' ',
    ':',        '(',        'Y',        ')',        '^',        '+',        ':',        '#',
    '=',        'I',        'H' | 0x80, ' ',        ':',        '(',        'Y',        ')',
    '^',        '#',        '=',        'A',        'Y' | 0x80, '(',        'Y',        ')',
    '=',        'I',        'H' | 0x80,

    ']',        'Z' | 0x80, ' ',        '(',        'Z',        ')',        ' ',        '=',
    'Z',        'I',        'Y',        '4' | 0x80, '(',        'Z',        ')',        '=',
    'Z' | 0x80, 'j' | 0x80};

const unsigned char rules2[] = {
    '(',        'A',        ')',        '=' | 0x80, '(',        '!',        ')',        '=',
    '.' | 0x80, '(',        '"',        ')',        ' ',        '=',        '-',        'A',
    'H',        '5',        'N',        'K',        'W',        'O',        'W',        'T',
    '-' | 0x80, '(',        '"',        ')',        '=',        'K',        'W',        'O',
    'W',        '4',        'T',        '-' | 0x80, '(',        '#',        ')',        '=',
    ' ',        'N',        'A',        'H',        '4',        'M',        'B',        'E',
    'R' | 0x80, '(',        '$',        ')',        '=',        ' ',        'D',        'A',
    'A',        '4',        'L',        'E',        'R' | 0x80, '(',        '%',        ')',
    '=',        ' ',        'P',        'E',        'R',        'S',        'E',        'H',
    '4',        'N',        'T' | 0x80, '(',        '&',        ')',        '=',        ' ',
    'A',        'E',        'N',        'D' | 0x80, '(',        '\'',       ')',        '=' | 0x80,
    '(',        '*',        ')',        '=',        ' ',        'A',        'E',        '4',
    'S',        'T',        'E',        'R',        'I',        'H',        'S',        'K' | 0x80,
    '(',        '+',        ')',        '=',        ' ',        'P',        'L',        'A',
    'H',        '4',        'S' | 0x80, '(',        ',',        ')',        '=',        ',' | 0x80,
    ' ',        '(',        '-',        ')',        ' ',        '=',        '-' | 0x80, '(',
    '-',        ')',        '=' | 0x80, '(',        '.',        ')',        '=',        ' ',
    'P',        'O',        'Y',        'N',        'T' | 0x80, '(',        '/',        ')',
    '=',        ' ',        'S',        'L',        'A',        'E',        '4',        'S',
    'H' | 0x80, '(',        '0',        ')',        '=',        ' ',        'Z',        'I',
    'Y',        '4',        'R',        'O',        'W' | 0x80, ' ',        '(',        '1',
    'S',        'T',        ')',        '=',        'F',        'E',        'R',        '4',
    'S',        'T' | 0x80, ' ',        '(',        '1',        '0',        'T',        'H',
    ')',        '=',        'T',        'E',        'H',        '4',        'N',        'T',
    'H' | 0x80, '(',        '1',        ')',        '=',        ' ',        'W',        'A',
    'H',        '4',        'N' | 0x80, ' ',        '(',        '2',        'N',        'D',
    ')',        '=',        'S',        'E',        'H',        '4',        'K',        'U',
    'N',        'D' | 0x80, '(',        '2',        ')',        '=',        ' ',        'T',
    'U',        'W',        '4' | 0x80, ' ',        '(',        '3',        'R',        'D',
    ')',        '=',        'T',        'H',        'E',        'R',        '4',        'D' | 0x80,
    '(',        '3',        ')',        '=',        ' ',        'T',        'H',        'R',
    'I',        'Y',        '4' | 0x80, '(',        '4',        ')',        '=',        ' ',
    'F',        'O',        'H',        '4',        'R' | 0x80, ' ',        '(',        '5',
    'T',        'H',        ')',        '=',        'F',        'I',        'H',        '4',
    'F',        'T',        'H' | 0x80, '(',        '5',        ')',        '=',        ' ',
    'F',        'A',        'Y',        '4',        'V' | 0x80, ' ',        '(',        '6',
    '4',        ')',        ' ',        '=',        'S',        'I',        'H',        '4',
    'K',        'S',        'T',        'I',        'Y',        ' ',        'F',        'O',
    'H',        'R' | 0x80, '(',        '6',        ')',        '=',        ' ',        'S',
    'I',        'H',        '4',        'K',        'S' | 0x80, '(',        '7',        ')',
    '=',        ' ',        'S',        'E',        'H',        '4',        'V',        'U',
    'N' | 0x80, ' ',        '(',        '8',        'T',        'H',        ')',        '=',
    'E',        'Y',        '4',        'T',        'H' | 0x80, '(',        '8',        ')',
    '=',        ' ',        'E',        'Y',        '4',        'T' | 0x80, '(',        '9',
    ')',        '=',        ' ',        'N',        'A',        'Y',        '4',        'N' | 0x80,
    '(',        ':',        ')',        '=',        '.' | 0x80, '(',        ';',        ')',
    '=',        '.' | 0x80, '(',        '<',        ')',        '=',        ' ',        'L',
    'E',        'H',        '4',        'S',        ' ',        'D',        'H',        'A',
    'E',        'N' | 0x80, '(',        '=',        ')',        '=',        ' ',        'I',
    'Y',        '4',        'K',        'W',        'U',        'L',        'Z' | 0x80, '(',
    '>',        ')',        '=',        ' ',        'G',        'R',        'E',        'Y',
    '4',        'T',        'E',        'R',        ' ',        'D',        'H',        'A',
    'E',        'N' | 0x80, '(',        '?',        ')',        '=',        '?' | 0x80, '(',
    '@',        ')',        '=',        ' ',        'A',        'E',        '6',        'T' | 0x80,
    '(',        '^',        ')',        '=',        ' ',        'K',        'A',        'E',
    '4',        'R',        'I',        'X',        'T' | 0x80, ']',        'A' | 0x80};

//26 items. From 'A' to 'Z'
// positions for mem62 and mem63 for each character
const unsigned char tab37489[] = {0,   149, 247, 162, 57, 197, 6,  126, 199, 38, 55, 78, 145,
                                  241, 85,  161, 254, 36, 69,  45, 167, 54,  83, 46, 71, 218};

const unsigned char tab37515[] = {125, 126, 126, 127, 128, 129, 130, 130, 130, 132, 132, 132, 132,
                                  132, 133, 135, 135, 136, 136, 137, 138, 139, 139, 140, 140, 140};

void STM32SAM::Output8BitAry(int index, unsigned char ary[5]) {
    int k;

    uint32_t bufferposOld = bufferpos;

    bufferpos += timetable[oldtimetableindex][index];
    oldtimetableindex = index;

    int sample_uS = bufferpos - bufferposOld;

    uint32_t f = 0;

    // write a little bit in advance
    for(k = 0; k < 5; k++) {
        //   buffer[bufferpos / 50 + k] = ary[k];

        // f = micros() + sample_uS / (_STM32SAM_SPEED + 1);
        // while(micros() < f) {
        // };
        f = sample_uS / (_STM32SAM_SPEED + 1);
        furi_delay_us(f);
        SetAUDIO(ary[k]);
        //  delayMicroseconds(sample_uS / 5 );
    }

    //  SetAUDIO(ary[0]);
}

void STM32SAM::Output8Bit(int index, unsigned char A) {
    unsigned char ary[5] = {A, A, A, A, A};
    Output8BitAry(index, ary);
}

//written by me because of different table positions.
// mem[47] = ...
// 168=pitches
// 169=frequency1
// 170=frequency2
// 171=frequency3
// 172=amplitude1
// 173=amplitude2
// 174=amplitude3
unsigned char STM32SAM::Read(unsigned char p, unsigned char Y) {
    switch(p) {
    case 168:
        return pitches[Y];
    case 169:
        return frequency1[Y];
    case 170:
        return frequency2[Y];
    case 171:
        return frequency3[Y];
    case 172:
        return amplitude1[Y];
    case 173:
        return amplitude2[Y];
    case 174:
        return amplitude3[Y];
    }
    // Serial1.println("Error reading to tables");
    return 0;
}

void STM32SAM::Write(unsigned char p, unsigned char Y, unsigned char value) {
    switch(p) {
    case 168:
        pitches[Y] = value;
        return;
    case 169:
        frequency1[Y] = value;
        return;
    case 170:
        frequency2[Y] = value;
        return;
    case 171:
        frequency3[Y] = value;
        return;
    case 172:
        amplitude1[Y] = value;
        return;
    case 173:
        amplitude2[Y] = value;
        return;
    case 174:
        amplitude3[Y] = value;
        return;
    }
    //Serial1.println("Error writing to tables\n");
}

// -------------------------------------------------------------------------
//Code48227
// Render a sampled sound from the sampleTable.
//
//   Phoneme   Sample Start   Sample End
//   32: S*    15             255
//   33: SH    257            511
//   34: F*    559            767
//   35: TH    583            767
//   36: /H    903            1023
//   37: /X    1135           1279
//   38: Z*    84             119
//   39: ZH    340            375
//   40: V*    596            639
//   41: DH    596            631
//
//   42: CH
//   43: **    399            511
//
//   44: J*
//   45: **    257            276
//   46: **
//
//   66: P*
//   67: **    743            767
//   68: **
//
//   69: T*
//   70: **    231            255
//   71: **
//
// The SampledPhonemesTable[] holds flags indicating if a phoneme is
// voiced or not. If the upper 5 bits are zero, the sample is voiced.
//
// Samples in the sampleTable are compressed, with bits being converted to
// bytes from high bit to low, as follows:
//
//   unvoiced 0 bit   -> X
//   unvoiced 1 bit   -> 5
//
//   voiced 0 bit     -> 6
//   voiced 1 bit     -> 24
//
// Where X is a value from the table:
//
//   { 0x18, 0x1A, 0x17, 0x17, 0x17 };
//
// The index into this table is determined by masking off the lower
// 3 bits from the SampledPhonemesTable:
//
//        index = (SampledPhonemesTable[i] & 7) - 1;
//
// For voices samples, samples are interleaved between voiced output.

// Code48227()
void STM32SAM::RenderSample(unsigned char* mem66) {
    int tempA;
    // current phoneme's index
    mem49 = Y;

    // mask low three bits and subtract 1 get value to
    // convert 0 bits on unvoiced samples.
    A = mem39 & 7;
    X = A - 1;

    // store the result
    mem56 = X;

    // determine which offset to use from table { 0x18, 0x1A, 0x17, 0x17, 0x17 }
    // T, S, Z                0          0x18
    // CH, J, SH, ZH          1          0x1A
    // P, F*, V, TH, DH       2          0x17
    // /H                     3          0x17
    // /X                     4          0x17

    // get value from the table
    mem53 = tab48426[X];
    mem47 = X; //46016+mem[56]*256

    // voiced sample?
    A = mem39 & 248;
    if(A == 0) {
        // voiced phoneme: Z*, ZH, V*, DH
        Y = mem49;
        A = pitches[mem49] >> 4;

        // jump to voiced portion
        goto pos48315;
    }

    Y = A ^ 255;
pos48274:

    // step through the 8 bits in the sample
    mem56 = 8;

    // get the next sample from the table
    // mem47*256 = offset to start of samples
    A = sampleTable[mem47 * 256 + Y];
pos48280:

    // left shift to get the high bit
    tempA = A;
    A = A << 1;
    //48281: BCC 48290

    // bit not set?
    if((tempA & 128) == 0) {
        // convert the bit to value from table
        X = mem53;
        //mem[54296] = X;
        // output the byte
        Output8Bit(1, (X & 0x0f) * 16);
        // if X != 0, exit loop
        if(X != 0) goto pos48296;
    }

    // output a 5 for the on bit
    Output8Bit(2, 5 * 16);

    //48295: NOP
pos48296:

    X = 0;

    // decrement counter
    mem56--;

    // if not done, jump to top of loop
    if(mem56 != 0) goto pos48280;

    // increment position
    Y++;
    if(Y != 0) goto pos48274;

    // restore values and return
    mem44 = 1;
    Y = mem49;
    return;

    unsigned char phase1;

pos48315:
    // handle voiced samples here

    // number of samples?
    phase1 = A ^ 255;

    Y = *mem66;
    do {
        //pos48321:

        // shift through all 8 bits
        mem56 = 8;
        //A = Read(mem47, Y);

        // fetch value from table
        A = sampleTable[mem47 * 256 + Y];

        // loop 8 times
        //pos48327:
        do {
            //48327: ASL A
            //48328: BCC 48337

            // left shift and check high bit
            tempA = A;
            A = A << 1;
            if((tempA & 128) != 0) {
                // if bit set, output 26
                X = 26;
                Output8Bit(3, (X & 0xf) * 16);
            } else {
                //timetable 4
                // bit is not set, output a 6
                X = 6;
                Output8Bit(4, (X & 0xf) * 16);
            }

            mem56--;
        } while(mem56 != 0);

        // move ahead in the table
        Y++;

        // continue until counter done
        phase1++;

    } while(phase1 != 0);
    //  if (phase1 != 0) goto pos48321;

    // restore values and return
    A = 1;
    mem44 = 1;
    *mem66 = Y;
    Y = mem49;
    return;
}

// RENDER THE PHONEMES IN THE LIST
//
// The phoneme list is converted into sound through the steps:
//
// 1. Copy each phoneme <length> number of times into the frames list,
//    where each frame represents 10 milliseconds of sound.
//
// 2. Determine the transitions lengths between phonemes, and linearly
//    interpolate the values across the frames.
//
// 3. Offset the pitches by the fundamental frequency.
//
// 4. Render the each frame.

//void Code47574()
void STM32SAM::Render() {
    unsigned char phase1 = 0; //mem43
    unsigned char phase2 = 0;
    unsigned char phase3 = 0;
    unsigned char mem66 = 0;
    unsigned char mem38 = 0;
    unsigned char mem40 = 0;
    unsigned char speedcounter = 0; //mem45
    unsigned char mem48 = 0;
    int i;
    if(phonemeIndexOutput[0] == 255) return; //exit if no data

    A = 0;
    X = 0;
    mem44 = 0;

    // CREATE FRAMES
    //
    // The length parameter in the list corresponds to the number of frames
    // to expand the phoneme to. Each frame represents 10 milliseconds of time.
    // So a phoneme with a length of 7 = 7 frames = 70 milliseconds duration.
    //
    // The parameters are copied from the phoneme to the frame verbatim.

    // pos47587:
    do {
        // get the index
        Y = mem44;
        // get the phoneme at the index
        A = phonemeIndexOutput[mem44];
        mem56 = A;

        // if terminal phoneme, exit the loop
        if(A == 255) break;

        // period phoneme *.
        if(A == 1) {
            // add rising inflection
            A = 1;
            mem48 = 1;
            //goto pos48376;
            AddInflection(mem48, phase1);
        }
        /*
      if (A == 2) goto pos48372;
    */

        // question mark phoneme?
        if(A == 2) {
            // create falling inflection
            mem48 = 255;
            AddInflection(mem48, phase1);
        }
        //  pos47615:

        // get the stress amount (more stress = higher pitch)
        phase1 = tab47492[stressOutput[Y] + 1];

        // get number of frames to write
        phase2 = phonemeLengthOutput[Y];
        Y = mem56;

        // copy from the source to the frames list
        do {
            frequency1[X] = freq1data[Y]; // F1 frequency
            frequency2[X] = freq2data[Y]; // F2 frequency
            frequency3[X] = freq3data[Y]; // F3 frequency
            amplitude1[X] = ampl1data[Y]; // F1 amplitude
            amplitude2[X] = ampl2data[Y]; // F2 amplitude
            amplitude3[X] = ampl3data[Y]; // F3 amplitude
            sampledConsonantFlag[X] =
                sampledConsonantFlags[Y]; // phoneme data for sampled consonants
            pitches[X] = pitch + phase1; // pitch
            X++;
            phase2--;
        } while(phase2 != 0);
        mem44++;
    } while(mem44 != 0);
    // -------------------
    //pos47694:

    // CREATE TRANSITIONS
    //
    // Linear transitions are now created to smoothly connect the
    // end of one sustained portion of a phoneme to the following
    // phoneme.
    //
    // To do this, three tables are used:
    //
    //  Table         Purpose
    //  =========     ==================================================
    //  blendRank     Determines which phoneme's blend values are used.
    //
    //  blendOut      The number of frames at the end of the phoneme that
    //                will be used to transition to the following phoneme.
    //
    //  blendIn       The number of frames of the following phoneme that
    //                will be used to transition into that phoneme.
    //
    // In creating a transition between two phonemes, the phoneme
    // with the HIGHEST rank is used. Phonemes are ranked on how much
    // their identity is based on their transitions. For example,
    // vowels are and diphthongs are identified by their sustained portion,
    // rather than the transitions, so they are given low values. In contrast,
    // stop consonants (P, B, T, K) and glides (Y, L) are almost entirely
    // defined by their transitions, and are given high rank values.
    //
    // Here are the rankings used by SAM:
    //
    //     Rank    Type                         Phonemes
    //     2       All vowels                   IY, IH, etc.
    //     5       Diphthong endings            YX, WX, ER
    //     8       Terminal liquid consonants   LX, WX, YX, N, NX
    //     9       Liquid consonants            L, RX, W
    //     10      Glide                        R, OH
    //     11      Glide                        WH
    //     18      Voiceless fricatives         S, SH, F, TH
    //     20      Voiced fricatives            Z, ZH, V, DH
    //     23      Plosives, stop consonants    P, T, K, KX, DX, CH
    //     26      Stop consonants              J, GX, B, D, G
    //     27-29   Stop consonants (internal)   **
    //     30      Unvoiced consonants          /H, /X and Q*
    //     160     Nasal                        M
    //
    // To determine how many frames to use, the two phonemes are
    // compared using the blendRank[] table. The phoneme with the
    // higher rank is selected. In case of a tie, a blend of each is used:
    //
    //      if blendRank[phoneme1] ==  blendRank[phomneme2]
    //          // use lengths from each phoneme
    //          outBlendFrames = outBlend[phoneme1]
    //          inBlendFrames = outBlend[phoneme2]
    //      else if blendRank[phoneme1] > blendRank[phoneme2]
    //          // use lengths from first phoneme
    //          outBlendFrames = outBlendLength[phoneme1]
    //          inBlendFrames = inBlendLength[phoneme1]
    //      else
    //          // use lengths from the second phoneme
    //          // note that in and out are SWAPPED!
    //          outBlendFrames = inBlendLength[phoneme2]
    //          inBlendFrames = outBlendLength[phoneme2]
    //
    // Blend lengths can't be less than zero.
    //
    // Transitions are assumed to be symetrical, so if the transition
    // values for the second phoneme are used, the inBlendLength and
    // outBlendLength values are SWAPPED.
    //
    // For most of the parameters, SAM interpolates over the range of the last
    // outBlendFrames-1 and the first inBlendFrames.
    //
    // The exception to this is the Pitch[] parameter, which is interpolates the
    // pitch from the CENTER of the current phoneme to the CENTER of the next
    // phoneme.
    //
    // Here are two examples. First, For example, consider the word "SUN" (S AH N)
    //
    //    Phoneme   Duration    BlendWeight    OutBlendFrames    InBlendFrames
    //    S         2           18             1                 3
    //    AH        8           2              4                 4
    //    N         7           8              1                 2
    //
    // The formant transitions for the output frames are calculated as follows:
    //
    //     flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch
    //    ------------------------------------------------
    // S
    //    241     0     6     0    73     0    99    61   Use S (weight 18) for transition instead of AH (weight 2)
    //    241     0     6     0    73     0    99    61   <-- (OutBlendFrames-1) = (1-1) = 0 frames
    // AH
    //      0     2    10     2    66     0    96    59 * <-- InBlendFrames = 3 frames
    //      0     4    14     3    59     0    93    57 *
    //      0     8    18     5    52     0    90    55 *
    //      0    15    22     9    44     1    87    53
    //      0    15    22     9    44     1    87    53
    //      0    15    22     9    44     1    87    53   Use N (weight 8) for transition instead of AH (weight 2).
    //      0    15    22     9    44     1    87    53   Since N is second phoneme, reverse the IN and OUT values.
    //      0    11    17     8    47     1    98    56 * <-- (InBlendFrames-1) = (2-1) = 1 frames
    // N
    //      0     8    12     6    50     1   109    58 * <-- OutBlendFrames = 1
    //      0     5     6     5    54     0   121    61
    //      0     5     6     5    54     0   121    61
    //      0     5     6     5    54     0   121    61
    //      0     5     6     5    54     0   121    61
    //      0     5     6     5    54     0   121    61
    //      0     5     6     5    54     0   121    61
    //
    // Now, consider the reverse "NUS" (N AH S):
    //
    //     flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch
    //    ------------------------------------------------
    // N
    //     0     5     6     5    54     0   121    61
    //     0     5     6     5    54     0   121    61
    //     0     5     6     5    54     0   121    61
    //     0     5     6     5    54     0   121    61
    //     0     5     6     5    54     0   121    61
    //     0     5     6     5    54     0   121    61   Use N (weight 8) for transition instead of AH (weight 2)
    //     0     5     6     5    54     0   121    61   <-- (OutBlendFrames-1) = (1-1) = 0 frames
    // AH
    //     0     8    11     6    51     0   110    59 * <-- InBlendFrames = 2
    //     0    11    16     8    48     0    99    56 *
    //     0    15    22     9    44     1    87    53   Use S (weight 18) for transition instead of AH (weight 2)
    //     0    15    22     9    44     1    87    53   Since S is second phoneme, reverse the IN and OUT values.
    //     0     9    18     5    51     1    90    55 * <-- (InBlendFrames-1) = (3-1) = 2
    //     0     4    14     3    58     1    93    57 *
    // S
    //   241     2    10     2    65     1    96    59 * <-- OutBlendFrames = 1
    //   241     0     6     0    73     0    99    61

    A = 0;
    mem44 = 0;
    mem49 = 0; // mem49 starts at as 0
    X = 0;
    while(1) //while No. 1
    {
        // get the current and following phoneme
        Y = phonemeIndexOutput[X];
        A = phonemeIndexOutput[X + 1];
        X++;

        // exit loop at end token
        if(A == 255) break; //goto pos47970;

        // get the ranking of each phoneme
        X = A;
        mem56 = blendRank[A];
        A = blendRank[Y];

        // compare the rank - lower rank value is stronger
        if(A == mem56) {
            // same rank, so use out blend lengths from each phoneme
            phase1 = outBlendLength[Y];
            phase2 = outBlendLength[X];
        } else if(A < mem56) {
            // first phoneme is stronger, so us it's blend lengths
            phase1 = inBlendLength[X];
            phase2 = outBlendLength[X];
        } else {
            // second phoneme is stronger, so use it's blend lengths
            // note the out/in are swapped
            phase1 = outBlendLength[Y];
            phase2 = inBlendLength[Y];
        }

        Y = mem44;
        A = mem49 + phonemeLengthOutput[mem44]; // A is mem49 + length
        mem49 = A; // mem49 now holds length + position
        A = A + phase2; //Maybe Problem because of carry flag

        //47776: ADC 42
        speedcounter = A;
        mem47 = 168;
        phase3 = mem49 - phase1; // what is mem49
        A = phase1 + phase2; // total transition?
        mem38 = A;

        X = A;
        X -= 2;
        if((X & 128) == 0)
            do //while No. 2
            {
                //pos47810:

                // mem47 is used to index the tables:
                // 168  pitches[]
                // 169  frequency1
                // 170  frequency2
                // 171  frequency3
                // 172  amplitude1
                // 173  amplitude2
                // 174  amplitude3

                mem40 = mem38;

                if(mem47 == 168) // pitch
                {
                    // unlike the other values, the pitches[] interpolates from
                    // the middle of the current phoneme to the middle of the
                    // next phoneme

                    unsigned char mem36, mem37;
                    // half the width of the current phoneme
                    mem36 = phonemeLengthOutput[mem44] >> 1;
                    // half the width of the next phoneme
                    mem37 = phonemeLengthOutput[mem44 + 1] >> 1;
                    // sum the values
                    mem40 = mem36 + mem37; // length of both halves
                    mem37 += mem49; // center of next phoneme
                    mem36 = mem49 - mem36; // center index of current phoneme
                    A = Read(
                        mem47, mem37); // value at center of next phoneme - end interpolation value
                    //A = mem[address];

                    Y = mem36; // start index of interpolation
                    mem53 = A - Read(mem47, mem36); // value to center of current phoneme
                } else {
                    // value to interpolate to
                    A = Read(mem47, speedcounter);
                    // position to start interpolation from
                    Y = phase3;
                    // value to interpolate from
                    mem53 = A - Read(mem47, phase3);
                }

                //Code47503(mem40);
                // ML : Code47503 is division with remainder, and mem50 gets the sign

                // calculate change per frame
                signed char m53 = (signed char)mem53;
                mem50 = mem53 & 128;
                unsigned char m53abs = abs(m53);
                mem51 = m53abs % mem40; //abs((char)m53) % mem40;
                mem53 = (unsigned char)((signed char)(m53) / mem40);

                // interpolation range
                X = mem40; // number of frames to interpolate over
                Y = phase3; // starting frame

                // linearly interpolate values

                mem56 = 0;
                //47907: CLC
                //pos47908:
                while(1) //while No. 3
                {
                    A = Read(mem47, Y) + mem53; //carry always cleared

                    mem48 = A;
                    Y++;
                    X--;
                    if(X == 0) break;

                    mem56 += mem51;
                    if(mem56 >= mem40) //???
                    {
                        mem56 -= mem40; //carry? is set
                        //if ((mem56 & 128)==0)
                        if((mem50 & 128) == 0) {
                            //47935: BIT 50
                            //47937: BMI 47943
                            if(mem48 != 0) mem48++;
                        } else
                            mem48--;
                    }
                    //pos47945:
                    Write(mem47, Y, mem48);
                } //while No. 3

                //pos47952:
                mem47++;
                //if (mem47 != 175) goto pos47810;
            } while(mem47 != 175); //while No. 2
        //pos47963:
        mem44++;
        X = mem44;
    } //while No. 1

    //goto pos47701;
    //pos47970:

    // add the length of this phoneme
    mem48 = mem49 + phonemeLengthOutput[mem44];

    // ASSIGN PITCH CONTOUR
    //
    // This subtracts the F1 frequency from the pitch to create a
    // pitch contour. Without this, the output would be at a single
    // pitch level (monotone).

    // don't adjust pitch if in sing mode
    if(!singmode) {
        // iterate through the buffer
        for(i = 0; i < 256; i++) {
            // subtract half the frequency of the formant 1.
            // this adds variety to the voice
            pitches[i] -= (frequency1[i] >> 1);
        }
    }

    phase1 = 0;
    phase2 = 0;
    phase3 = 0;
    mem49 = 0;
    speedcounter = 72; //sam standard speed

    // RESCALE AMPLITUDE
    //
    // Rescale volume from a linear scale to decibels.
    //

    //amplitude rescaling
    for(i = 255; i >= 0; i--) {
        amplitude1[i] = amplitudeRescale[amplitude1[i]];
        amplitude2[i] = amplitudeRescale[amplitude2[i]];
        amplitude3[i] = amplitudeRescale[amplitude3[i]];
    }

    Y = 0;
    A = pitches[0];
    mem44 = A;
    X = A;
    mem38 = A - (A >> 2); // 3/4*A ???

    // PROCESS THE FRAMES
    //
    // In traditional vocal synthesis, the glottal pulse drives filters, which
    // are attenuated to the frequencies of the formants.
    //
    // SAM generates these formants directly with sin and rectangular waves.
    // To simulate them being driven by the glottal pulse, the waveforms are
    // reset at the beginning of each glottal pulse.

    //finally the loop for sound output
    //pos48078:
    while(1) {
        // get the sampled information on the phoneme
        A = sampledConsonantFlag[Y];
        mem39 = A;

        // unvoiced sampled phoneme?
        A = A & 248;
        if(A != 0) {
            // render the sample for the phoneme
            RenderSample(&mem66);

            // skip ahead two in the phoneme buffer
            Y += 2;
            mem48 -= 2;
        } else {
            // simulate the glottal pulse and formants
            unsigned char ary[5];
            unsigned int p1 =
                phase1 * 256; // Fixed point integers because we need to divide later on
            unsigned int p2 = phase2 * 256;
            unsigned int p3 = phase3 * 256;
            int k;
            for(k = 0; k < 5; k++) {
                signed char sp1 = (signed char)sinus[0xff & (p1 >> 8)];
                signed char sp2 = (signed char)sinus[0xff & (p2 >> 8)];
                signed char rp3 = (signed char)rectangle[0xff & (p3 >> 8)];
                signed int sin1 = sp1 * ((unsigned char)amplitude1[Y] & 0x0f);
                signed int sin2 = sp2 * ((unsigned char)amplitude2[Y] & 0x0f);
                signed int rect = rp3 * ((unsigned char)amplitude3[Y] & 0x0f);
                signed int mux = sin1 + sin2 + rect;
                mux /= 32;
                mux += 128; // Go from signed to unsigned amplitude
                ary[k] = mux;
                p1 += frequency1[Y] * 256 / 4; // Compromise, this becomes a shift and works well
                p2 += frequency2[Y] * 256 / 4;
                p3 += frequency3[Y] * 256 / 4;
            }
            // output the accumulated value
            Output8BitAry(0, ary);
            speedcounter--;
            if(speedcounter != 0) goto pos48155;
            Y++; //go to next amplitude

            // decrement the frame count
            mem48--;
        }

        // if the frame count is zero, exit the loop
        if(mem48 == 0) return;
        speedcounter = speed;
    pos48155:

        // decrement the remaining length of the glottal pulse
        mem44--;

        // finished with a glottal pulse?
        if(mem44 == 0) {
        pos48159:
            // fetch the next glottal pulse length
            A = pitches[Y];
            mem44 = A;
            A = A - (A >> 2);
            mem38 = A;

            // reset the formant wave generators to keep them in
            // sync with the glottal pulse
            phase1 = 0;
            phase2 = 0;
            phase3 = 0;
            continue;
        }

        // decrement the count
        mem38--;

        // is the count non-zero and the sampled flag is zero?
        if((mem38 != 0) || (mem39 == 0)) {
            // reset the phase of the formants to match the pulse
            phase1 += frequency1[Y];
            phase2 += frequency2[Y];
            phase3 += frequency3[Y];
            continue;
        }

        // voiced sampled phonemes interleave the sample with the
        // glottal pulse. The sample flag is non-zero, so render
        // the sample for the phoneme.
        RenderSample(&mem66);
        goto pos48159;
    } //while

    // The following code is never reached. It's left over from when
    // the voiced sample code was part of this loop, instead of part
    // of RenderSample();

    //pos48315:
    int tempA;
    phase1 = A ^ 255;
    Y = mem66;
    do {
        //pos48321:

        mem56 = 8;
        A = Read(mem47, Y);

        //pos48327:
        do {
            //48327: ASL A
            //48328: BCC 48337
            tempA = A;
            A = A << 1;
            if((tempA & 128) != 0) {
                X = 26;
                // mem[54296] = X;
                bufferpos += 150;
                //
                //
                //        buffer[bufferpos / 50] = (X & 15) * 16;
                //
                //

            } else {
                //mem[54296] = 6;
                X = 6;
                bufferpos += 150;
                //
                //        buffer[bufferpos / 50] = (X & 15) * 16;
                //
                //
            }

            for(X = wait2; X > 0; X--)
                ; //wait
            mem56--;
        } while(mem56 != 0);

        Y++;
        phase1++;

    } while(phase1 != 0);
    //  if (phase1 != 0) goto pos48321;
    A = 1;
    mem44 = 1;
    mem66 = Y;
    Y = mem49;
    return;
}

// Create a rising or falling inflection 30 frames prior to
// index X. A rising inflection is used for questions, and
// a falling inflection is used for statements.

void STM32SAM::AddInflection(unsigned char mem48, unsigned char phase1) {
    //pos48372:
    //  mem48 = 255;
    //pos48376:

    // store the location of the punctuation
    mem49 = X;
    A = X;
    int Atemp = A;

    // backup 30 frames
    A = A - 30;
    // if index is before buffer, point to start of buffer
    if(Atemp <= 30) A = 0;
    X = A;

    // FIXME: Explain this fix better, it's not obvious
    // ML : A =, fixes a problem with invalid pitch with '.'
    while((A = pitches[X]) == 127) X++;

pos48398:
    //48398: CLC
    //48399: ADC 48

    // add the inflection direction
    A += mem48;
    phase1 = A;

    // set the inflection
    pitches[X] = A;
pos48406:

    // increment the position
    X++;

    // exit if the punctuation has been reached
    if(X == mem49) return; //goto pos47615;
    if(pitches[X] == 255) goto pos48406;
    A = phase1;
    goto pos48398;
}

/*
    SAM's voice can be altered by changing the frequencies of the
    mouth formant (F1) and the throat formant (F2). Only the voiced
    phonemes (5-29 and 48-53) are altered.
*/
void STM32SAM::SetMouthThroat() {
    unsigned char initialFrequency;
    unsigned char newFrequency = 0;
    //unsigned char mouth; //mem38880
    //unsigned char throat; //mem38881

    // mouth formants (F1) 5..29
    unsigned char mouthFormants5_29[30] = {0,  0,  0,  0,  0,  10, 14, 19, 24, 27,
                                           23, 21, 16, 20, 14, 18, 14, 18, 18, 16,
                                           13, 15, 11, 18, 14, 11, 9,  6,  6,  6};

    // throat formants (F2) 5..29
    unsigned char throatFormants5_29[30] = {255, 255, 255, 255, 255, 84, 73, 67, 63, 40,
                                            44,  31,  37,  45,  73,  49, 36, 30, 51, 37,
                                            29,  69,  24,  50,  30,  24, 83, 46, 54, 86};

    // there must be no zeros in this 2 tables
    // formant 1 frequencies (mouth) 48..53
    unsigned char mouthFormants48_53[6] = {19, 27, 21, 27, 18, 13};

    // formant 2 frequencies (throat) 48..53
    unsigned char throatFormants48_53[6] = {72, 39, 31, 43, 30, 34};

    unsigned char pos = 5; //mem39216
    //pos38942:
    // recalculate formant frequencies 5..29 for the mouth (F1) and throat (F2)
    while(pos != 30) {
        // recalculate mouth frequency
        initialFrequency = mouthFormants5_29[pos];
        if(initialFrequency != 0) newFrequency = trans(mouth, initialFrequency);
        freq1data[pos] = newFrequency;

        // recalculate throat frequency
        initialFrequency = throatFormants5_29[pos];
        if(initialFrequency != 0) newFrequency = trans(throat, initialFrequency);
        freq2data[pos] = newFrequency;
        pos++;
    }

    //pos39059:
    // recalculate formant frequencies 48..53
    pos = 48;
    Y = 0;
    while(pos != 54) {
        // recalculate F1 (mouth formant)
        initialFrequency = mouthFormants48_53[Y];
        newFrequency = trans(mouth, initialFrequency);
        freq1data[pos] = newFrequency;

        // recalculate F2 (throat formant)
        initialFrequency = throatFormants48_53[Y];
        newFrequency = trans(throat, initialFrequency);
        freq2data[pos] = newFrequency;
        Y++;
        pos++;
    }
}

//return = (mem39212*mem39213) >> 1
unsigned char STM32SAM::trans(unsigned char mem39212, unsigned char mem39213) {
    //pos39008:
    unsigned char carry;
    int temp;
    unsigned char mem39214, mem39215;
    A = 0;
    mem39215 = 0;
    mem39214 = 0;
    X = 8;
    do {
        carry = mem39212 & 1;
        mem39212 = mem39212 >> 1;
        if(carry != 0) {
            /*
                  39018: LSR 39212
                  39021: BCC 39033
      */
            carry = 0;
            A = mem39215;
            temp = (int)A + (int)mem39213;
            A = A + mem39213;
            if(temp > 255) carry = 1;
            mem39215 = A;
        }
        temp = mem39215 & 1;
        mem39215 = (mem39215 >> 1) | (carry ? 128 : 0);
        carry = temp;
        //39033: ROR 39215
        X--;
    } while(X != 0);
    temp = mem39214 & 128;
    mem39214 = (mem39214 << 1) | (carry ? 1 : 0);
    carry = temp;
    temp = mem39215 & 128;
    mem39215 = (mem39215 << 1) | (carry ? 1 : 0);
    carry = temp;

    return mem39215;
}

////////////////////////////////////////////////////////////////////////////////////////////
//
//           Sam
//
////////////////////////////////////////////////////////////////////////////////////////////

//char input[]={"/HAALAOAO MAYN NAAMAEAE IHSTT SAEBAASTTIHAAN \x9b\x9b\0"};
//unsigned char input[]={"/HAALAOAO \x9b\0"};
//unsigned char input[]={"AA \x9b\0"};
//unsigned char input[] = {"GUH5DEHN TAEG\x9b\0"};

//unsigned char input[]={"AY5 AEM EY TAO4LXKIHNX KAX4MPYUX4TAH. GOW4 AH/HEH3D PAHNK.MEYK MAY8 DEY.\x9b\0"};
//unsigned char input[]={"/HEH3LOW2, /HAW AH YUX2 TUXDEY. AY /HOH3P YUX AH FIYLIHNX OW4 KEY.\x9b\0"};
//unsigned char input[]={"/HEY2, DHIHS IH3Z GREY2T. /HAH /HAH /HAH.AYL BIY5 BAEK.\x9b\0"};
//unsigned char input[]={"/HAH /HAH /HAH \x9b\0"};
//unsigned char input[]={"/HAH /HAH /HAH.\x9b\0"};
//unsigned char input[]={".TUW BIY5Y3,, OHR NAA3T - TUW BIY5IYIY., DHAE4T IHZ DHAH KWEH4SCHAHN.\x9b\0"};
//unsigned char input[]={"/HEY2, DHIHS \x9b\0"};

//unsigned char input[]={" IYIHEHAEAAAHAOOHUHUXERAXIX  \x9b\0"};
//unsigned char input[]={" RLWWYMNNXBDGJZZHVDH \x9b\0"};
//unsigned char input[]={" SSHFTHPTKCH/H \x9b\0"};

//unsigned char input[]={" EYAYOYAWOWUW ULUMUNQ YXWXRXLX/XDX\x9b\0"};

void STM32SAM::SetInput(char* _input) {
    int i, l;
    l = strlen(_input);
    if(l > 254) l = 254;
    for(i = 0; i < l; i++) {
        input[i] = _input[i];
    }
    input[l] = 0;
}

// 168=pitches
// 169=frequency1
// 170=frequency2
// 171=frequency3
// 172=amplitude1
// 173=amplitude2
// 174=amplitude3

void STM32SAM::Init() {
    bufferpos = 0;
    int i;
    SetMouthThroat();

    bufferpos = 0;
    // TODO, check for free the memory, 10 seconds of output should be more than enough
    //buffer = malloc(22050*10);

    // buffer = (char*) calloc(1, sizeof(char));

    /*
    freq2data = &mem[45136];
    freq1data = &mem[45056];
    freq3data = &mem[45216];
  */
    //pitches = &mem[43008];
    /*
    frequency1 = &mem[43264];
    frequency2 = &mem[43520];
    frequency3 = &mem[43776];
  */
    /*
    amplitude1 = &mem[44032];
    amplitude2 = &mem[44288];
    amplitude3 = &mem[44544];
  */
    //phoneme = &mem[39904];
    /*
    ampl1data = &mem[45296];
    ampl2data = &mem[45376];
    ampl3data = &mem[45456];
  */

    for(i = 0; i < 256; i++) {
        stress[i] = 0;
        phonemeLength[i] = 0;
    }

    for(i = 0; i < 60; i++) {
        phonemeIndexOutput[i] = 0;
        stressOutput[i] = 0;
        phonemeLengthOutput[i] = 0;
    }
    phonemeindex[255] =
        255; //to prevent buffer overflow // ML : changed from 32 to 255 to stop freezing with long inputs
}

//int Code39771()
int STM32SAM::SAMMain() {
    Init();
    phonemeindex[255] = 32; //to prevent buffer overflow

    if(!Parser1()) {
        return 0;
    }

    Parser2();
    CopyStress();
    SetPhonemeLength();
    AdjustLengths();
    Code41240();
    do {
        A = phonemeindex[X];
        if(A > 80) {
            phonemeindex[X] = 255;
            break; // error: delete all behind it
        }
        X++;
    } while(X != 0);

    //pos39848:
    InsertBreath();

    //mem[40158] = 255;

    PrepareOutput();

    return 1;
}

//void Code48547()
void STM32SAM::PrepareOutput() {
    A = 0;
    X = 0;
    Y = 0;

    //pos48551:
    while(1) {
        A = phonemeindex[X];
        if(A == 255) {
            A = 255;
            phonemeIndexOutput[Y] = 255;
            Render();
            return;
        }
        if(A == 254) {
            X++;
            int temp = X;
            //mem[48546] = X;
            phonemeIndexOutput[Y] = 255;
            Render();
            //X = mem[48546];
            X = temp;
            Y = 0;
            continue;
        }

        if(A == 0) {
            X++;
            continue;
        }

        phonemeIndexOutput[Y] = A;
        phonemeLengthOutput[Y] = phonemeLength[X];
        stressOutput[Y] = stress[X];
        X++;
        Y++;
    }
}

//void Code41014()
void STM32SAM::Insert(
    unsigned char position /*var57*/,
    unsigned char mem60,
    unsigned char mem59,
    unsigned char mem58) {
    int i;
    for(i = 253; i >= position; i--) // ML : always keep last safe-guarding 255
    {
        phonemeindex[i + 1] = phonemeindex[i];
        phonemeLength[i + 1] = phonemeLength[i];
        stress[i + 1] = stress[i];
    }

    phonemeindex[position] = mem60;
    phonemeLength[position] = mem59;
    stress[position] = mem58;
    return;
}

//void Code48431()
void STM32SAM::InsertBreath() {
    unsigned char mem54;
    unsigned char mem55;
    unsigned char index; //variable Y
    mem54 = 255;
    X++;
    mem55 = 0;
    unsigned char mem66 = 0;
    while(1) {
        //pos48440:
        X = mem66;
        index = phonemeindex[X];
        if(index == 255) return;
        mem55 += phonemeLength[X];

        if(mem55 < 232) {
            if(index != 254) // ML : Prevents an index out of bounds problem
            {
                A = flags2[index] & 1;
                if(A != 0) {
                    X++;
                    mem55 = 0;
                    Insert(X, 254, mem59, 0);
                    mem66++;
                    mem66++;
                    continue;
                }
            }
            if(index == 0) mem54 = X;
            mem66++;
            continue;
        }
        X = mem54;
        phonemeindex[X] = 31; // 'Q*' glottal stop
        phonemeLength[X] = 4;
        stress[X] = 0;
        X++;
        mem55 = 0;
        Insert(X, 254, mem59, 0);
        X++;
        mem66 = X;
    }
}

// Iterates through the phoneme buffer, copying the stress value from
// the following phoneme under the following circumstance:

//     1. The current phoneme is voiced, excluding plosives and fricatives
//     2. The following phoneme is voiced, excluding plosives and fricatives, and
//     3. The following phoneme is stressed
//
//  In those cases, the stress value+1 from the following phoneme is copied.
//
// For example, the word LOITER is represented as LOY5TER, with as stress
// of 5 on the diphtong OY. This routine will copy the stress value of 6 (5+1)
// to the L that precedes it.

//void Code41883()
void STM32SAM::CopyStress() {
    // loop thought all the phonemes to be output
    unsigned char pos = 0; //mem66
    while(1) {
        // get the phomene
        Y = phonemeindex[pos];

        // exit at end of buffer
        if(Y == 255) return;

        // if CONSONANT_FLAG set, skip - only vowels get stress
        if((flags[Y] & 64) == 0) {
            pos++;
            continue;
        }
        // get the next phoneme
        Y = phonemeindex[pos + 1];
        if(Y == 255) //prevent buffer overflow
        {
            pos++;
            continue;
        } else
            // if the following phoneme is a vowel, skip
            if((flags[Y] & 128) == 0) {
                pos++;
                continue;
            }

        // get the stress value at the next position
        Y = stress[pos + 1];

        // if next phoneme is not stressed, skip
        if(Y == 0) {
            pos++;
            continue;
        }

        // if next phoneme is not a VOWEL OR ER, skip
        if((Y & 128) != 0) {
            pos++;
            continue;
        }

        // copy stress from prior phoneme to this one
        stress[pos] = Y + 1;

        // advance pointer
        pos++;
    }
}

// The input[] buffer contains a string of phonemes and stress markers along
// the lines of:
//
//     DHAX KAET IHZ AH5GLIY. <0x9B>
//
// The byte 0x9B marks the end of the buffer. Some phonemes are 2 bytes
// long, such as "DH" and "AX". Others are 1 byte long, such as "T" and "Z".
// There are also stress markers, such as "5" and ".".
//
// The first character of the phonemes are stored in the table signInputTable1[].
// The second character of the phonemes are stored in the table signInputTable2[].
// The stress characters are arranged in low to high stress order in stressInputTable[].
//
// The following process is used to parse the input[] buffer:
//
// Repeat until the <0x9B> character is reached:
//
//        First, a search is made for a 2 character match for phonemes that do not
//        end with the '*' (wildcard) character. On a match, the index of the phoneme
//        is added to phonemeIndex[] and the buffer position is advanced 2 bytes.
//
//        If this fails, a search is made for a 1 character match against all
//        phoneme names ending with a '*' (wildcard). If this succeeds, the
//        phoneme is added to phonemeIndex[] and the buffer position is advanced
//        1 byte.
//
//        If this fails, search for a 1 character match in the stressInputTable[].
//        If this succeeds, the stress value is placed in the last stress[] table
//        at the same index of the last added phoneme, and the buffer position is
//        advanced by 1 byte.
//
//        If this fails, return a 0.
//
// On success:
//
//    1. phonemeIndex[] will contain the index of all the phonemes.
//    2. The last index in phonemeIndex[] will be 255.
//    3. stress[] will contain the stress value for each phoneme

// input[] holds the string of phonemes, each two bytes wide
// signInputTable1[] holds the first character of each phoneme
// signInputTable2[] holds te second character of each phoneme
// phonemeIndex[] holds the indexes of the phonemes after parsing input[]
//
// The parser scans through the input[], finding the names of the phonemes
// by searching signInputTable1[] and signInputTable2[]. On a match, it
// copies the index of the phoneme into the phonemeIndexTable[].
//
// The character <0x9B> marks the end of text in input[]. When it is reached,
// the index 255 is placed at the end of the phonemeIndexTable[], and the
// function returns with a 1 indicating success.
int STM32SAM::Parser1() {
    int i;
    unsigned char sign1;
    unsigned char sign2;
    unsigned char position = 0;
    X = 0;
    A = 0;
    Y = 0;

    // CLEAR THE STRESS TABLE
    for(i = 0; i < 256; i++) stress[i] = 0;

    // THIS CODE MATCHES THE PHONEME LETTERS TO THE TABLE
    // pos41078:
    while(1) {
        // GET THE FIRST CHARACTER FROM THE PHONEME BUFFER
        sign1 = input[X];
        // TEST FOR 155 (�) END OF LINE MARKER
        if(sign1 == 155) {
            // MARK ENDPOINT AND RETURN
            phonemeindex[position] = 255; //mark endpoint
            // REACHED END OF PHONEMES, SO EXIT
            return 1; //all ok
        }

        // GET THE NEXT CHARACTER FROM THE BUFFER
        X++;
        sign2 = input[X];

        // NOW sign1 = FIRST CHARACTER OF PHONEME, AND sign2 = SECOND CHARACTER OF PHONEME

        // TRY TO MATCH PHONEMES ON TWO TWO-CHARACTER NAME
        // IGNORE PHONEMES IN TABLE ENDING WITH WILDCARDS

        // SET INDEX TO 0
        Y = 0;
    pos41095:

        // GET FIRST CHARACTER AT POSITION Y IN signInputTable
        // --> should change name to PhonemeNameTable1
        A = signInputTable1[Y];

        // FIRST CHARACTER MATCHES?
        if(A == sign1) {
            // GET THE CHARACTER FROM THE PhonemeSecondLetterTable
            A = signInputTable2[Y];
            // NOT A SPECIAL AND MATCHES SECOND CHARACTER?
            if((A != '*') && (A == sign2)) {
                // STORE THE INDEX OF THE PHONEME INTO THE phomeneIndexTable
                phonemeindex[position] = Y;

                // ADVANCE THE POINTER TO THE phonemeIndexTable
                position++;
                // ADVANCE THE POINTER TO THE phonemeInputBuffer
                X++;

                // CONTINUE PARSING
                continue;
            }
        }

        // NO MATCH, TRY TO MATCH ON FIRST CHARACTER TO WILDCARD NAMES (ENDING WITH '*')

        // ADVANCE TO THE NEXT POSITION
        Y++;
        // IF NOT END OF TABLE, CONTINUE
        if(Y != 81) goto pos41095;

        // REACHED END OF TABLE WITHOUT AN EXACT (2 CHARACTER) MATCH.
        // THIS TIME, SEARCH FOR A 1 CHARACTER MATCH AGAINST THE WILDCARDS

        // RESET THE INDEX TO POINT TO THE START OF THE PHONEME NAME TABLE
        Y = 0;
    pos41134:
        // DOES THE PHONEME IN THE TABLE END WITH '*'?
        if(signInputTable2[Y] == '*') {
            // DOES THE FIRST CHARACTER MATCH THE FIRST LETTER OF THE PHONEME
            if(signInputTable1[Y] == sign1) {
                // SAVE THE POSITION AND MOVE AHEAD
                phonemeindex[position] = Y;

                // ADVANCE THE POINTER
                position++;

                // CONTINUE THROUGH THE LOOP
                continue;
            }
        }
        Y++;
        if(Y != 81) goto pos41134; //81 is size of PHONEME NAME table

        // FAILED TO MATCH WITH A WILDCARD. ASSUME THIS IS A STRESS
        // CHARACTER. SEARCH THROUGH THE STRESS TABLE

        // SET INDEX TO POSITION 8 (END OF STRESS TABLE)
        Y = 8;

        // WALK BACK THROUGH TABLE LOOKING FOR A MATCH
        while((sign1 != stressInputTable[Y]) && (Y > 0)) {
            // DECREMENT INDEX
            Y--;
        }

        // REACHED THE END OF THE SEARCH WITHOUT BREAKING OUT OF LOOP?
        if(Y == 0) {
            //mem[39444] = X;
            //41181: JSR 42043 //Error
            // FAILED TO MATCH ANYTHING, RETURN 0 ON FAILURE
            return 0;
        }
        // SET THE STRESS FOR THE PRIOR PHONEME
        stress[position - 1] = Y;
    } //while
}

//change phonemelength depedendent on stress
//void Code41203()
void STM32SAM::SetPhonemeLength() {
    unsigned char A;
    int position = 0;
    while(phonemeindex[position] != 255) {
        A = stress[position];
        //41218: BMI 41229
        if((A == 0) || ((A & 128) != 0)) {
            phonemeLength[position] = phonemeLengthTable[phonemeindex[position]];
        } else {
            phonemeLength[position] = phonemeStressedLengthTable[phonemeindex[position]];
        }
        position++;
    }
}

void STM32SAM::Code41240() {
    unsigned char pos = 0;

    while(phonemeindex[pos] != 255) {
        unsigned char index; //register AC
        X = pos;
        index = phonemeindex[pos];
        if((flags[index] & 2) == 0) {
            pos++;
            continue;
        } else if((flags[index] & 1) == 0) {
            Insert(pos + 1, index + 1, phonemeLengthTable[index + 1], stress[pos]);
            Insert(pos + 2, index + 2, phonemeLengthTable[index + 2], stress[pos]);
            pos += 3;
            continue;
        }

        do {
            X++;
            A = phonemeindex[X];
        } while(A == 0);

        if(A != 255) {
            if((flags[A] & 8) != 0) {
                pos++;
                continue;
            }
            if((A == 36) || (A == 37)) {
                pos++; // '/H' '/X'
                continue;
            }
        }

        Insert(pos + 1, index + 1, phonemeLengthTable[index + 1], stress[pos]);
        Insert(pos + 2, index + 2, phonemeLengthTable[index + 2], stress[pos]);
        pos += 3;
    };
}

// Rewrites the phonemes using the following rules:
//
//       <DIPHTONG ENDING WITH WX> -> <DIPHTONG ENDING WITH WX> WX
//       <DIPHTONG NOT ENDING WITH WX> -> <DIPHTONG NOT ENDING WITH WX> YX
//       UL -> AX L
//       UM -> AX M
//       <STRESSED VOWEL> <SILENCE> <STRESSED VOWEL> -> <STRESSED VOWEL> <SILENCE> Q <VOWEL>
//       T R -> CH R
//       D R -> J R
//       <VOWEL> R -> <VOWEL> RX
//       <VOWEL> L -> <VOWEL> LX
//       G S -> G Z
//       K <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> KX <VOWEL OR DIPHTONG NOT ENDING WITH IY>
//       G <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> GX <VOWEL OR DIPHTONG NOT ENDING WITH IY>
//       S P -> S B
//       S T -> S D
//       S K -> S G
//       S KX -> S GX
//       <ALVEOLAR> UW -> <ALVEOLAR> UX
//       CH -> CH CH' (CH requires two phonemes to represent it)
//       J -> J J' (J requires two phonemes to represent it)
//       <UNSTRESSED VOWEL> T <PAUSE> -> <UNSTRESSED VOWEL> DX <PAUSE>
//       <UNSTRESSED VOWEL> D <PAUSE>  -> <UNSTRESSED VOWEL> DX <PAUSE>

//void Code41397()
void STM32SAM::Parser2() {
    unsigned char pos = 0; //mem66;
    unsigned char mem58 = 0;

    // Loop through phonemes
    while(1) {
        // SET X TO THE CURRENT POSITION
        X = pos;
        // GET THE PHONEME AT THE CURRENT POSITION
        A = phonemeindex[pos];

        // Is phoneme pause?
        if(A == 0) {
            // Move ahead to the
            pos++;
            continue;
        }

        // If end of phonemes flag reached, exit routine
        if(A == 255) return;

        // Copy the current phoneme index to Y
        Y = A;

        // RULE:
        //       <DIPHTONG ENDING WITH WX> -> <DIPHTONG ENDING WITH WX> WX
        //       <DIPHTONG NOT ENDING WITH WX> -> <DIPHTONG NOT ENDING WITH WX> YX
        // Example: OIL, COW

        // Check for DIPHTONG
        if((flags[A] & 16) == 0) goto pos41457;

        // Not a diphthong. Get the stress
        mem58 = stress[pos];

        // End in IY sound?
        A = flags[Y] & 32;

        // If ends with IY, use YX, else use WX
        if(A == 0)
            A = 20;
        else
            A = 21; // 'WX' = 20 'YX' = 21
        //pos41443:
        // Insert at WX or YX following, copying the stress

        Insert(pos + 1, A, mem59, mem58);
        X = pos;
        // Jump to ???
        goto pos41749;

    pos41457:

        // RULE:
        //       UL -> AX L
        // Example: MEDDLE

        // Get phoneme
        A = phonemeindex[X];
        // Skip this rule if phoneme is not UL
        if(A != 78) goto pos41487; // 'UL'
        A = 24; // 'L'                 //change 'UL' to 'AX L'

    pos41466:
        // Get current phoneme stress
        mem58 = stress[X];

        // Change UL to AX
        phonemeindex[X] = 13; // 'AX'
        // Perform insert. Note code below may jump up here with different values
        Insert(X + 1, A, mem59, mem58);
        pos++;
        // Move to next phoneme
        continue;

    pos41487:

        // RULE:
        //       UM -> AX M
        // Example: ASTRONOMY

        // Skip rule if phoneme != UM
        if(A != 79) goto pos41495; // 'UM'
        // Jump up to branch - replaces current phoneme with AX and continues
        A = 27; // 'M'  //change 'UM' to  'AX M'

        goto pos41466;
    pos41495:

        // RULE:
        //       UN -> AX N
        // Example: FUNCTION

        // Skip rule if phoneme != UN
        if(A != 80) goto pos41503; // 'UN'

        // Jump up to branch - replaces current phoneme with AX and continues
        A = 28; // 'N' //change UN to 'AX N'

        goto pos41466;
    pos41503:

        // RULE:
        //       <STRESSED VOWEL> <SILENCE> <STRESSED VOWEL> -> <STRESSED VOWEL> <SILENCE> Q <VOWEL>
        // EXAMPLE: AWAY EIGHT

        Y = A;
        // VOWEL set?
        A = flags[A] & 128;

        // Skip if not a vowel
        if(A != 0) {
            // Get the stress
            A = stress[X];

            // If stressed...
            if(A != 0) {
                // Get the following phoneme
                X++;
                A = phonemeindex[X];
                // If following phoneme is a pause

                if(A == 0) {
                    // Get the phoneme following pause
                    X++;
                    Y = phonemeindex[X];

                    // Check for end of buffer flag
                    if(Y == 255) //buffer overflow
                        // ??? Not sure about these flags
                        A = 65 & 128;
                    else
                        // And VOWEL flag to current phoneme's flags
                        A = flags[Y] & 128;

                    // If following phonemes is not a pause
                    if(A != 0) {
                        // If the following phoneme is not stressed
                        A = stress[X];
                        if(A != 0) {
                            // 31 = 'Q'
                            Insert(X, 31, mem59, 0);
                            pos++;
                            continue;
                        }
                    }
                }
            }
        }

        // RULES FOR PHONEMES BEFORE R
        //        T R -> CH R
        // Example: TRACK

        // Get current position and phoneme
        X = pos;
        A = phonemeindex[pos];
        if(A != 23) goto pos41611; // 'R'

        // Look at prior phoneme
        X--;
        A = phonemeindex[pos - 1];
        //pos41567:
        if(A == 69) // 'T'
        {
            phonemeindex[pos - 1] = 42;
            goto pos41779;
        }

        // RULES FOR PHONEMES BEFORE R
        //        D R -> J R
        // Example: DRY

        // Prior phonemes D?
        if(A == 57) // 'D'
        {
            // Change D to J
            phonemeindex[pos - 1] = 44;

            goto pos41788;
        }

        // RULES FOR PHONEMES BEFORE R
        //        <VOWEL> R -> <VOWEL> RX
        // Example: ART

        // If vowel flag is set change R to RX
        A = flags[A] & 128;

        if(A != 0) phonemeindex[pos] = 18; // 'RX'

        // continue to next phoneme
        pos++;
        continue;

    pos41611:

        // RULE:
        //       <VOWEL> L -> <VOWEL> LX
        // Example: ALL

        // Is phoneme L?
        if(A == 24) // 'L'
        {
            // If prior phoneme does not have VOWEL flag set, move to next phoneme
            if((flags[phonemeindex[pos - 1]] & 128) == 0) {
                pos++;
                continue;
            }
            // Prior phoneme has VOWEL flag set, so change L to LX and move to next phoneme

            phonemeindex[X] = 19; // 'LX'
            pos++;
            continue;
        }

        // RULE:
        //       G S -> G Z
        //
        // Can't get to fire -
        //       1. The G -> GX rule intervenes
        //       2. Reciter already replaces GS -> GZ

        // Is current phoneme S?
        if(A == 32) // 'S'
        {
            // If prior phoneme is not G, move to next phoneme
            if(phonemeindex[pos - 1] != 60) {
                pos++;
                continue;
            }
            // Replace S with Z and move on

            phonemeindex[pos] = 38; // 'Z'
            pos++;
            continue;
        }

        // RULE:
        //             K <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> KX <VOWEL OR DIPHTONG NOT ENDING WITH IY>
        // Example: COW

        // Is current phoneme K?
        if(A == 72) // 'K'
        {
            // Get next phoneme
            Y = phonemeindex[pos + 1];
            // If at end, replace current phoneme with KX
            if(Y == 255)
                phonemeindex[pos] = 75; // ML : prevents an index out of bounds problem
            else {
                // VOWELS AND DIPHTONGS ENDING WITH IY SOUND flag set?
                A = flags[Y] & 32;

                // Replace with KX
                if(A == 0) phonemeindex[pos] = 75; // 'KX'
            }
        } else

            // RULE:
            //             G <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> GX <VOWEL OR DIPHTONG NOT ENDING WITH IY>
            // Example: GO

            // Is character a G?
            if(A == 60) // 'G'
            {
                // Get the following character
                unsigned char index = phonemeindex[pos + 1];

                // At end of buffer?
                if(index == 255) //prevent buffer overflow
                {
                    pos++;
                    continue;
                } else
                    // If diphtong ending with YX, move continue processing next phoneme
                    if((flags[index] & 32) != 0) {
                        pos++;
                        continue;
                    }
                // replace G with GX and continue processing next phoneme

                phonemeindex[pos] = 63; // 'GX'
                pos++;
                continue;
            }

        // RULE:
        //      S P -> S B
        //      S T -> S D
        //      S K -> S G
        //      S KX -> S GX
        // Examples: SPY, STY, SKY, SCOWL

        Y = phonemeindex[pos];
        //pos41719:
        // Replace with softer version?
        A = flags[Y] & 1;
        if(A == 0) goto pos41749;
        A = phonemeindex[pos - 1];
        if(A != 32) // 'S'
        {
            A = Y;
            goto pos41812;
        }
        // Replace with softer version

        phonemeindex[pos] = Y - 12;
        pos++;
        continue;

    pos41749:

        // RULE:
        //      <ALVEOLAR> UW -> <ALVEOLAR> UX
        //
        // Example: NEW, DEW, SUE, ZOO, THOO, TOO

        //       UW -> UX

        A = phonemeindex[X];
        if(A == 53) // 'UW'
        {
            // ALVEOLAR flag set?
            Y = phonemeindex[X - 1];
            A = flags2[Y] & 4;
            // If not set, continue processing next phoneme
            if(A == 0) {
                pos++;
                continue;
            }

            phonemeindex[X] = 16;
            pos++;
            continue;
        }
    pos41779:

        // RULE:
        //       CH -> CH CH' (CH requires two phonemes to represent it)
        // Example: CHEW

        if(A == 42) // 'CH'
        {
            //        pos41783:

            Insert(X + 1, A + 1, mem59, stress[X]);
            pos++;
            continue;
        }

    pos41788:

        // RULE:
        //       J -> J J' (J requires two phonemes to represent it)
        // Example: JAY

        if(A == 44) // 'J'
        {
            Insert(X + 1, A + 1, mem59, stress[X]);
            pos++;
            continue;
        }

        // Jump here to continue
    pos41812:

        // RULE: Soften T following vowel
        // NOTE: This rule fails for cases such as "ODD"
        //       <UNSTRESSED VOWEL> T <PAUSE> -> <UNSTRESSED VOWEL> DX <PAUSE>
        //       <UNSTRESSED VOWEL> D <PAUSE>  -> <UNSTRESSED VOWEL> DX <PAUSE>
        // Example: PARTY, TARDY

        // Past this point, only process if phoneme is T or D

        if(A != 69) // 'T'
            if(A != 57) {
                pos++; // 'D'
                continue;
            }
        //pos41825:

        // If prior phoneme is not a vowel, continue processing phonemes
        if((flags[phonemeindex[X - 1]] & 128) == 0) {
            pos++;
            continue;
        }

        // Get next phoneme
        X++;
        A = phonemeindex[X];
        //pos41841
        // Is the next phoneme a pause?
        if(A != 0) {
            // If next phoneme is not a pause, continue processing phonemes
            if((flags[A] & 128) == 0) {
                pos++;
                continue;
            }
            // If next phoneme is stressed, continue processing phonemes
            // FIXME: How does a pause get stressed?
            if(stress[X] != 0) {
                pos++;
                continue;
            }
            //pos41856:
            // Set phonemes to DX

            phonemeindex[pos] = 30; // 'DX'
        } else {
            A = phonemeindex[X + 1];
            if(A == 255) //prevent buffer overflow
                A = 65 & 128;
            else
                // Is next phoneme a vowel or ER?
                A = flags[A] & 128;

            if(A != 0) phonemeindex[pos] = 30; // 'DX'
        }

        pos++;

    } // while
} // parser 2

// Applies various rules that adjust the lengths of phonemes
//
//         Lengthen <FRICATIVE> or <VOICED> between <VOWEL> and <PUNCTUATION> by 1.5
//         <VOWEL> <RX | LX> <CONSONANT> - decrease <VOWEL> length by 1
//         <VOWEL> <UNVOICED PLOSIVE> - decrease vowel by 1/8th
//         <VOWEL> <UNVOICED CONSONANT> - increase vowel by 1/2 + 1
//         <NASAL> <STOP CONSONANT> - set nasal = 5, consonant = 6
//         <VOICED STOP CONSONANT> {optional silence} <STOP CONSONANT> - shorten both to 1/2 + 1
//         <LIQUID CONSONANT> <DIPHTONG> - decrease by 2

//void Code48619()
void STM32SAM::AdjustLengths() {
    // LENGTHEN VOWELS PRECEDING PUNCTUATION
    //
    // Search for punctuation. If found, back up to the first vowel, then
    // process all phonemes between there and up to (but not including) the punctuation.
    // If any phoneme is found that is a either a fricative or voiced, the duration is
    // increased by (length * 1.5) + 1

    // loop index
    X = 0;
    unsigned char index;

    // iterate through the phoneme list
    unsigned char loopIndex = 0;
    while(1) {
        // get a phoneme
        index = phonemeindex[X];

        // exit loop if end on buffer token
        if(index == 255) break;

        // not punctuation?
        if((flags2[index] & 1) == 0) {
            // skip
            X++;
            continue;
        }

        // hold index
        loopIndex = X;

        // Loop backwards from this point
    pos48644:

        // back up one phoneme
        X--;

        // stop once the beginning is reached
        if(X == 0) break;

        // get the preceding phoneme
        index = phonemeindex[X];

        if(index != 255) //inserted to prevent access overrun
            if((flags[index] & 128) == 0) goto pos48644; // if not a vowel, continue looping

        //pos48657:
        do {
            // test for vowel
            index = phonemeindex[X];

            if(index != 255) //inserted to prevent access overrun
                // test for fricative/unvoiced or not voiced
                if(((flags2[index] & 32) == 0) || ((flags[index] & 4) != 0)) //nochmal �berpr�fen
                {
                    //A = flags[Y] & 4;
                    //if(A == 0) goto pos48688;

                    // get the phoneme length
                    A = phonemeLength[X];

                    // change phoneme length to (length * 1.5) + 1
                    A = (A >> 1) + A + 1;

                    phonemeLength[X] = A;
                }
            // keep moving forward
            X++;
        } while(X != loopIndex);
        //  if (X != loopIndex) goto pos48657;
        X++;
    } // while

    // Similar to the above routine, but shorten vowels under some circumstances

    // Loop throught all phonemes
    loopIndex = 0;
    //pos48697

    while(1) {
        // get a phoneme
        X = loopIndex;
        index = phonemeindex[X];

        // exit routine at end token
        if(index == 255) return;

        // vowel?
        A = flags[index] & 128;
        if(A != 0) {
            // get next phoneme
            X++;
            index = phonemeindex[X];

            // get flags
            if(index == 255)
                mem56 = 65; // use if end marker
            else
                mem56 = flags[index];

            // not a consonant
            if((flags[index] & 64) == 0) {
                // RX or LX?
                if((index == 18) || (index == 19)) // 'RX' & 'LX'
                {
                    // get the next phoneme
                    X++;
                    index = phonemeindex[X];

                    // next phoneme a consonant?
                    if((flags[index] & 64) != 0) {
                        // RULE: <VOWEL> RX | LX <CONSONANT>

                        // decrease length of vowel by 1 frame
                        phonemeLength[loopIndex]--;
                    }
                    // move ahead
                    loopIndex++;
                    continue;
                }
                // move ahead
                loopIndex++;
                continue;
            }

            // Got here if not <VOWEL>

            // not voiced
            if((mem56 & 4) == 0) {
                // Unvoiced
                // *, .*, ?*, ,*, -*, DX, S*, SH, F*, TH, /H, /X, CH, P*, T*, K*, KX

                // not an unvoiced plosive?
                if((mem56 & 1) == 0) {
                    // move ahead
                    loopIndex++;
                    continue;
                }

                // P*, T*, K*, KX

                // RULE: <VOWEL> <UNVOICED PLOSIVE>
                // <VOWEL> <P*, T*, K*, KX>

                // move back
                X--;

                // decrease length by 1/8th
                mem56 = phonemeLength[X] >> 3;
                phonemeLength[X] -= mem56;

                // move ahead
                loopIndex++;
                continue;
            }

            // RULE: <VOWEL> <VOICED CONSONANT>
            // <VOWEL> <WH, R*, L*, W*, Y*, M*, N*, NX, DX, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX>

            // decrease length
            A = phonemeLength[X - 1];
            phonemeLength[X - 1] = (A >> 2) + A + 1; // 5/4*A + 1

            // move ahead
            loopIndex++;
            continue;
        }

        // WH, R*, L*, W*, Y*, M*, N*, NX, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX

        //pos48821:

        // RULE: <NASAL> <STOP CONSONANT>
        //       Set punctuation length to 6
        //       Set stop consonant length to 5

        // nasal?
        if((flags2[index] & 8) != 0) {
            // M*, N*, NX,

            // get the next phoneme
            X++;
            index = phonemeindex[X];

            // end of buffer?
            if(index == 255)
                A = 65 & 2; //prevent buffer overflow
            else
                A = flags[index] & 2; // check for stop consonant

            // is next phoneme a stop consonant?
            if(A != 0)

            // B*, D*, G*, GX, P*, T*, K*, KX

            {
                // set stop consonant length to 6
                phonemeLength[X] = 6;

                // set nasal length to 5
                phonemeLength[X - 1] = 5;
            }
            // move to next phoneme
            loopIndex++;
            continue;
        }

        // WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX

        // RULE: <VOICED STOP CONSONANT> {optional silence} <STOP CONSONANT>
        //       Shorten both to (length/2 + 1)

        // (voiced) stop consonant?
        if((flags[index] & 2) != 0) {
            // B*, D*, G*, GX

            // move past silence
            do {
                // move ahead
                X++;
                index = phonemeindex[X];
            } while(index == 0);

            // check for end of buffer
            if(index == 255) //buffer overflow
            {
                // ignore, overflow code
                if((65 & 2) == 0) {
                    loopIndex++;
                    continue;
                }
            } else if((flags[index] & 2) == 0) {
                // if another stop consonant, move ahead
                loopIndex++;
                continue;
            }

            // RULE: <UNVOICED STOP CONSONANT> {optional silence} <STOP CONSONANT>

            // X gets overwritten, so hold prior X value for debug statement
            // int debugX = X;
            // shorten the prior phoneme length to (length/2 + 1)
            phonemeLength[X] = (phonemeLength[X] >> 1) + 1;
            X = loopIndex;

            // also shorten this phoneme length to (length/2 +1)
            phonemeLength[loopIndex] = (phonemeLength[loopIndex] >> 1) + 1;

            // move ahead
            loopIndex++;
            continue;
        }

        // WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, **,

        // RULE: <VOICED NON-VOWEL> <DIPHTONG>
        //       Decrease <DIPHTONG> by 2

        // liquic consonant?
        if((flags2[index] & 16) != 0) {
            // R*, L*, W*, Y*

            // get the prior phoneme
            index = phonemeindex[X - 1];

            // prior phoneme a stop consonant>
            if((flags[index] & 2) != 0) {
                // Rule: <LIQUID CONSONANT> <DIPHTONG>

                // decrease the phoneme length by 2 frames (20 ms)
                phonemeLength[X] -= 2;
            }
        }

        // move to next phoneme
        loopIndex++;
        continue;
    }
    //            goto pos48701;
}

// -------------------------------------------------------------------------
// ML : Code47503 is division with remainder, and mem50 gets the sign
void STM32SAM::Code47503(unsigned char mem52) {
    Y = 0;
    if((mem53 & 128) != 0) {
        mem53 = -mem53;
        Y = 128;
    }
    mem50 = Y;
    A = 0;
    for(X = 8; X > 0; X--) {
        int temp = mem53;
        mem53 = mem53 << 1;
        A = A << 1;
        if(temp >= 128) A++;
        if(A >= mem52) {
            A = A - mem52;
            mem53++;
        }
    }

    mem51 = A;
    if((mem50 & 128) != 0) mem53 = -mem53;
}

////////////////////////////////////////////////////////////////////////////////////////////
//
//           Reciter
//
////////////////////////////////////////////////////////////////////////////////////////////

void STM32SAM::Code37055(unsigned char mem59) {
    X = mem59;
    X--;
    A = inputtemp[X];
    Y = A;
    A = tab36376[Y];
    return;
}

void STM32SAM::Code37066(unsigned char mem58) {
    X = mem58;
    X++;
    A = inputtemp[X];
    Y = A;
    A = tab36376[Y];
}

unsigned char STM32SAM::GetRuleByte(unsigned short mem62, unsigned char Y) {
    unsigned int address = mem62;

    if(mem62 >= 37541) {
        address -= 37541;
        return rules2[address + Y];
    }
    address -= 32000;
    return rules[address + Y];
}

int STM32SAM::TextToPhonemes(unsigned char* input) // Code36484
{
    //unsigned char *tab39445 = &mem[39445];   //input and output
    //unsigned char mem29;
    unsigned char mem56; //output position for phonemes
    unsigned char mem57;
    unsigned char mem58;
    unsigned char mem59;
    unsigned char mem60;
    unsigned char mem61;
    unsigned short mem62; // memory position of current rule

    unsigned char mem64; // position of '=' or current character
    unsigned char mem65; // position of ')'
    unsigned char mem66; // position of '('
    unsigned char mem36653;

    inputtemp[0] = 32;

    // secure copy of input
    // because input will be overwritten by phonemes
    X = 1;
    Y = 0;
    do {
        //pos36499:
        A = input[Y] & 127;
        if(A >= 112)
            A = A & 95;
        else if(A >= 96)
            A = A & 79;

        inputtemp[X] = A;
        X++;
        Y++;
    } while(Y != 255);

    X = 255;
    inputtemp[X] = 27;
    mem61 = 255;

pos36550:
    A = 255;
    mem56 = 255;

pos36554:
    while(1) {
        mem61++;
        X = mem61;
        A = inputtemp[X];
        mem64 = A;
        if(A == '[') {
            mem56++;
            X = mem56;
            A = 155;
            input[X] = 155;
            //goto pos36542;
            //          Code39771();    //Code39777();
            return 1;
        }

        //pos36579:
        if(A != '.') break;
        X++;
        Y = inputtemp[X];
        A = tab36376[Y] & 1;
        if(A != 0) break;
        mem56++;
        X = mem56;
        A = '.';
        input[X] = '.';
    } //while

    //pos36607:
    A = mem64;
    Y = A;
    A = tab36376[A];
    mem57 = A;
    if((A & 2) != 0) {
        mem62 = 37541;
        goto pos36700;
    }

    //pos36630:
    A = mem57;
    if(A != 0) goto pos36677;
    A = 32;
    inputtemp[X] = ' ';
    mem56++;
    X = mem56;
    if(X > 120) goto pos36654;
    input[X] = A;
    goto pos36554;

    // -----

    //36653 is unknown. Contains position

pos36654:
    input[X] = 155;
    A = mem61;
    mem36653 = A;
    //  mem29 = A; // not used
    //  Code36538(); das ist eigentlich
    return 1;
    //Code39771();
    //go on if there is more input ???
    mem61 = mem36653;
    goto pos36550;

pos36677:
    A = mem57 & 128;
    if(A == 0) {
        //36683: BRK
        return 0;
    }

    // go to the right rules for this character.
    X = mem64 - 'A';
    mem62 = tab37489[X] | (tab37515[X] << 8);

    // -------------------------------------
    // go to next rule
    // -------------------------------------

pos36700:

    // find next rule
    Y = 0;
    do {
        mem62 += 1;
        A = GetRuleByte(mem62, Y);
    } while((A & 128) == 0);
    Y++;

    //pos36720:
    // find '('
    while(1) {
        A = GetRuleByte(mem62, Y);
        if(A == '(') break;
        Y++;
    }
    mem66 = Y;

    //pos36732:
    // find ')'
    do {
        Y++;
        A = GetRuleByte(mem62, Y);
    } while(A != ')');
    mem65 = Y;

    //pos36741:
    // find '='
    do {
        Y++;
        A = GetRuleByte(mem62, Y);
        A = A & 127;
    } while(A != '=');
    mem64 = Y;

    X = mem61;
    mem60 = X;

    // compare the string within the bracket
    Y = mem66;
    Y++;
    //pos36759:
    while(1) {
        mem57 = inputtemp[X];
        A = GetRuleByte(mem62, Y);
        if(A != mem57) goto pos36700;
        Y++;
        if(Y == mem65) break;
        X++;
        mem60 = X;
    }

    // the string in the bracket is correct

    //pos36787:
    A = mem61;
    mem59 = mem61;

pos36791:
    while(1) {
        mem66--;
        Y = mem66;
        A = GetRuleByte(mem62, Y);
        mem57 = A;
        //36800: BPL 36805
        if((A & 128) != 0) goto pos37180;
        X = A & 127;
        A = tab36376[X] & 128;
        if(A == 0) break;
        X = mem59 - 1;
        A = inputtemp[X];
        if(A != mem57) goto pos36700;
        mem59 = X;
    }

    //pos36833:
    A = mem57;
    if(A == ' ') goto pos36895;
    if(A == '#') goto pos36910;
    if(A == '.') goto pos36920;
    if(A == '&') goto pos36935;
    if(A == '@') goto pos36967;
    if(A == '^') goto pos37004;
    if(A == '+') goto pos37019;
    if(A == ':') goto pos37040;
    //  Code42041();    //Error
    //36894: BRK
    return 0;

    // --------------

pos36895:
    Code37055(mem59);
    A = A & 128;
    if(A != 0) goto pos36700;
pos36905:
    mem59 = X;
    goto pos36791;

    // --------------

pos36910:
    Code37055(mem59);
    A = A & 64;
    if(A != 0) goto pos36905;
    goto pos36700;

    // --------------

pos36920:
    Code37055(mem59);
    A = A & 8;
    if(A == 0) goto pos36700;
pos36930:
    mem59 = X;
    goto pos36791;

    // --------------

pos36935:
    Code37055(mem59);
    A = A & 16;
    if(A != 0) goto pos36930;
    A = inputtemp[X];
    if(A != 72) goto pos36700;
    X--;
    A = inputtemp[X];
    if((A == 67) || (A == 83)) goto pos36930;
    goto pos36700;

    // --------------

pos36967:
    Code37055(mem59);
    A = A & 4;
    if(A != 0) goto pos36930;
    A = inputtemp[X];
    if(A != 72) goto pos36700;
    if((A != 84) && (A != 67) && (A != 83)) goto pos36700;
    mem59 = X;
    goto pos36791;

    // --------------

pos37004:
    Code37055(mem59);
    A = A & 32;
    if(A == 0) goto pos36700;

pos37014:
    mem59 = X;
    goto pos36791;

    // --------------

pos37019:
    X = mem59;
    X--;
    A = inputtemp[X];
    if((A == 'E') || (A == 'I') || (A == 'Y')) goto pos37014;
    goto pos36700;
    // --------------

pos37040:
    Code37055(mem59);
    A = A & 32;
    if(A == 0) goto pos36791;
    mem59 = X;
    goto pos37040;

    //---------------------------------------

pos37077:
    X = mem58 + 1;
    A = inputtemp[X];
    if(A != 'E') goto pos37157;
    X++;
    Y = inputtemp[X];
    X--;
    A = tab36376[Y] & 128;
    if(A == 0) goto pos37108;
    X++;
    A = inputtemp[X];
    if(A != 'R') goto pos37113;
pos37108:
    mem58 = X;
    goto pos37184;
pos37113:
    if((A == 83) || (A == 68)) goto pos37108; // 'S' 'D'
    if(A != 76) goto pos37135; // 'L'
    X++;
    A = inputtemp[X];
    if(A != 89) goto pos36700;
    goto pos37108;

pos37135:
    if(A != 70) goto pos36700;
    X++;
    A = inputtemp[X];
    if(A != 85) goto pos36700;
    X++;
    A = inputtemp[X];
    if(A == 76) goto pos37108;
    goto pos36700;

pos37157:
    if(A != 73) goto pos36700;
    X++;
    A = inputtemp[X];
    if(A != 78) goto pos36700;
    X++;
    A = inputtemp[X];
    if(A == 71) goto pos37108;
    //pos37177:
    goto pos36700;

    // -----------------------------------------

pos37180:

    A = mem60;
    mem58 = A;

pos37184:
    Y = mem65 + 1;

    //37187: CPY 64
    //  if(? != 0) goto pos37194;
    if(Y == mem64) goto pos37455;
    mem65 = Y;
    //37196: LDA (62),y
    A = GetRuleByte(mem62, Y);
    mem57 = A;
    X = A;
    A = tab36376[X] & 128;
    if(A == 0) goto pos37226;
    X = mem58 + 1;
    A = inputtemp[X];
    if(A != mem57) goto pos36700;
    mem58 = X;
    goto pos37184;
pos37226:
    A = mem57;
    if(A == 32) goto pos37295; // ' '
    if(A == 35) goto pos37310; // '#'
    if(A == 46) goto pos37320; // '.'
    if(A == 38) goto pos37335; // '&'
    if(A == 64) goto pos37367; // ''
    if(A == 94) goto pos37404; // ''
    if(A == 43) goto pos37419; // '+'
    if(A == 58) goto pos37440; // ':'
    if(A == 37) goto pos37077; // '%'
    //pos37291:
    //  Code42041(); //Error
    //37294: BRK
    return 0;

    // --------------
pos37295:
    Code37066(mem58);
    A = A & 128;
    if(A != 0) goto pos36700;
pos37305:
    mem58 = X;
    goto pos37184;

    // --------------

pos37310:
    Code37066(mem58);
    A = A & 64;
    if(A != 0) goto pos37305;
    goto pos36700;

    // --------------

pos37320:
    Code37066(mem58);
    A = A & 8;
    if(A == 0) goto pos36700;

pos37330:
    mem58 = X;
    goto pos37184;

    // --------------

pos37335:
    Code37066(mem58);
    A = A & 16;
    if(A != 0) goto pos37330;
    A = inputtemp[X];
    if(A != 72) goto pos36700;
    X++;
    A = inputtemp[X];
    if((A == 67) || (A == 83)) goto pos37330;
    goto pos36700;

    // --------------

pos37367:
    Code37066(mem58);
    A = A & 4;
    if(A != 0) goto pos37330;
    A = inputtemp[X];
    if(A != 72) goto pos36700;
    if((A != 84) && (A != 67) && (A != 83)) goto pos36700;
    mem58 = X;
    goto pos37184;

    // --------------

pos37404:
    Code37066(mem58);
    A = A & 32;
    if(A == 0) goto pos36700;
pos37414:
    mem58 = X;
    goto pos37184;

    // --------------

pos37419:
    X = mem58;
    X++;
    A = inputtemp[X];
    if((A == 69) || (A == 73) || (A == 89)) goto pos37414;
    goto pos36700;

    // ----------------------

pos37440:

    Code37066(mem58);
    A = A & 32;
    if(A == 0) goto pos37184;
    mem58 = X;
    goto pos37440;
pos37455:
    Y = mem64;
    mem61 = mem60;

pos37461:
    //37461: LDA (62),y
    A = GetRuleByte(mem62, Y);
    mem57 = A;
    A = A & 127;
    if(A != '=') {
        mem56++;
        X = mem56;
        input[X] = A;
    }

    //37478: BIT 57
    //37480: BPL 37485  //not negative flag
    if((mem57 & 128) == 0) goto pos37485; //???
    goto pos36554;
pos37485:
    Y++;
    goto pos37461;
}

// Constructor

STM32SAM::STM32SAM(uint32_t STM32SAM_SPEED /* = 5 */) {
    STM32SAM_SPEED = STM32SAM_SPEED & 0x1f; // limit it from 0 to 31

    _STM32SAM_SPEED = STM32SAM_SPEED;

    // set default voice

    speed = 72;
    pitch = 64;
    mouth = 128;
    throat = 128;

    phonetic = 0;
    singmode = 0;

    wait1 = 7;
    wait2 = 6;

    mem59 = 0;

    oldtimetableindex = 0;
}

STM32SAM::STM32SAM() {
    _STM32SAM_SPEED = 7;

    // set default voice

    speed = 72;
    pitch = 64;
    mouth = 128;
    throat = 128;

    phonetic = 0;
    singmode = 0;

    wait1 = 7;
    wait2 = 6;

    mem59 = 0;

    oldtimetableindex = 0;
}

/*
  STM32SAM::~STM32SAM() {
  {
  // TODO: end();
  }
*/

////////////////////////////////////////////////////////////////////////////////////////////
//
//           STM32SAM sam  (variable string,  phonetic, sing, pitch, speed, mouth, throat)
//           STM32SAM say (sing off, phonetic off) (const string)
//           STM32SAM say (sing off, phonetic off) (variable string)
//           STM32SAM sing (sing on, phonetic off) (const string)
//           STM32SAM sing (sing on, phonetic off) (variable string)
//           STM32SAM sayPhonetic (sing off, phonetic on) (const string)
//           STM32SAM sayPhonetic (sing off, phonetic on) (variable string)
//           STM32SAM singPhonetic (sing on, phonetic on) (const string)
//           STM32SAM singPhonetic (sing on, phonetic on) (variable string)
//           STM32SAM voice (pitch, speed, mouth, throat)
//           STM32SAM setPitch (pitch)
//           STM32SAM setSpeed (speed)
//           STM32SAM setMouth (mouth)
//           STM32SAM setThroat (throat)
//
//
////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////
//
//           STM32SAM sam  (const string,  phonetic, sing, pitch, speed, mouth, throat)
//
////////////////////////////////////////////////////////////////////////////////////////////

char to_upper_case(char c) {
    if(c >= 'a' && c <= 'z') {
        return c - 'a' + 'A';
    }
    return c;
}

void STM32SAM::sam(
    const char* argv,
    unsigned char _phonetic,
    unsigned char _singmode,
    unsigned char _pitch,
    unsigned char _speed,
    unsigned char _mouth,
    unsigned char _throat) {
    phonetic = _phonetic;
    singmode = _singmode;
    pitch = _pitch;
    speed = _speed;
    mouth = _mouth;
    throat = _throat;

    int i;

    for(i = 0; i < 256; i++) {
        input[i] = argv[i];
    }

    for(i = 0; input[i] != 0; i++) {
        if(i != 0) {
            input[i] = to_upper_case((int)argv[i]);
        }
    }

    if(!phonetic) {
        strncat(input, "[", 256);
        if(!TextToPhonemes((unsigned char*)input)) {
            // PrintUsage();
            return;
        }

    } else {
        strncat(input, "\x9b", 256);
    }

    SetInput(input);

    if(!SAMMain()) {
        return;
    }
}

////////////////////////////////////////////////////////////////////////////////////////////
//
//           STM32SAM sam  (variable string,  phonetic, sing, pitch, speed, mouth, throat)
//
////////////////////////////////////////////////////////////////////////////////////////////

void STM32SAM::sam(
    char* argv,
    unsigned char _phonetic,
    unsigned char _singmode,
    unsigned char _pitch,
    unsigned char _speed,
    unsigned char _mouth,
    unsigned char _throat) {
    phonetic = _phonetic;
    singmode = _singmode;
    pitch = _pitch;
    speed = _speed;
    mouth = _mouth;
    throat = _throat;

    int i;

    for(i = 0; i < 256; i++) {
        input[i] = argv[i];
    }

    for(i = 0; input[i] != 0; i++) {
        if(i != 0) {
            input[i] = to_upper_case((int)argv[i]);
        }
    }

    if(!phonetic) {
        strncat(input, "[", 256);
        if(!TextToPhonemes((unsigned char*)input)) {
            // PrintUsage();
            return;
        }

    } else {
        strncat(input, "\x9b", 256);
    }

    SetInput(input);

    if(!SAMMain()) {
        return;
    }
}

////////////////////////////////////////////////////////////////////////////////////////////
//
//           STM32SAM say(sing off, phonetic off) (const string)
//
////////////////////////////////////////////////////////////////////////////////////////////

void STM32SAM::say(const char* argv) {
    int i;

    phonetic = 0;
    singmode = 0;

    char const_input[256];

    for(i = 0; i < 256; i++) {
        const_input[i] = argv[i];
    }

    sam(const_input, phonetic, singmode, pitch, speed, mouth, throat);
}

void STM32SAM::say(char* argv) {
    int i;

    phonetic = 0;
    singmode = 0;

    char const_input[256];

    for(i = 0; i < 256; i++) {
        const_input[i] = argv[i];
    }

    sam(const_input, phonetic, singmode, pitch, speed, mouth, throat);
}

////////////////////////////////////////////////////////////////////////////////////////////
//
//           STM32SAM sing (sing on, phonetic off)
//
////////////////////////////////////////////////////////////////////////////////////////////

void STM32SAM::sing(const char* argv) {
    int i;

    phonetic = 0;
    singmode = 1;

    char const_input[256];

    for(i = 0; i < 256; i++) {
        const_input[i] = argv[i];
    }

    sam(const_input, phonetic, singmode, pitch, speed, mouth, throat);
}

void STM32SAM::sing(char* argv) {
    int i;

    phonetic = 0;
    singmode = 1;

    char const_input[256];

    for(i = 0; i < 256; i++) {
        const_input[i] = argv[i];
    }

    sam(const_input, phonetic, singmode, pitch, speed, mouth, throat);
}

////////////////////////////////////////////////////////////////////////////////////////////
//
//           STM32SAM sayPhonetic (sing off, phonetic on)
//
////////////////////////////////////////////////////////////////////////////////////////////

void STM32SAM::sayPhonetic(const char* argv) {
    int i;

    phonetic = 1;
    singmode = 0;

    char const_input[256];

    for(i = 0; i < 256; i++) {
        const_input[i] = argv[i];
    }

    sam(const_input, phonetic, singmode, pitch, speed, mouth, throat);
}

void STM32SAM::sayPhonetic(char* argv) {
    int i;

    phonetic = 1;
    singmode = 0;

    char const_input[256];

    for(i = 0; i < 256; i++) {
        const_input[i] = argv[i];
    }

    sam(const_input, phonetic, singmode, pitch, speed, mouth, throat);
}

////////////////////////////////////////////////////////////////////////////////////////////
//
//           STM32SAM singPhonetic (sing on, phonetic on)
//
////////////////////////////////////////////////////////////////////////////////////////////

void STM32SAM::singPhonetic(const char* argv) {
    int i;

    phonetic = 1;
    singmode = 1;

    char const_input[256];

    for(i = 0; i < 256; i++) {
        const_input[i] = argv[i];
    }

    sam(const_input, phonetic, singmode, pitch, speed, mouth, throat);
}

void STM32SAM::singPhonetic(char* argv) {
    int i;

    phonetic = 1;
    singmode = 0;

    char const_input[256];

    for(i = 0; i < 256; i++) {
        const_input[i] = argv[i];
    }

    sam(const_input, phonetic, singmode, pitch, speed, mouth, throat);
}

////////////////////////////////////////////////////////////////////////////////////////////
//
//           STM32SAM voice (pitch, speed, mouth, throat)
//
////////////////////////////////////////////////////////////////////////////////////////////

void STM32SAM::setVoice(
    unsigned char _pitch /* = 64 */,
    unsigned char _speed /* = 72 */,
    unsigned char _mouth /* = 128 */,
    unsigned char _throat /* = 128 */) {
    pitch = _pitch;
    speed = _speed;
    mouth = _mouth;
    throat = _throat;
}

////////////////////////////////////////////////////////////////////////////////////////////
//
//           STM32SAM setPitch (pitch)
//
////////////////////////////////////////////////////////////////////////////////////////////

void STM32SAM::setPitch(unsigned char _pitch /* = 64 */) {
    pitch = _pitch;
}
////////////////////////////////////////////////////////////////////////////////////////////
//
//           STM32SAM setSpeed (speed)
//
////////////////////////////////////////////////////////////////////////////////////////////

void STM32SAM::setSpeed(unsigned char _speed /* = 72 */) {
    speed = _speed;
}
////////////////////////////////////////////////////////////////////////////////////////////
//
//           STM32SAM setMouth (mouth)
//
////////////////////////////////////////////////////////////////////////////////////////////

void STM32SAM::setMouth(unsigned char _mouth /* = 128 */) {
    mouth = _mouth;
}

////////////////////////////////////////////////////////////////////////////////////////////
//
//           STM32SAM setThroat (throat)
//
////////////////////////////////////////////////////////////////////////////////////////////

void STM32SAM::setThroat(unsigned char _throat /* = 128 */) {
    throat = _throat;
}
////////////////////////////////////////////////////////////////////////////////////////////
//
//           Hardware
//
////////////////////////////////////////////////////////////////////////////////////////////
// Hardware specifics, for easier porting to other microcontrollers

//
// Set PA8 pin as PWM, at 256 timer ticks overflow (8bit resolution)

#include <math.h>
#include <stm32wbxx_ll_tim.h>

#define FURI_HAL_SPEAKER_TIMER TIM16
#define FURI_HAL_SPEAKER_CHANNEL LL_TIM_CHANNEL_CH1

void STM32SAM::begin(void) {
#ifdef USE_ROGER_CORE

    pinMode(PA8, PWM); //   audio output pin

    Timer1.setPeriod(
        4); // Can't set at 256 ticks, only in uS. First nearest uS is 4 (Roger core is only for bluepill, that means 72*4=288 ticks, or 128*4=512 ticks when overclocked. It's ok, just overall volume will be lower, because maximum volume will be 256/288 or 256/512)

#endif

#ifdef USE_STM32duino_CORE
    pinMode(PA8, OUTPUT);

    PWM->pause();
    PWM->setMode(1, TIMER_OUTPUT_COMPARE_PWM1, PA8); // TIM1 CH1 (PA8)
    PWM->setPrescaleFactor(1);
    PWM->setOverflow(256, TICK_FORMAT); // 256 ticks overflow, no matter the CPU (timer) speed
    PWM->resume();

#endif

    LL_TIM_InitTypeDef TIM_InitStruct;
    memset(&TIM_InitStruct, 0, sizeof(LL_TIM_InitTypeDef));
    TIM_InitStruct.Prescaler = 4;
    TIM_InitStruct.Autoreload = 255;
    LL_TIM_Init(FURI_HAL_SPEAKER_TIMER, &TIM_InitStruct);

    LL_TIM_OC_InitTypeDef TIM_OC_InitStruct;
    memset(&TIM_OC_InitStruct, 0, sizeof(LL_TIM_OC_InitTypeDef));
    TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
    TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE;
    TIM_OC_InitStruct.CompareValue = 127;
    LL_TIM_OC_Init(FURI_HAL_SPEAKER_TIMER, FURI_HAL_SPEAKER_CHANNEL, &TIM_OC_InitStruct);

    LL_TIM_EnableAllOutputs(FURI_HAL_SPEAKER_TIMER);
    LL_TIM_EnableCounter(FURI_HAL_SPEAKER_TIMER);
} // begin

inline void STM32SAM::SetAUDIO(unsigned char main_volume) {
#ifdef USE_ROGER_CORE
    Timer1.setCompare(TIMER_CH1, main_volume);
#endif

#ifdef USE_STM32duino_CORE
    PWM->setCaptureCompare(1, main_volume, TICK_COMPARE_FORMAT);
#endif

    // if(main_volume > 64) {
    //     LL_TIM_OC_SetCompareCH1(FURI_HAL_SPEAKER_TIMER, 127);
    // } else {
    //     LL_TIM_OC_SetCompareCH1(FURI_HAL_SPEAKER_TIMER, main_volume);
    // }

    float data = main_volume;
    data /= 255.0f;
    data -= 0.5f;
    data *= 4.0f;
    data = tanhf(data);

    data += 0.5f;
    data *= 255.0f;

    if(data < 0) {
        data = 0;
    } else if(data > 255) {
        data = 255;
    }

    LL_TIM_OC_SetCompareCH1(FURI_HAL_SPEAKER_TIMER, data);
}