[
  {
    "path": "BatBonanzaAnalog/BatBonanzaAnalog.ino",
    "content": "/* 2015 / 2016 /2017\n * Pong clone by Andy Jackson - Twitter @andyhighnumber\n * Inspired by http://webboggles.com/ and includes some code from the #AttinyArcade games on that site\n * The code that does not fall under the licenses of sources listed below can be used non commercially with attribution.\n * \n * This code takes its inputs from two paddles - one on pin 7 (the centre of a 10k linear pot between the power rails), the other\n * on the reset pin - this time with a 6k8 resistor between the negative leg of the pot and ground (to stop it resetting the ATTINY85!)\n * You should be able to find the circuit diagram from the folder where these files are (if you got them from my Google Drive) otherwise\n * Tweet @andyhighnumber and I will direct you to the circuit.\n * \n * There's one button in this design (on pin 5). When the game is running, pressing and releasing the button cycles through modes, including \n * two-player games and one-player modes with varying degrees of difficulty. \n * \n * Also, from standby....\n *  Press and hold the button to reset all settings (good to do when you first flash the chip, since the settings are loaded from EEPROM)\n * \n * If you have problems uploading this sketch, this is probably due to sketch size - you need to update ld.exe in arduino\\hardware\\tools\\avr\\avr\\bin\n * https://github.com/TCWORLD/ATTinyCore/tree/master/PCREL%20Patch%20for%20GCC\n *\n * This sketch is using the screen control and font functions written by Neven Boyanov for the http://tinusaur.wordpress.com/ project\n * Source code and font files available at: https://bitbucket.org/tinusaur/ssd1306xled\n * **Note that this highly size-optimised version requires modified library functions (which are in this source code file) \n * and a modified font header\n * \n * Sleep code is based on this blog post by Matthew Little:\n * http://www.re-innovation.co.uk/web12/index.php/en/blog-75/306-sleep-modes-on-attiny85\n*/\n#include <EEPROM.h>\n#include \"font6x8AJ.h\"\n#include <avr/sleep.h>\n#include <avr/interrupt.h> // needed for the additional interrupt\n\n#define DIGITAL_WRITE_HIGH(PORT) PORTB |= (1 << PORT)\n#define DIGITAL_WRITE_LOW(PORT) PORTB &= ~(1 << PORT)\n\n// Routines to set and clear bits (used in the sleep code)\n#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))\n#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))\n\n// Defines for OLED output\n#define SSD1306XLED_H\n#define SSD1306_SCL   PORTB4  // SCL, Pin 4 on SSD1306 Board - for webbogles board\n#define SSD1306_SDA   PORTB3  // SDA, Pin 3 on SSD1306 Board - for webbogles board\n#define SSD1306_SA    0x78  // Slave address\n\n#define WINSCORE 7\n\n// Function prototypes\nvoid startGame(void);\nvoid drawPlatform(void);\nvoid drawPlatform2(void);\nvoid sendBlock(int);\nvoid playPong(void);\nvoid beep(int,int);\nvoid drawBall(int x, int y);\nvoid blankBall(int x, int y);\n\nvoid doDrawLS(long, byte);\nvoid doDrawRS(long, byte);\nvoid doNumber (int x, int y, int value);\n\nvoid ssd1306_init(void);\nvoid ssd1306_xfer_start(void);\nvoid ssd1306_xfer_stop(void);\nvoid ssd1306_send_byte(uint8_t byte);\nvoid ssd1306_send_command(uint8_t command);\nvoid ssd1306_send_data_start(void);\nvoid ssd1306_send_data_stop(void);\nvoid ssd1306_setpos(uint8_t x, uint8_t y);\nvoid ssd1306_fillscreen(uint8_t fill_Data);\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]);\nvoid ssd1306_draw_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t bitmap[]);\n\nint topScoreB = 0;\nint player; //0 to 128-platformWidth  - this is the position of the player\nint player2; //0 to 128-platformWidth  - this is the position of the player\nint lastPlayer;\nint lastPlayer2;\nint platformWidth = 16; \nboolean stopAnimate = 0; // this is set to 1 when a collision is detected\nboolean mute = 0;\nint score = 0; // score - this affects the difficulty of the game\nint score2 = 0; // score - this affects the difficulty of the game\n\nint ballx = 62*8; // coordinate of the ball\nint bally = 50*4; // coordinate of the ball\nint vdir = -4; // vertical direction and step  distance\nint hdir = -8; // horizontal direction and step distance\n\nint mode = 0;\n\nint perturbation = 0;\nint pFactor = 12;\n\n// Interrupt handlers\nISR(PCINT0_vect){ // PB0 pin button interrupt           \n}\n\nvoid playerIncPong(){ // PB2 pin button interrupt\n}\n\n// Arduino stuff - setup\nvoid setup() {\n  DDRB = 0b00000010;    // set PB1 as output (for the speaker)\n  PCMSK = 0b00000001; // pin change mask: listen to portb bit 1\n  GIMSK |= 0b00100000;  // enable PCINT interrupt \n  sei();          // enable all interrupts\n}\n\n// Arduino stuff - loop\nvoid loop() { \n  ssd1306_init();\n  ssd1306_fillscreen(0x00);\n  \n  // The lower case character set is seriously compromised because I've had to truncate the ASCII table\n  // to release space for executable code - hence lower case y and w are remapped to h and / respectively.\n  // There is no z in the table (or h!) as these aren't used anywhere in the text here and most of the \n  // symbols are also missing for the same reason (see my hacked version of font6x8.h - font6x8AJ.h for more detail)\n  ssd1306_char_f6x8(0, 1, \"   ---------------  \");\n  ssd1306_char_f6x8(0, 2, \"        B A T       \");\n  ssd1306_char_f6x8(0, 4, \"    B O N A N Z A   \");\n  ssd1306_char_f6x8(0, 5, \"   ---------------  \");\n  ssd1306_char_f6x8(0, 7, \"   bh andh jackson  \"); // see comments above !\n\n   long startT = millis();\n    long nowT =0;\n    boolean sChange = 0;\n    while(digitalRead(0) == HIGH) {\n      nowT = millis();\n      if (nowT - startT > 2000) {\n        sChange = 1;     \n        EEPROM.write(0,0);\n        EEPROM.write(1,0);\n        ssd1306_char_f6x8(16, 0, \"- SYSTEM RESET -\");  \n        break;\n      }\n      if (sChange == 1) break;\n    }  \n    while(digitalRead(0) == HIGH);\n\n    mute=EEPROM.read(0);\n    mode=EEPROM.read(1);\n\n    if (mute != 0 && mute != 1) {\n      mute = 0;\n       EEPROM.write(0,0);\n    }\n\n    if (mode < 0 || mode > 5) {\n      mode = 0;\n      EEPROM.write(1,0);\n    }\n\n    if (sChange != 1) {\n    delay(1500);\n    ssd1306_init();\n    ssd1306_fillscreen(0x00);\n    stopAnimate = 0;\n    score = 0;\n    score2 = 0;\n\n    playPong(); \n    \n    delay(3500);\n \n  }\n  system_sleep();\n}\n\nvoid doNumber (int x, int y, int value) {\n    char temp[10] = {0,0,0,0,0,0,0,0,0,0};\n    itoa(value,temp,10);\n    ssd1306_char_f6x8(x, y, temp);\n}\n\nvoid ssd1306_init(void){\n  DDRB |= (1 << SSD1306_SDA); // Set port as output\n  DDRB |= (1 << SSD1306_SCL); // Set port as output\n\n  ssd1306_send_command(0xAE); // display off\n  ssd1306_send_command(0x00); // Set Memory Addressing Mode\n  ssd1306_send_command(0x10); // 00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid\n  ssd1306_send_command(0x40); // Set Page Start Address for Page Addressing Mode,0-7\n  ssd1306_send_command(0x81); // Set COM Output Scan Direction\n  ssd1306_send_command(0xCF); // ---set low column address\n  ssd1306_send_command(0xA1); // ---set high column address\n  ssd1306_send_command(0xC8); // --set start line address\n  ssd1306_send_command(0xA6); // --set contrast control register\n  ssd1306_send_command(0xA8);\n  ssd1306_send_command(0x3F); // --set segment re-map 0 to 127\n  ssd1306_send_command(0xD3); // --set normal display\n  ssd1306_send_command(0x00); // --set multiplex ratio(1 to 64)\n  ssd1306_send_command(0xD5); // \n  ssd1306_send_command(0x80); // 0xa4,Output follows RAM content;0xa5,Output ignores RAM content\n  ssd1306_send_command(0xD9); // -set display offset\n  ssd1306_send_command(0xF1); // -not offset\n  ssd1306_send_command(0xDA); // --set display clock divide ratio/oscillator frequency\n  ssd1306_send_command(0x12); // --set divide ratio\n  ssd1306_send_command(0xDB); // --set pre-charge period\n  ssd1306_send_command(0x40); // \n  ssd1306_send_command(0x20); // --set com pins hardware configuration\n  ssd1306_send_command(0x02);\n  ssd1306_send_command(0x8D); // --set vcomh\n  ssd1306_send_command(0x14); // 0x20,0.77xVcc\n  ssd1306_send_command(0xA4); // --set DC-DC enable\n  ssd1306_send_command(0xA6); // \n  ssd1306_send_command(0xAF); // --turn on oled panel \n}\n\nvoid ssd1306_xfer_start(void){\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n}\n\nvoid ssd1306_xfer_stop(void){\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n}\n\nvoid ssd1306_send_byte(uint8_t byte){\n  uint8_t i;\n  for(i=0; i<8; i++)\n  {\n    if((byte << i) & 0x80)\n      DIGITAL_WRITE_HIGH(SSD1306_SDA);\n    else\n      DIGITAL_WRITE_LOW(SSD1306_SDA);\n    \n    DIGITAL_WRITE_HIGH(SSD1306_SCL);\n    DIGITAL_WRITE_LOW(SSD1306_SCL);\n  }\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);\n  DIGITAL_WRITE_LOW(SSD1306_SCL);\n}\n\nvoid ssd1306_send_command(uint8_t command){\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  // Slave address, SA0=0\n  ssd1306_send_byte(0x00);  // write command\n  ssd1306_send_byte(command);\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_send_data_start(void){\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);\n  ssd1306_send_byte(0x40);  //write data\n}\n\nvoid ssd1306_send_data_stop(void){\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_setpos(uint8_t x, uint8_t y)\n{\n  if (y>7) return;\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  //Slave address,SA0=0\n  ssd1306_send_byte(0x00);  //write command\n\n  ssd1306_send_byte(0xb0+y);\n  ssd1306_send_byte(((x&0xf0)>>4)|0x10); // |0x10\n  ssd1306_send_byte((x&0x0f)|0x01); // |0x01\n\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_fillscreen(uint8_t fill_Data){\n  uint8_t m,n;\n  for(m=0;m<8;m++)\n  {\n    ssd1306_send_command(0xb0+m); //page0-page1\n    ssd1306_send_command(0x00);   //low column start address\n    ssd1306_send_command(0x10);   //high column start address\n    ssd1306_send_data_start();\n    for(n=0;n<128;n++)\n    {\n      ssd1306_send_byte(fill_Data);\n    }\n    ssd1306_send_data_stop();\n  }\n}\n\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]){\n  uint8_t c,i,j=0;\n  while(ch[j] != '\\0')\n  {\n    c = ch[j] - 32;\n    if (c >0) c = c - 12;\n    if (c >15) c = c - 6;\n    if (c>40) c=c-6;\n    if(x>126)\n    {\n      x=0;\n      y++;\n    }\n    ssd1306_setpos(x,y);\n    ssd1306_send_data_start();\n    for(i=0;i<6;i++)\n    {\n      ssd1306_send_byte(pgm_read_byte(&ssd1306xled_font6x8[c*6+i]));\n    }\n    ssd1306_send_data_stop();\n    x += 6;\n    j++;\n  }\n}\n\nvoid system_sleep() {\n  ssd1306_fillscreen(0x00);\n  ssd1306_send_command(0xAE);\n  cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF\n  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here\n  sleep_enable();\n  sleep_mode();                        // System actually sleeps here\n  sleep_disable();                     // System continues execution here when watchdog timed out \n  sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON  \n  ssd1306_send_command(0xAF);\n}\n\nvoid beep(int bCount,int bDelay){\n  if (mute) return;\n  for (int i = 0; i<=bCount; i++){digitalWrite(1,HIGH);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}digitalWrite(1,LOW);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}}\n}\n\n\n\n/* ------------------------\n *  Pong Code\n */\nvoid playPong() {\n  ballx = 64*8;\n  bally = 32*4;\n  hdir = -8;\n  vdir = -4;\n  int actualy, actualx;\n  int factor = 0;\n  int waitCount = 0;\n\n  int lastx=64*8, lasty=32*4;\n\n  player=64;\n  player2=64;\n  lastPlayer = 64;\n  lastPlayer2 = 64;\n  score = 0; // obvious\n  score2 = 0; // obvious\n  perturbation = 0;\n  \n  startGame();\n  while (stopAnimate == 0) {\n    while(1) {\n    waitCount++;\n    \n    if(digitalRead(0)==1) {\n      boolean sChange = 0;\n      long startT = millis();\n      long nowT =0;\n      while(digitalRead(0) == HIGH) {\n        nowT = millis();\n        if (nowT - startT > 1500) {\n          sChange = 1;\n          if (mute == 0) { mute = 1; ssd1306_char_f6x8(32, 0, \"-- MUTE --\"); } else { mute = 0; ssd1306_char_f6x8(23, 0, \"-- SOUND ON --\"); }\n          break;\n        }\n      }\n      while(digitalRead(0) == HIGH);\n      if (sChange == 1) {\n      } else if (mode == 0) { \n          mode = 1; \n          ssd1306_char_f6x8(26, 0, \"-- EXPERT --\");  \n          } else if (mode == 1) { \n            mode = 2; \n            pFactor = 11;\n            ssd1306_char_f6x8(32, 0, \"-- AUTO --\"); \n          } else if (mode == 2) { \n            mode = 3; \n            pFactor = 11;\n            ssd1306_char_f6x8(20, 0, \"- TOUGH AUTO -\");  \n          } else if (mode == 3) { \n            mode = 4; \n            pFactor = 10;\n            ssd1306_char_f6x8(16, 0, \"- EXPERT AUTO -\");  \n          } else if (mode == 4) { \n            mode = 0; \n            ssd1306_char_f6x8(26, 0, \"-- NORMAL --\");  \n          }\n      \n      if (sChange == 0) delay(1000);\n      ssd1306_fillscreen(0x00);        \n      EEPROM.write(0,mute);\n      EEPROM.write(1,mode);\n    }\n\n    player = ((analogRead(0)-560)/7);\n        if (player > 48) player = 48;\n    if (player <0) player = 0;\n\n\n    player2 = (analogRead(1) / 16);\n    if (mode == 2 || mode == 3 || mode == 4) {\n      if(waitCount >= 3) {\n        waitCount = 0;\n        perturbation = perturbation - 2 + random(0,5);\n        if (perturbation > pFactor) perturbation = pFactor - 2;\n        if (perturbation < pFactor*-1) perturbation = (pFactor*-1)+2;\n      }\n      player2 = (bally/4 -8)+perturbation;\n    }\n    if (player2 > 48) player2 = 48;\n    if (player2 <0) player2 = 0;\n\n    actualy = floor(bally/4);\n    actualx = floor(ballx/8);\n    \n    // bounce off the sides of the screen\n    if ((actualy+vdir<63&&vdir>01) || (actualy- vdir>6&&vdir<0)){\n      bally+=vdir;\n    }else {\n        vdir = vdir*-1;\n    }\n    ballx+=hdir;\n\n    actualy = floor(bally/4);\n    actualx = floor(ballx/8);\n    \n    // check it hits the left pad and deal with bounces and misses\n    if (actualx <= 4) {\n      if(actualy<player-1||actualy>player+platformWidth+1){ \n        score2++;\n    \n        ballx = 5*8;\n        bally = player*4;\n\n        hdir = 13;\n        if (vdir > 0) {\n          vdir = 2;\n        } else vdir = -2;\n        \n        ssd1306_fillscreen(0x00);        \n        doNumber(46,4,score);\n        doNumber(78,4,score2);        \n        if (score2 < WINSCORE) {\n          for (int i = 0; i<1000; i = i+ 100){\n            beep(50,i);\n          }\n          for (int incr=0;incr<3;incr++) {\n              ssd1306_send_data_stop();\n              ssd1306_setpos(78,4);\n              ssd1306_send_data_start();\n              sendBlock(0);\n              sendBlock(0);\n              ssd1306_send_data_stop();\n              delay(350);\n              doNumber(78,4,score2);\n              delay(350);\n            }\n            startGame();\n        }\n        perturbation = 0;\n        break;\n      }else if (actualy<player+1){        \n        vdir = -6;\n        hdir = 7;\n      }else if (actualy<player+4){        \n        vdir = -4;\n        hdir = 10;\n      }else if (actualy<player+7){        \n        vdir = -2;\n        hdir = 13;\n      }else if (actualy<player+9){        \n        vdir = 0;\n        hdir = 14;\n      }else if (actualy<player+12){        \n        vdir = 2;\n        hdir = 13;\n      }else if (actualy<player+15){        \n        vdir = 4;\n        hdir = 10;\n      }else {   \n        vdir = 6;\n        hdir = 7;\n      }\n      beep(20,600);\n    }  \n    \n    // check it hits the right pad and deal with bounces\n    if(actualx >= 122) {\n      if(actualy<player2-1||actualy>player2+platformWidth+1){\n        score++;\n  \n        ballx = 120*8;\n        bally = player2*4;\n\n        hdir = -13;\n        if (vdir > 0) {\n          vdir = 2;\n        } else vdir = -2;\n\n        ssd1306_fillscreen(0x00);        \n        doNumber(46,4,score);\n        doNumber(78,4,score2);\n        if (score < WINSCORE) {\n        for (int i = 0; i<1000; i = i+ 100){\n            beep(50,i);\n          }                \n  \n          for (int incr=0;incr<3;incr++) {\n              ssd1306_setpos(46,4);\n              ssd1306_send_data_start();\n              sendBlock(0);\n              sendBlock(0);\n              ssd1306_send_data_stop();\n              delay(350);\n              doNumber(46,4,score);\n              delay(350);\n            }\n            perturbation = 0;\n            startGame();\n        }        \n        break;\n      }else if (actualy<player2+1){        \n        vdir = -6;\n        hdir = -7;\n      }else if (actualy<player2+4){        \n        vdir = -4;\n        hdir = -10;\n      }else if (actualy<player2+7){        \n        vdir = -2;\n        hdir = -13;\n      }else if (actualy<player2+9){        \n        vdir = 0;\n        hdir = -14;\n      }else if (actualy<player2+12){        \n        vdir = 2;\n        hdir = -13;\n      }else if (actualy<player2+15){        \n        vdir = 4;\n        hdir = -10;\n      }else {   \n        vdir = 6;\n        hdir = -7;\n      }\n      beep(20,300);\n    }      \n\n    \n    if (mode == 1 || mode == 3 || mode == 4) {\n      factor = 8-floor((score-score2)/2); // expert modes\n      if (factor < 2) factor = 2;\n    } else {\n      factor = 20-floor((score-score2)/2); // normal modes\n      if (factor < 10) factor = 10;\n    }\n    \n    delay(factor);\n    \n    // draw ball\n    blankBall(floor(lastx/8),floor(lasty/4));  \n    drawPlatform();\n    drawPlatform2();\n    drawBall(floor(ballx/8),floor(bally/4));\n    lastx = ballx;\n    lasty = bally;\n    \n    doNumber(28,0,score);\n    doNumber(92,0,score2);\n    if (score == WINSCORE || score2 == WINSCORE) {\n      stopAnimate = 1;\n      break;\n    }\n    }\n }\n\nblankBall(floor(lastx/8),floor(lasty/4));  \nblankBall(floor(ballx/8),floor(bally/4));  \n\nif (score > score2) {\n  ssd1306_char_f6x8(27, 3, \"P L A Y E R 1\"); \n} else {\n  ssd1306_char_f6x8(27, 3, \"P L A Y E R 2\"); \n}\nssd1306_char_f6x8(27, 4, \"             \");\nssd1306_char_f6x8(27, 5, \"   W I N S   \");\n\nfor (int i = 0; i<1000; i = i+ 50){\n  beep(50,i);\n}\n\n\nfor (int incr=0;incr<6;incr++) {\n    ssd1306_setpos(28,0);\n    ssd1306_send_data_start();\n    sendBlock(0);\n    sendBlock(0);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(92,0);\n    ssd1306_send_data_start();\n    sendBlock(0);\n    sendBlock(0);\n    ssd1306_send_data_stop();\n    delay(350);\n    doNumber(28,0,score);\n    doNumber(92,0,score2);\n    delay(350);\n  }\n}\n\nvoid drawPlatform() {\n  if (player != lastPlayer) {\n    ssd1306_setpos(0,lastPlayer/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(0,lastPlayer/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop(); \n    ssd1306_setpos(0,lastPlayer/8+2);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop(); \n  }  \n\n  if (player%8!=0){\n    ssd1306_setpos(0,player/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte((B11111111)<<player%8);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(0,player/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B11111111);\n    ssd1306_send_data_stop();    \n    ssd1306_setpos(0,player/8+2);\n    ssd1306_send_data_start();\n    ssd1306_send_byte((B01111110)>>8-player%8);\n    ssd1306_send_data_stop();\n  } else {\n    ssd1306_setpos(0,player/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B11111111);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(0,player/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B11111111);\n    ssd1306_send_data_stop();\n\n  }\n  lastPlayer = player;\n}\n\nvoid drawPlatform2() {\n\n  if (player2 != lastPlayer2) {\n    ssd1306_setpos(127,lastPlayer2/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(127,lastPlayer2/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop(); \n    ssd1306_setpos(127,lastPlayer2/8+2);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop(); \n  }\n  \n  if (player2%8!=0){\n    ssd1306_setpos(127,player2/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte((B11111111)<<player2%8);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(127,player2/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B11111111);\n    ssd1306_send_data_stop();        \n    ssd1306_setpos(127,player2/8+2);\n    ssd1306_send_data_start();\n    ssd1306_send_byte((B01111110)>>8-player2%8);\n    ssd1306_send_data_stop();\n  } else {\n    ssd1306_setpos(127,player2/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte((B11111111)<<0);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(127,player2/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte((B11111111)<<0);\n    ssd1306_send_data_stop();\n  }\n  lastPlayer2 = player2;\n}\n\n\n\nvoid sendBlock(int fill){\n  if (fill == 1) {\n   ssd1306_send_byte(B10011000);\n   ssd1306_send_byte(B01011100);\n   ssd1306_send_byte(B10110110);\n   ssd1306_send_byte(B01011111);\n   ssd1306_send_byte(B01011111);\n   ssd1306_send_byte(B10110110);\n   ssd1306_send_byte(B01011100);\n   ssd1306_send_byte(B10011000);\n  } else  {\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n  } \n}\n\nvoid blankBall(int x, int y) {\n  if (y%8!=0){\n    ssd1306_setpos(x,y/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop();\n    \n    ssd1306_setpos(x,y/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop();\n  } else {\n    ssd1306_setpos(x,y/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop();\n  }\n}\n\n\nvoid drawBall(int x, int y) {\n  if (y%8!=0){\n    ssd1306_setpos(x,y/8);\n    ssd1306_send_data_start();\n    doDrawLS(0,y%8);\n    ssd1306_send_data_stop();\n    \n    ssd1306_setpos(x,y/8+1);\n    ssd1306_send_data_start();\n    doDrawRS(0,8-y%8);\n    ssd1306_send_data_stop();\n  } else {\n    ssd1306_setpos(x,y/8);\n    ssd1306_send_data_start();\n    doDrawLS(0,0);\n    ssd1306_send_data_stop();\n  }\n}\n\n// Drawing routine for the player and fire - with right-shifts\nvoid doDrawRS(long P1, byte P2) {\n  ssd1306_send_byte((B00000011 | P1)>>P2);\n  ssd1306_send_byte((B00000011 | P1)>>P2);\n}\n\n// Drawing routine for the player and fire - with left-shifts\nvoid doDrawLS(long P1, byte P2) {\n  ssd1306_send_byte((B00000011 | P1)<<P2);\n  ssd1306_send_byte((B00000011 | P1)<<P2);\n}\n\nvoid startGame(void) {\n  \n    ssd1306_fillscreen(0x00);\n\n    ssd1306_char_f6x8(16, 3, \"-- GET READY --\");\n    doNumber(60,5,3);\n    delay(1000);\n    doNumber(60,5,2);\n    delay(1000);\n    doNumber(60,5,1);\n    delay(1000);\n    ssd1306_fillscreen(0x00);\n\n    for (int i = 800; i>200; i = i - 200){\n    beep(30,i);\n    }\n\n}\n\r\n"
  },
  {
    "path": "BatBonanzaAnalog/font6x8AJ.h",
    "content": "/*\n * SSD1306xLED - Drivers for SSD1306 controlled dot matrix OLED/PLED 128x64 displays\n *\n * @file: font6x8.h\n * @created: 2014-08-12\n * @author: Neven Boyanov\n * \n * Hacked by andy jackson to allow two games (originally by webboggles.com) to \n * fit onto an ATTiny85 at the same time - hence several characters are missing\n * and a couple have been moved to limit the amount of software remapping required\n * to map ASCII values onto locations in this array.\n *\n * Source code available at: https://bitbucket.org/tinusaur/ssd1306xled\n *\n */\n\n// ----------------------------------------------------------------------------\n\n#include <avr/pgmspace.h>\n\n// ----------------------------------------------------------------------------\n\n/* Standard ASCII 6x8 font */\nstatic const uint8_t ssd1306xled_font6x8 [] PROGMEM = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sp\n/*\n  0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // !\n  0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // \"\n  0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // #\n  0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $\n  0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // %\n  0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // &\n  0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // '\n  0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // (\n  0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // )\n  0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // *\n  0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // +\n  0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // ,\n  */\n  0x00, 0x08, 0x08, 0x08, 0x08, 0x08, // -\n  0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // .\n  0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w in place of /\n  //0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // /\n  0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0\n  0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, // 1\n  0x00, 0x42, 0x61, 0x51, 0x49, 0x46, // 2\n  0x00, 0x21, 0x41, 0x45, 0x4B, 0x31, // 3\n  0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, // 4\n  0x00, 0x27, 0x45, 0x45, 0x45, 0x39, // 5\n  0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6\n  0x00, 0x01, 0x71, 0x09, 0x05, 0x03, // 7\n  0x00, 0x36, 0x49, 0x49, 0x49, 0x36, // 8\n  0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, // 9\n  0x00, 0x00, 0x36, 0x36, 0x00, 0x00, // :\n/*\n  0x00, 0x00, 0x56, 0x36, 0x00, 0x00, // ;\n  0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // <\n  0x00, 0x14, 0x14, 0x14, 0x14, 0x14, // =\n  0x00, 0x00, 0x41, 0x22, 0x14, 0x08, // >\n  0x00, 0x02, 0x01, 0x51, 0x09, 0x06, // ?\n  0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, // @\n */\n  0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, // B\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, // C\n  0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, // D\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, // E\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, // F\n  0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, // G\n  0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, // H\n  0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, // I\n  0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, // J\n  0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, // K\n  0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, // L\n  0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M\n  0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, // N\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, // O\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, // P\n  0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q\n  0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, // R\n  0x00, 0x46, 0x49, 0x49, 0x49, 0x31, // S\n  0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, // T\n  0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, // U\n  0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, // V\n  0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, // W\n  0x00, 0x63, 0x14, 0x08, 0x14, 0x63, // X\n  0x00, 0x07, 0x08, 0x70, 0x08, 0x07, // Y\n  0x00, 0x61, 0x51, 0x49, 0x45, 0x43, // Z\n  /*\n  0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, // [\n  0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55, // 55\n  0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, // ]\n  0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^\n  0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _\n  0x00, 0x00, 0x01, 0x02, 0x04, 0x00, // '\n*/\n  0x00, 0x20, 0x54, 0x54, 0x54, 0x78, // a\n  0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, // b\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x20, // c\n  0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, // d\n  0x00, 0x38, 0x54, 0x54, 0x54, 0x18, // e\n  0x00, 0x08, 0x7E, 0x09, 0x01, 0x02, // f\n  0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g\n  0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C, // y (in place of h)\n  //0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h\n  0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, // i\n  0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, // j\n  0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, // k\n  0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, // l\n  0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, // m\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, // n\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x38, // o\n  0x00, 0xFC, 0x24, 0x24, 0x24, 0x18, // p\n  0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, // q\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, // r\n  0x00, 0x48, 0x54, 0x54, 0x54, 0x20, // s\n  0x00, 0x04, 0x3F, 0x44, 0x40, 0x20, // t\n  0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, // u\n  0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, // v\n // 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w\n // 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, // x\n // 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C // y\n};\n\n// ----------------------------------------------------------------------------\n\r\n"
  },
  {
    "path": "BatBonanzaAnalogSinglePot/BatBonanzaAnalogSinglePot.ino",
    "content": "/* 2015 / 2016 /2017\n * Pong clone by Andy Jackson - Twitter @andyhighnumber\n * Inspired by http://webboggles.com/ and includes some code from the #AttinyArcade games on that site\n * The code that does not fall under the licenses of sources listed below can be used non commercially with attribution.\n * \n * This code takes its inputs from one paddles - same as my analog Space Invaders Clone\n * Tweet @andyhighnumber and I will direct you to the circuit.\n * \n * There's one button in this design (on pin 5). When the game is running, pressing and releasing the button cycles through modes, with varying degrees of difficulty. \n * \n * Also, from standby....\n *  Press and hold the button to reset all settings (good to do when you first flash the chip, since the settings are loaded from EEPROM)\n * \n * If you have problems uploading this sketch, this is probably due to sketch size - you need to update ld.exe in arduino\\hardware\\tools\\avr\\avr\\bin\n * https://github.com/TCWORLD/ATTinyCore/tree/master/PCREL%20Patch%20for%20GCC\n *\n * This sketch is using the screen control and font functions written by Neven Boyanov for the http://tinusaur.wordpress.com/ project\n * Source code and font files available at: https://bitbucket.org/tinusaur/ssd1306xled\n * **Note that this highly size-optimised version requires modified library functions (which are in this source code file) \n * and a modified font header\n * \n * Sleep code is based on this blog post by Matthew Little:\n * http://www.re-innovation.co.uk/web12/index.php/en/blog-75/306-sleep-modes-on-attiny85\n*/\n#include <EEPROM.h>\n#include \"font6x8AJ.h\"\n#include <avr/sleep.h>\n#include <avr/interrupt.h> // needed for the additional interrupt\n\n#define DIGITAL_WRITE_HIGH(PORT) PORTB |= (1 << PORT)\n#define DIGITAL_WRITE_LOW(PORT) PORTB &= ~(1 << PORT)\n\n// Routines to set and clear bits (used in the sleep code)\n#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))\n#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))\n\n// Defines for OLED output\n#define SSD1306XLED_H\n#define SSD1306_SCL   PORTB4  // SCL, Pin 4 on SSD1306 Board - for webbogles board\n#define SSD1306_SDA   PORTB3  // SDA, Pin 3 on SSD1306 Board - for webbogles board\n#define SSD1306_SA    0x78  // Slave address\n\n#define WINSCORE 7\n\n// Function prototypes\nvoid startGame(void);\nvoid drawPlatform(void);\nvoid drawPlatform2(void);\nvoid sendBlock(int);\nvoid playPong(void);\nvoid beep(int,int);\nvoid drawBall(int x, int y);\nvoid blankBall(int x, int y);\n\nvoid doDrawLS(long, byte);\nvoid doDrawRS(long, byte);\nvoid doNumber (int x, int y, int value);\n\nvoid ssd1306_init(void);\nvoid ssd1306_xfer_start(void);\nvoid ssd1306_xfer_stop(void);\nvoid ssd1306_send_byte(uint8_t byte);\nvoid ssd1306_send_command(uint8_t command);\nvoid ssd1306_send_data_start(void);\nvoid ssd1306_send_data_stop(void);\nvoid ssd1306_setpos(uint8_t x, uint8_t y);\nvoid ssd1306_fillscreen(uint8_t fill_Data);\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]);\nvoid ssd1306_draw_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t bitmap[]);\n\nint topScoreB = 0;\nint player; //0 to 128-platformWidth  - this is the position of the player\nint player2; //0 to 128-platformWidth  - this is the position of the player\nint lastPlayer;\nint lastPlayer2;\nint platformWidth = 16; \nboolean stopAnimate = 0; // this is set to 1 when a collision is detected\nboolean mute = 0;\nint score = 0; // score - this affects the difficulty of the game\nint score2 = 0; // score - this affects the difficulty of the game\n\nint ballx = 62*8; // coordinate of the ball\nint bally = 50*4; // coordinate of the ball\nint vdir = -4; // vertical direction and step  distance\nint hdir = -8; // horizontal direction and step distance\n\nint mode = 2;\n\nint perturbation = 0;\nint pFactor = 12;\n\n// Interrupt handlers\nISR(PCINT0_vect){ // PB0 pin button interrupt           \n}\n\nvoid playerIncPong(){ // PB2 pin button interrupt\n}\n\n// Arduino stuff - setup\nvoid setup() {\n  DDRB = 0b00000010;    // set PB1 as output (for the speaker)\n  PCMSK = 0b00000001; // pin change mask: listen to portb bit 1\n  GIMSK |= 0b00100000;  // enable PCINT interrupt \n  sei();          // enable all interrupts\n}\n\n// Arduino stuff - loop\nvoid loop() { \n  ssd1306_init();\n  ssd1306_fillscreen(0x00);\n  \n  // The lower case character set is seriously compromised because I've had to truncate the ASCII table\n  // to release space for executable code - hence lower case y and w are remapped to h and / respectively.\n  // There is no z in the table (or h!) as these aren't used anywhere in the text here and most of the \n  // symbols are also missing for the same reason (see my hacked version of font6x8.h - font6x8AJ.h for more detail)\n  ssd1306_char_f6x8(0, 1, \"   ---------------  \");\n  ssd1306_char_f6x8(0, 2, \"        B A T       \");\n  ssd1306_char_f6x8(0, 4, \"    B O N A N Z A   \");\n  ssd1306_char_f6x8(0, 5, \"   ---------------  \");\n  ssd1306_char_f6x8(0, 7, \"   bh andh jackson  \"); // see comments above !\n\n   long startT = millis();\n    long nowT =0;\n    boolean sChange = 0;\n    while(digitalRead(0) == HIGH) {\n      nowT = millis();\n      if (nowT - startT > 2000) {\n        sChange = 1;     \n        EEPROM.write(0,0);\n        EEPROM.write(1,1);\n        ssd1306_char_f6x8(16, 0, \"- SYSTEM RESET -\");  \n        break;\n      }\n      if (sChange == 1) break;\n    }  \n    while(digitalRead(0) == HIGH);\n\n    mute=EEPROM.read(0);\n    mode=EEPROM.read(1);\n\n    if (mute != 0 && mute != 1) {\n      mute = 0;\n       EEPROM.write(0,0);\n    }\n\n    if (mode < 2 || mode > 5) {\n      mode = 2;\n      EEPROM.write(1,2);\n    }\n\n    if (sChange != 1) {\n    delay(1500);\n    ssd1306_init();\n    ssd1306_fillscreen(0x00);\n    stopAnimate = 0;\n    score = 0;\n    score2 = 0;\n\n    playPong(); \n    \n    delay(3500);\n \n  }\n  system_sleep();\n}\n\nvoid doNumber (int x, int y, int value) {\n    char temp[10] = {0,0,0,0,0,0,0,0,0,0};\n    itoa(value,temp,10);\n    ssd1306_char_f6x8(x, y, temp);\n}\n\nvoid ssd1306_init(void){\n  DDRB |= (1 << SSD1306_SDA); // Set port as output\n  DDRB |= (1 << SSD1306_SCL); // Set port as output\n\n  ssd1306_send_command(0xAE); // display off\n  ssd1306_send_command(0x00); // Set Memory Addressing Mode\n  ssd1306_send_command(0x10); // 00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid\n  ssd1306_send_command(0x40); // Set Page Start Address for Page Addressing Mode,0-7\n  ssd1306_send_command(0x81); // Set COM Output Scan Direction\n  ssd1306_send_command(0xCF); // ---set low column address\n  ssd1306_send_command(0xA1); // ---set high column address\n  ssd1306_send_command(0xC8); // --set start line address\n  ssd1306_send_command(0xA6); // --set contrast control register\n  ssd1306_send_command(0xA8);\n  ssd1306_send_command(0x3F); // --set segment re-map 0 to 127\n  ssd1306_send_command(0xD3); // --set normal display\n  ssd1306_send_command(0x00); // --set multiplex ratio(1 to 64)\n  ssd1306_send_command(0xD5); // \n  ssd1306_send_command(0x80); // 0xa4,Output follows RAM content;0xa5,Output ignores RAM content\n  ssd1306_send_command(0xD9); // -set display offset\n  ssd1306_send_command(0xF1); // -not offset\n  ssd1306_send_command(0xDA); // --set display clock divide ratio/oscillator frequency\n  ssd1306_send_command(0x12); // --set divide ratio\n  ssd1306_send_command(0xDB); // --set pre-charge period\n  ssd1306_send_command(0x40); // \n  ssd1306_send_command(0x20); // --set com pins hardware configuration\n  ssd1306_send_command(0x02);\n  ssd1306_send_command(0x8D); // --set vcomh\n  ssd1306_send_command(0x14); // 0x20,0.77xVcc\n  ssd1306_send_command(0xA4); // --set DC-DC enable\n  ssd1306_send_command(0xA6); // \n  ssd1306_send_command(0xAF); // --turn on oled panel \n}\n\nvoid ssd1306_xfer_start(void){\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n}\n\nvoid ssd1306_xfer_stop(void){\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n}\n\nvoid ssd1306_send_byte(uint8_t byte){\n  uint8_t i;\n  for(i=0; i<8; i++)\n  {\n    if((byte << i) & 0x80)\n      DIGITAL_WRITE_HIGH(SSD1306_SDA);\n    else\n      DIGITAL_WRITE_LOW(SSD1306_SDA);\n    \n    DIGITAL_WRITE_HIGH(SSD1306_SCL);\n    DIGITAL_WRITE_LOW(SSD1306_SCL);\n  }\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);\n  DIGITAL_WRITE_LOW(SSD1306_SCL);\n}\n\nvoid ssd1306_send_command(uint8_t command){\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  // Slave address, SA0=0\n  ssd1306_send_byte(0x00);  // write command\n  ssd1306_send_byte(command);\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_send_data_start(void){\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);\n  ssd1306_send_byte(0x40);  //write data\n}\n\nvoid ssd1306_send_data_stop(void){\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_setpos(uint8_t x, uint8_t y)\n{\n  if (y>7) return;\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  //Slave address,SA0=0\n  ssd1306_send_byte(0x00);  //write command\n\n  ssd1306_send_byte(0xb0+y);\n  ssd1306_send_byte(((x&0xf0)>>4)|0x10); // |0x10\n  ssd1306_send_byte((x&0x0f)|0x01); // |0x01\n\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_fillscreen(uint8_t fill_Data){\n  uint8_t m,n;\n  for(m=0;m<8;m++)\n  {\n    ssd1306_send_command(0xb0+m); //page0-page1\n    ssd1306_send_command(0x00);   //low column start address\n    ssd1306_send_command(0x10);   //high column start address\n    ssd1306_send_data_start();\n    for(n=0;n<128;n++)\n    {\n      ssd1306_send_byte(fill_Data);\n    }\n    ssd1306_send_data_stop();\n  }\n}\n\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]){\n  uint8_t c,i,j=0;\n  while(ch[j] != '\\0')\n  {\n    c = ch[j] - 32;\n    if (c >0) c = c - 12;\n    if (c >15) c = c - 6;\n    if (c>40) c=c-6;\n    if(x>126)\n    {\n      x=0;\n      y++;\n    }\n    ssd1306_setpos(x,y);\n    ssd1306_send_data_start();\n    for(i=0;i<6;i++)\n    {\n      ssd1306_send_byte(pgm_read_byte(&ssd1306xled_font6x8[c*6+i]));\n    }\n    ssd1306_send_data_stop();\n    x += 6;\n    j++;\n  }\n}\n\nvoid system_sleep() {\n  ssd1306_fillscreen(0x00);\n  ssd1306_send_command(0xAE);\n  cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF\n  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here\n  sleep_enable();\n  sleep_mode();                        // System actually sleeps here\n  sleep_disable();                     // System continues execution here when watchdog timed out \n  sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON  \n  ssd1306_send_command(0xAF);\n}\n\nvoid beep(int bCount,int bDelay){\n  if (mute) return;\n  for (int i = 0; i<=bCount; i++){digitalWrite(1,HIGH);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}digitalWrite(1,LOW);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}}\n}\n\n\n\n/* ------------------------\n *  Pong Code\n */\nvoid playPong() {\n  ballx = 64*8;\n  bally = 32*4;\n  hdir = -8;\n  vdir = -4;\n  int actualy, actualx;\n  int factor = 0;\n  int waitCount = 0;\n\n  int lastx=64*8, lasty=32*4;\n\n  player=64;\n  player2=64;\n  lastPlayer = 64;\n  lastPlayer2 = 64;\n  score = 0; // obvious\n  score2 = 0; // obvious\n  perturbation = 0;\n  \n  startGame();\n  while (stopAnimate == 0) {\n    while(1) {\n    waitCount++;\n    \n    if(digitalRead(0)==1) {\n      boolean sChange = 0;\n      long startT = millis();\n      long nowT =0;\n      while(digitalRead(0) == HIGH) {\n        nowT = millis();\n        if (nowT - startT > 1500) {\n          sChange = 1;\n          if (mute == 0) { mute = 1; ssd1306_char_f6x8(32, 0, \"-- MUTE --\"); } else { mute = 0; ssd1306_char_f6x8(23, 0, \"-- SOUND ON --\"); }\n          break;\n        }\n      }\n      while(digitalRead(0) == HIGH);\n      if (sChange == 1) {\n      } else if (mode == 2) { \n          mode = 3; \n          pFactor = 11;\n          ssd1306_char_f6x8(26, 0, \"-- TOUGH  --\");  \n        } else if (mode == 3) { \n          mode = 4; \n          pFactor = 10;\n          ssd1306_char_f6x8(26, 0, \"-- EXPERT --\");  \n        } else if (mode == 4) { \n          mode = 2; \n          ssd1306_char_f6x8(26, 0, \"-- NORMAL --\");  \n        }\n      \n      if (sChange == 0) delay(1000);\n      ssd1306_fillscreen(0x00);        \n      EEPROM.write(0,mute);\n      EEPROM.write(1,mode);\n    }\n\n    player = (analogRead(1) / 16);\n        if (player > 48) player = 48;\n    if (player <0) player = 0;\n\n\n    if(waitCount >= 3) {\n      waitCount = 0;\n      perturbation = perturbation - 2 + random(0,5);\n      if (perturbation > pFactor) perturbation = pFactor - 2;\n      if (perturbation < pFactor*-1) perturbation = (pFactor*-1)+2;\n    }\n    player2 = (bally/4 -8)+perturbation;\n\n    if (player2 > 48) player2 = 48;\n    if (player2 <0) player2 = 0;\n\n    actualy = floor(bally/4);\n    actualx = floor(ballx/8);\n    \n    // bounce off the sides of the screen\n    if ((actualy+vdir<63&&vdir>01) || (actualy- vdir>6&&vdir<0)){\n      bally+=vdir;\n    }else {\n        vdir = vdir*-1;\n    }\n    ballx+=hdir;\n\n    actualy = floor(bally/4);\n    actualx = floor(ballx/8);\n    \n    // check it hits the left pad and deal with bounces and misses\n    if (actualx <= 4) {\n      if(actualy<player-1||actualy>player+platformWidth+1){ \n        score2++;\n    \n        ballx = 5*8;\n        bally = player*4;\n\n        hdir = 13;\n        if (vdir > 0) {\n          vdir = 2;\n        } else vdir = -2;\n        \n        ssd1306_fillscreen(0x00);        \n        doNumber(46,4,score);\n        doNumber(78,4,score2);        \n        if (score2 < WINSCORE) {\n          for (int i = 0; i<1000; i = i+ 100){\n            beep(50,i);\n          }\n          for (int incr=0;incr<3;incr++) {\n              ssd1306_send_data_stop();\n              ssd1306_setpos(78,4);\n              ssd1306_send_data_start();\n              sendBlock(0);\n              sendBlock(0);\n              ssd1306_send_data_stop();\n              delay(350);\n              doNumber(78,4,score2);\n              delay(350);\n            }\n            startGame();\n        }\n        perturbation = 0;\n        break;\n      }else if (actualy<player+1){        \n        vdir = -6;\n        hdir = 7;\n      }else if (actualy<player+4){        \n        vdir = -4;\n        hdir = 10;\n      }else if (actualy<player+7){        \n        vdir = -2;\n        hdir = 13;\n      }else if (actualy<player+9){        \n        vdir = 0;\n        hdir = 14;\n      }else if (actualy<player+12){        \n        vdir = 2;\n        hdir = 13;\n      }else if (actualy<player+15){        \n        vdir = 4;\n        hdir = 10;\n      }else {   \n        vdir = 6;\n        hdir = 7;\n      }\n      beep(20,600);\n    }  \n    \n    // check it hits the right pad and deal with bounces\n    if(actualx >= 122) {\n      if(actualy<player2-1||actualy>player2+platformWidth+1){\n        score++;\n  \n        ballx = 120*8;\n        bally = player2*4;\n\n        hdir = -13;\n        if (vdir > 0) {\n          vdir = 2;\n        } else vdir = -2;\n\n        ssd1306_fillscreen(0x00);        \n        doNumber(46,4,score);\n        doNumber(78,4,score2);\n        if (score < WINSCORE) {\n        for (int i = 0; i<1000; i = i+ 100){\n            beep(50,i);\n          }                \n  \n          for (int incr=0;incr<3;incr++) {\n              ssd1306_setpos(46,4);\n              ssd1306_send_data_start();\n              sendBlock(0);\n              sendBlock(0);\n              ssd1306_send_data_stop();\n              delay(350);\n              doNumber(46,4,score);\n              delay(350);\n            }\n            perturbation = 0;\n            startGame();\n        }        \n        break;\n      }else if (actualy<player2+1){        \n        vdir = -6;\n        hdir = -7;\n      }else if (actualy<player2+4){        \n        vdir = -4;\n        hdir = -10;\n      }else if (actualy<player2+7){        \n        vdir = -2;\n        hdir = -13;\n      }else if (actualy<player2+9){        \n        vdir = 0;\n        hdir = -14;\n      }else if (actualy<player2+12){        \n        vdir = 2;\n        hdir = -13;\n      }else if (actualy<player2+15){        \n        vdir = 4;\n        hdir = -10;\n      }else {   \n        vdir = 6;\n        hdir = -7;\n      }\n      beep(20,300);\n    }      \n\n    \n    if (mode == 1 || mode == 3 || mode == 4) {\n      factor = 8-floor((score-score2)/2); // expert modes\n      if (factor < 2) factor = 2;\n    } else {\n      factor = 20-floor((score-score2)/2); // normal modes\n      if (factor < 10) factor = 10;\n    }\n    \n    delay(factor);\n    \n    // draw ball\n    blankBall(floor(lastx/8),floor(lasty/4));  \n    drawPlatform();\n    drawPlatform2();\n    drawBall(floor(ballx/8),floor(bally/4));\n    lastx = ballx;\n    lasty = bally;\n    \n    doNumber(28,0,score);\n    doNumber(92,0,score2);\n    if (score == WINSCORE || score2 == WINSCORE) {\n      stopAnimate = 1;\n      break;\n    }\n    }\n }\n\nblankBall(floor(lastx/8),floor(lasty/4));  \nblankBall(floor(ballx/8),floor(bally/4));  \n\nif (score > score2) {\n  ssd1306_char_f6x8(27, 3, \"P L A Y E R 1\"); \n} else {\n  ssd1306_char_f6x8(27, 3, \"P L A Y E R 2\"); \n}\nssd1306_char_f6x8(27, 4, \"             \");\nssd1306_char_f6x8(27, 5, \"   W I N S   \");\n\nfor (int i = 0; i<1000; i = i+ 50){\n  beep(50,i);\n}\n\n\nfor (int incr=0;incr<6;incr++) {\n    ssd1306_setpos(28,0);\n    ssd1306_send_data_start();\n    sendBlock(0);\n    sendBlock(0);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(92,0);\n    ssd1306_send_data_start();\n    sendBlock(0);\n    sendBlock(0);\n    ssd1306_send_data_stop();\n    delay(350);\n    doNumber(28,0,score);\n    doNumber(92,0,score2);\n    delay(350);\n  }\n}\n\nvoid drawPlatform() {\n  if (player != lastPlayer) {\n    ssd1306_setpos(0,lastPlayer/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(0,lastPlayer/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop(); \n    ssd1306_setpos(0,lastPlayer/8+2);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop(); \n  }  \n\n  if (player%8!=0){\n    ssd1306_setpos(0,player/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte((B11111111)<<player%8);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(0,player/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B11111111);\n    ssd1306_send_data_stop();    \n    ssd1306_setpos(0,player/8+2);\n    ssd1306_send_data_start();\n    ssd1306_send_byte((B01111110)>>8-player%8);\n    ssd1306_send_data_stop();\n  } else {\n    ssd1306_setpos(0,player/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B11111111);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(0,player/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B11111111);\n    ssd1306_send_data_stop();\n\n  }\n  lastPlayer = player;\n}\n\nvoid drawPlatform2() {\n\n  if (player2 != lastPlayer2) {\n    ssd1306_setpos(127,lastPlayer2/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(127,lastPlayer2/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop(); \n    ssd1306_setpos(127,lastPlayer2/8+2);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop(); \n  }\n  \n  if (player2%8!=0){\n    ssd1306_setpos(127,player2/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte((B11111111)<<player2%8);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(127,player2/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B11111111);\n    ssd1306_send_data_stop();        \n    ssd1306_setpos(127,player2/8+2);\n    ssd1306_send_data_start();\n    ssd1306_send_byte((B01111110)>>8-player2%8);\n    ssd1306_send_data_stop();\n  } else {\n    ssd1306_setpos(127,player2/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte((B11111111)<<0);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(127,player2/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte((B11111111)<<0);\n    ssd1306_send_data_stop();\n  }\n  lastPlayer2 = player2;\n}\n\n\n\nvoid sendBlock(int fill){\n  if (fill == 1) {\n   ssd1306_send_byte(B10011000);\n   ssd1306_send_byte(B01011100);\n   ssd1306_send_byte(B10110110);\n   ssd1306_send_byte(B01011111);\n   ssd1306_send_byte(B01011111);\n   ssd1306_send_byte(B10110110);\n   ssd1306_send_byte(B01011100);\n   ssd1306_send_byte(B10011000);\n  } else  {\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n  } \n}\n\nvoid blankBall(int x, int y) {\n  if (y%8!=0){\n    ssd1306_setpos(x,y/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop();\n    \n    ssd1306_setpos(x,y/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop();\n  } else {\n    ssd1306_setpos(x,y/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop();\n  }\n}\n\n\nvoid drawBall(int x, int y) {\n  if (y%8!=0){\n    ssd1306_setpos(x,y/8);\n    ssd1306_send_data_start();\n    doDrawLS(0,y%8);\n    ssd1306_send_data_stop();\n    \n    ssd1306_setpos(x,y/8+1);\n    ssd1306_send_data_start();\n    doDrawRS(0,8-y%8);\n    ssd1306_send_data_stop();\n  } else {\n    ssd1306_setpos(x,y/8);\n    ssd1306_send_data_start();\n    doDrawLS(0,0);\n    ssd1306_send_data_stop();\n  }\n}\n\n// Drawing routine for the player and fire - with right-shifts\nvoid doDrawRS(long P1, byte P2) {\n  ssd1306_send_byte((B00000011 | P1)>>P2);\n  ssd1306_send_byte((B00000011 | P1)>>P2);\n}\n\n// Drawing routine for the player and fire - with left-shifts\nvoid doDrawLS(long P1, byte P2) {\n  ssd1306_send_byte((B00000011 | P1)<<P2);\n  ssd1306_send_byte((B00000011 | P1)<<P2);\n}\n\nvoid startGame(void) {\n  \n    ssd1306_fillscreen(0x00);\n\n    ssd1306_char_f6x8(16, 3, \"-- GET READY --\");\n    doNumber(60,5,3);\n    delay(1000);\n    doNumber(60,5,2);\n    delay(1000);\n    doNumber(60,5,1);\n    delay(1000);\n    ssd1306_fillscreen(0x00);\n\n    for (int i = 800; i>200; i = i - 200){\n    beep(30,i);\n    }\n\n}\n\r\n"
  },
  {
    "path": "BatBonanzaAnalogSinglePot/font6x8AJ.h",
    "content": "/*\n * SSD1306xLED - Drivers for SSD1306 controlled dot matrix OLED/PLED 128x64 displays\n *\n * @file: font6x8.h\n * @created: 2014-08-12\n * @author: Neven Boyanov\n * \n * Hacked by andy jackson to allow two games (originally by webboggles.com) to \n * fit onto an ATTiny85 at the same time - hence several characters are missing\n * and a couple have been moved to limit the amount of software remapping required\n * to map ASCII values onto locations in this array.\n *\n * Source code available at: https://bitbucket.org/tinusaur/ssd1306xled\n *\n */\n\n// ----------------------------------------------------------------------------\n\n#include <avr/pgmspace.h>\n\n// ----------------------------------------------------------------------------\n\n/* Standard ASCII 6x8 font */\nstatic const uint8_t ssd1306xled_font6x8 [] PROGMEM = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sp\n/*\n  0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // !\n  0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // \"\n  0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // #\n  0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $\n  0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // %\n  0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // &\n  0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // '\n  0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // (\n  0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // )\n  0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // *\n  0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // +\n  0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // ,\n  */\n  0x00, 0x08, 0x08, 0x08, 0x08, 0x08, // -\n  0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // .\n  0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w in place of /\n  //0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // /\n  0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0\n  0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, // 1\n  0x00, 0x42, 0x61, 0x51, 0x49, 0x46, // 2\n  0x00, 0x21, 0x41, 0x45, 0x4B, 0x31, // 3\n  0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, // 4\n  0x00, 0x27, 0x45, 0x45, 0x45, 0x39, // 5\n  0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6\n  0x00, 0x01, 0x71, 0x09, 0x05, 0x03, // 7\n  0x00, 0x36, 0x49, 0x49, 0x49, 0x36, // 8\n  0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, // 9\n  0x00, 0x00, 0x36, 0x36, 0x00, 0x00, // :\n/*\n  0x00, 0x00, 0x56, 0x36, 0x00, 0x00, // ;\n  0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // <\n  0x00, 0x14, 0x14, 0x14, 0x14, 0x14, // =\n  0x00, 0x00, 0x41, 0x22, 0x14, 0x08, // >\n  0x00, 0x02, 0x01, 0x51, 0x09, 0x06, // ?\n  0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, // @\n */\n  0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, // B\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, // C\n  0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, // D\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, // E\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, // F\n  0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, // G\n  0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, // H\n  0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, // I\n  0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, // J\n  0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, // K\n  0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, // L\n  0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M\n  0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, // N\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, // O\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, // P\n  0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q\n  0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, // R\n  0x00, 0x46, 0x49, 0x49, 0x49, 0x31, // S\n  0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, // T\n  0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, // U\n  0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, // V\n  0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, // W\n  0x00, 0x63, 0x14, 0x08, 0x14, 0x63, // X\n  0x00, 0x07, 0x08, 0x70, 0x08, 0x07, // Y\n  0x00, 0x61, 0x51, 0x49, 0x45, 0x43, // Z\n  /*\n  0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, // [\n  0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55, // 55\n  0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, // ]\n  0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^\n  0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _\n  0x00, 0x00, 0x01, 0x02, 0x04, 0x00, // '\n*/\n  0x00, 0x20, 0x54, 0x54, 0x54, 0x78, // a\n  0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, // b\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x20, // c\n  0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, // d\n  0x00, 0x38, 0x54, 0x54, 0x54, 0x18, // e\n  0x00, 0x08, 0x7E, 0x09, 0x01, 0x02, // f\n  0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g\n  0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C, // y (in place of h)\n  //0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h\n  0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, // i\n  0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, // j\n  0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, // k\n  0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, // l\n  0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, // m\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, // n\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x38, // o\n  0x00, 0xFC, 0x24, 0x24, 0x24, 0x18, // p\n  0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, // q\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, // r\n  0x00, 0x48, 0x54, 0x54, 0x54, 0x20, // s\n  0x00, 0x04, 0x3F, 0x44, 0x40, 0x20, // t\n  0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, // u\n  0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, // v\n // 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w\n // 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, // x\n // 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C // y\n};\n\n// ----------------------------------------------------------------------------\n\r\n"
  },
  {
    "path": "BatBonanzaAttinyArcade/BatBonanzaAttinyArcade.ino",
    "content": "/* 2015 / 2016 /2017\n * Pong game by Andy Jackson - Twitter @andyhighnumber\n * Inspired by http://webboggles.com/ and includes some code from the #AttinyArcade games on that site\n * The code that does not fall under the licenses of sources listed below can be used non commercially with attribution.\n * \n * When the game is running :\n * LEFT BUTTON - Controls the player's bat\n * RIGHT BUTTON - Press and relese to change mode (difficulty) - Press and hold to toggle sound\n *  \n * Also, from standby....\n *  Press and hold left button to reset the system\n * \n * If you have problems uploading this sketch, this is probably due to sketch size - you need to update ld.exe in arduino\\hardware\\tools\\avr\\avr\\bin\n * https://github.com/TCWORLD/ATTinyCore/tree/master/PCREL%20Patch%20for%20GCC\n *\n * This sketch is using the screen control and font functions written by Neven Boyanov for the http://tinusaur.wordpress.com/ project\n * Source code and font files available at: https://bitbucket.org/tinusaur/ssd1306xled\n * **Note that this highly size-optimised version requires modified library functions (which are in this source code file) \n * and a modified font header\n * \n * Sleep code is based on this blog post by Matthew Little:\n * http://www.re-innovation.co.uk/web12/index.php/en/blog-75/306-sleep-modes-on-attiny85\n*/\n#include <EEPROM.h>\n#include \"font6x8AJ.h\"\n#include <avr/sleep.h>\n#include <avr/interrupt.h> // needed for the additional interrupt\n\n#define DIGITAL_WRITE_HIGH(PORT) PORTB |= (1 << PORT)\n#define DIGITAL_WRITE_LOW(PORT) PORTB &= ~(1 << PORT)\n\n// Routines to set and clear bits (used in the sleep code)\n#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))\n#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))\n\n// Defines for OLED output\n#define SSD1306XLED_H\n#define SSD1306_SCL   PORTB4  // SCL, Pin 4 on SSD1306 Board - for webbogles board\n#define SSD1306_SDA   PORTB3  // SDA, Pin 3 on SSD1306 Board - for webbogles board\n#define SSD1306_SA    0x78  // Slave address\n\n#define WINSCORE 7\n\n// Function prototypes\nvoid startGame(void);\nvoid drawPlatform(void);\nvoid drawPlatform2(void);\nvoid sendBlock(int);\nvoid playPong(void);\nvoid beep(int,int);\nvoid drawBall(int x, int y);\nvoid blankBall(int x, int y);\n\nvoid doDrawLS(long, byte);\nvoid doDrawRS(long, byte);\nvoid doNumber (int x, int y, int value);\n\nvoid ssd1306_init(void);\nvoid ssd1306_xfer_start(void);\nvoid ssd1306_xfer_stop(void);\nvoid ssd1306_send_byte(uint8_t byte);\nvoid ssd1306_send_command(uint8_t command);\nvoid ssd1306_send_data_start(void);\nvoid ssd1306_send_data_stop(void);\nvoid ssd1306_setpos(uint8_t x, uint8_t y);\nvoid ssd1306_fillscreen(uint8_t fill_Data);\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]);\nvoid ssd1306_draw_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t bitmap[]);\n\nint player; //0 to 128-platformWidth  - this is the position of the player\nint player2; //0 to 128-platformWidth  - this is the position of the player\nint lastPlayer;\nint lastPlayer2;\nint platformWidth = 16; \nboolean stopAnimate = 0; // this is set to 1 when a collision is detected\nboolean mute = 0;\nboolean newHigh = 0;\nint score = 0; // score - this affects the difficulty of the game\nint score2 = 0; // score - this affects the difficulty of the game\n\nint ballx = 62*8; // coordinate of the ball\nint bally = 50*4; // coordinate of the ball\nint vdir = -4; // vertical direction and step  distance\nint hdir = -8; // horizontal direction and step distance\n\nint mode = 0;\n\nint perturbation = 0;\nint pFactor = 12;\n\n// Interrupt handlers\nISR(PCINT0_vect){ // PB0 pin button interrupt           \n}\n\nvoid playerIncPong(){ // PB2 pin button interrupt\n}\n\n// Arduino stuff - setup\nvoid setup() {\n  DDRB = 0b00000010;    // set PB1 as output (for the speaker)\n  PCMSK = 0b00000001; // pin change mask: listen to portb bit 1\n  GIMSK |= 0b00100000;  // enable PCINT interrupt \n  sei();          // enable all interrupts\n}\n\n// Arduino stuff - loop\nvoid loop() { \n  ssd1306_init();\n  ssd1306_fillscreen(0x00);\n  \n  // The lower case character set is seriously compromised because I've had to truncate the ASCII table\n  // to release space for executable code - hence lower case y and w are remapped to h and / respectively.\n  // There is no z in the table (or h!) as these aren't used anywhere in the text here and most of the \n  // symbols are also missing for the same reason (see my hacked version of font6x8.h - font6x8AJ.h for more detail)\n  ssd1306_char_f6x8(0, 1, \"   ---------------  \");\n  ssd1306_char_f6x8(0, 2, \"        B A T       \");\n  ssd1306_char_f6x8(0, 4, \"    B O N A N Z A   \");\n  ssd1306_char_f6x8(0, 5, \"   ---------------  \");\n  ssd1306_char_f6x8(0, 7, \"   bh andh jackson  \"); // see comments above !\n\n   long startT = millis();\n    long nowT =0;\n    boolean sChange = 0;\n    while(digitalRead(0) == HIGH) {\n      nowT = millis();\n      if (nowT - startT > 2000) {\n        sChange = 1;     \n        EEPROM.write(0,0);\n        EEPROM.write(1,1);\n        ssd1306_char_f6x8(16, 0, \"- SYSTEM RESET -\");  \n        break;\n      }\n      if (sChange == 1) break;\n    }  \n    while(digitalRead(0) == HIGH);\n\n    mute=EEPROM.read(0);\n    mode=EEPROM.read(1);\n\n    if (mute != 0 && mute != 1) {\n      mute = 0;\n       EEPROM.write(0,0);\n    }\n\n    if (mode != 1 && mode != 3 && mode != 4) {\n      mode = 1;\n      EEPROM.write(1,1);\n    }\n\n    \n    if (sChange != 1) {\n    delay(1500);\n    ssd1306_init();\n    ssd1306_fillscreen(0x00);\n    stopAnimate = 0;\n    score = 0;\n    score2 = 0;\n\n    playPong(); \n    \n    delay(3500);\n \n  }\n  system_sleep();\n}\n\nvoid doNumber (int x, int y, int value) {\n    char temp[10] = {0,0,0,0,0,0,0,0,0,0};\n    itoa(value,temp,10);\n    ssd1306_char_f6x8(x, y, temp);\n}\n\nvoid ssd1306_init(void){\n  DDRB |= (1 << SSD1306_SDA); // Set port as output\n  DDRB |= (1 << SSD1306_SCL); // Set port as output\n\n  ssd1306_send_command(0xAE); // display off\n  ssd1306_send_command(0x00); // Set Memory Addressing Mode\n  ssd1306_send_command(0x10); // 00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid\n  ssd1306_send_command(0x40); // Set Page Start Address for Page Addressing Mode,0-7\n  ssd1306_send_command(0x81); // Set COM Output Scan Direction\n  ssd1306_send_command(0xCF); // ---set low column address\n  ssd1306_send_command(0xA1); // ---set high column address\n  ssd1306_send_command(0xC8); // --set start line address\n  ssd1306_send_command(0xA6); // --set contrast control register\n  ssd1306_send_command(0xA8);\n  ssd1306_send_command(0x3F); // --set segment re-map 0 to 127\n  ssd1306_send_command(0xD3); // --set normal display\n  ssd1306_send_command(0x00); // --set multiplex ratio(1 to 64)\n  ssd1306_send_command(0xD5); // \n  ssd1306_send_command(0x80); // 0xa4,Output follows RAM content;0xa5,Output ignores RAM content\n  ssd1306_send_command(0xD9); // -set display offset\n  ssd1306_send_command(0xF1); // -not offset\n  ssd1306_send_command(0xDA); // --set display clock divide ratio/oscillator frequency\n  ssd1306_send_command(0x12); // --set divide ratio\n  ssd1306_send_command(0xDB); // --set pre-charge period\n  ssd1306_send_command(0x40); // \n  ssd1306_send_command(0x20); // --set com pins hardware configuration\n  ssd1306_send_command(0x02);\n  ssd1306_send_command(0x8D); // --set vcomh\n  ssd1306_send_command(0x14); // 0x20,0.77xVcc\n  ssd1306_send_command(0xA4); // --set DC-DC enable\n  ssd1306_send_command(0xA6); // \n  ssd1306_send_command(0xAF); // --turn on oled panel \n}\n\nvoid ssd1306_xfer_start(void){\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n}\n\nvoid ssd1306_xfer_stop(void){\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n}\n\nvoid ssd1306_send_byte(uint8_t byte){\n  uint8_t i;\n  for(i=0; i<8; i++)\n  {\n    if((byte << i) & 0x80)\n      DIGITAL_WRITE_HIGH(SSD1306_SDA);\n    else\n      DIGITAL_WRITE_LOW(SSD1306_SDA);\n    \n    DIGITAL_WRITE_HIGH(SSD1306_SCL);\n    DIGITAL_WRITE_LOW(SSD1306_SCL);\n  }\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);\n  DIGITAL_WRITE_LOW(SSD1306_SCL);\n}\n\nvoid ssd1306_send_command(uint8_t command){\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  // Slave address, SA0=0\n  ssd1306_send_byte(0x00);  // write command\n  ssd1306_send_byte(command);\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_send_data_start(void){\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);\n  ssd1306_send_byte(0x40);  //write data\n}\n\nvoid ssd1306_send_data_stop(void){\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_setpos(uint8_t x, uint8_t y)\n{\n  if (y>7) return;\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  //Slave address,SA0=0\n  ssd1306_send_byte(0x00);  //write command\n\n  ssd1306_send_byte(0xb0+y);\n  ssd1306_send_byte(((x&0xf0)>>4)|0x10); // |0x10\n  ssd1306_send_byte((x&0x0f)|0x01); // |0x01\n\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_fillscreen(uint8_t fill_Data){\n  uint8_t m,n;\n  for(m=0;m<8;m++)\n  {\n    ssd1306_send_command(0xb0+m); //page0-page1\n    ssd1306_send_command(0x00);   //low column start address\n    ssd1306_send_command(0x10);   //high column start address\n    ssd1306_send_data_start();\n    for(n=0;n<128;n++)\n    {\n      ssd1306_send_byte(fill_Data);\n    }\n    ssd1306_send_data_stop();\n  }\n}\n\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]){\n  uint8_t c,i,j=0;\n  while(ch[j] != '\\0')\n  {\n    c = ch[j] - 32;\n    if (c >0) c = c - 12;\n    if (c >15) c = c - 6;\n    if (c>40) c=c-6;\n    if(x>126)\n    {\n      x=0;\n      y++;\n    }\n    ssd1306_setpos(x,y);\n    ssd1306_send_data_start();\n    for(i=0;i<6;i++)\n    {\n      ssd1306_send_byte(pgm_read_byte(&ssd1306xled_font6x8[c*6+i]));\n    }\n    ssd1306_send_data_stop();\n    x += 6;\n    j++;\n  }\n}\n\nvoid system_sleep() {\n  ssd1306_fillscreen(0x00);\n  ssd1306_send_command(0xAE);\n  cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF\n  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here\n  sleep_enable();\n  sleep_mode();                        // System actually sleeps here\n  sleep_disable();                     // System continues execution here when watchdog timed out \n  sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON  \n  ssd1306_send_command(0xAF);\n}\n\nvoid beep(int bCount,int bDelay){\n  if (mute) return;\n  for (int i = 0; i<=bCount; i++){digitalWrite(1,HIGH);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}digitalWrite(1,LOW);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}}\n}\n\n\n\n/* ------------------------\n *  Pong Code\n */\nvoid playPong() {\n  ballx = 64*8;\n  bally = 32*4;\n  hdir = -8;\n  vdir = -4;\n  int actualy, actualx;\n  int factor = 0;\n  int waitCount = 0;\n\n  int lastx=64*8, lasty=32*4;\n\n  player=64;\n  player2=64;\n  lastPlayer = 64;\n  lastPlayer2 = 64;\n  score = 0; // obvious\n  score2 = 0; // obvious\n  perturbation = 0;\n    \n  startGame();\n  while (stopAnimate == 0) {\n    while(1) {\n    waitCount++;\n    \n    if(digitalRead(2)==1) {\n      boolean sChange = 0;\n      long startT = millis();\n      long nowT =0;\n      while(digitalRead(2) == HIGH) {\n        nowT = millis();\n        if (nowT - startT > 1500) {\n          sChange = 1;\n          if (mute == 0) { mute = 1; ssd1306_char_f6x8(32, 0, \"-- MUTE --\"); } else { mute = 0; ssd1306_char_f6x8(23, 0, \"-- SOUND ON --\"); }\n          break;\n        }\n      }\n      while(digitalRead(2) == HIGH);\n      if (sChange == 1) {\n          } else if (mode == 1) { \n            mode = 3; \n            pFactor = 11;\n            ssd1306_char_f6x8(20, 0, \"- TOUGH MODE -\");  \n          } else if (mode == 3) { \n            mode = 4; \n            pFactor = 10;\n            ssd1306_char_f6x8(16, 0, \"- EXPERT MODE -\");  \n          } else if (mode == 4) { \n            mode = 1; \n            pFactor = 12;\n            ssd1306_char_f6x8(32, 0, \"-- NORMAL --\"); \n          }\n      \n      if (sChange == 0) delay(1000);\n      ssd1306_fillscreen(0x00);        \n      EEPROM.write(0,mute);\n      EEPROM.write(1,mode);\n    }\n\n    if (digitalRead(0) == 1) {\n      player-= 3;\n    }\n    player+=1;\n    if (player > 48) player = 48;\n    if (player <0) player = 0;\n    \n    if (mode == 1 || mode == 3 || mode == 4) {\n      if(waitCount >= 3) {\n        waitCount = 0;\n        perturbation = perturbation - 2 + random(0,5);\n        if (perturbation > pFactor) perturbation = pFactor - 2;\n        if (perturbation < pFactor*-1) perturbation = (pFactor*-1)+2;\n      }\n      player2 = (bally/4 -8)+perturbation;\n    }\n    if (player2 > 48) player2 = 48;\n    if (player2 <0) player2 = 0;\n\n    actualy = floor(bally/4);\n    actualx = floor(ballx/8);\n    \n    // bounce off the sides of the screen\n    if ((actualy+vdir<63&&vdir>01) || (actualy- vdir>6&&vdir<0)){\n      bally+=vdir;\n    }else {\n        vdir = vdir*-1;\n    }\n    ballx+=hdir;\n\n    actualy = floor(bally/4);\n    actualx = floor(ballx/8);\n    \n    // check it hits the left pad and deal with bounces and misses\n    if (actualx <= 4) {\n      if(actualy<player-1||actualy>player+platformWidth+1){ \n        score2++;\n    \n        ballx = 5*8;\n        bally = player*4;\n\n        hdir = 13;\n        if (vdir > 0) {\n          vdir = 2;\n        } else vdir = -2;\n        \n        ssd1306_fillscreen(0x00);        \n        doNumber(46,4,score);\n        doNumber(78,4,score2);        \n        if (score2 < WINSCORE) {\n          for (int i = 0; i<1000; i = i+ 100){\n            beep(50,i);\n          }\n          for (int incr=0;incr<3;incr++) {\n              ssd1306_send_data_stop();\n              ssd1306_setpos(78,4);\n              ssd1306_send_data_start();\n              sendBlock(0);\n              sendBlock(0);\n              ssd1306_send_data_stop();\n              delay(350);\n              doNumber(78,4,score2);\n              delay(350);\n            }\n            startGame();\n        }\n        perturbation = 0;\n        break;\n      }else if (actualy<player+1){        \n        vdir = -6;\n        hdir = 7;\n      }else if (actualy<player+4){        \n        vdir = -4;\n        hdir = 10;\n      }else if (actualy<player+7){        \n        vdir = -2;\n        hdir = 13;\n      }else if (actualy<player+9){        \n        vdir = 0;\n        hdir = 14;\n      }else if (actualy<player+12){        \n        vdir = 2;\n        hdir = 13;\n      }else if (actualy<player+15){        \n        vdir = 4;\n        hdir = 10;\n      }else {   \n        vdir = 6;\n        hdir = 7;\n      }\n      beep(20,600);\n    }  \n    \n    // check it hits the right pad and deal with bounces\n    if(actualx >= 122) {\n      if(actualy<player2-1||actualy>player2+platformWidth+1){\n        score++;\n  \n        ballx = 120*8;\n        bally = player2*4;\n\n        hdir = -13;\n        if (vdir > 0) {\n          vdir = 2;\n        } else vdir = -2;\n\n        ssd1306_fillscreen(0x00);        \n        doNumber(46,4,score);\n        doNumber(78,4,score2);\n        if (score < WINSCORE) {\n        for (int i = 0; i<1000; i = i+ 100){\n            beep(50,i);\n          }                \n  \n          for (int incr=0;incr<3;incr++) {\n              ssd1306_setpos(46,4);\n              ssd1306_send_data_start();\n              sendBlock(0);\n              sendBlock(0);\n              ssd1306_send_data_stop();\n              delay(350);\n              doNumber(46,4,score);\n              delay(350);\n            }\n            perturbation = 0;\n            startGame();\n        }        \n        break;\n      }else if (actualy<player2+1){        \n        vdir = -6;\n        hdir = -7;\n      }else if (actualy<player2+4){        \n        vdir = -4;\n        hdir = -10;\n      }else if (actualy<player2+7){        \n        vdir = -2;\n        hdir = -13;\n      }else if (actualy<player2+9){        \n        vdir = 0;\n        hdir = -14;\n      }else if (actualy<player2+12){        \n        vdir = 2;\n        hdir = -13;\n      }else if (actualy<player2+15){        \n        vdir = 4;\n        hdir = -10;\n      }else {   \n        vdir = 6;\n        hdir = -7;\n      }\n      beep(20,300);\n    }      \n\n    \n    if (mode == 2 || mode == 3 || mode == 4) {\n      factor = 8-floor((score-score2)/2); // expert modes\n      if (factor < 2) factor = 2;\n    } else {\n      factor = 20-floor((score-score2)/2); // normal modes\n      if (factor < 10) factor = 10;\n    }\n    \n    delay(factor);\n    \n    // draw ball\n    blankBall(floor(lastx/8),floor(lasty/4));  \n    drawPlatform();\n    drawPlatform2();\n    drawBall(floor(ballx/8),floor(bally/4));\n    lastx = ballx;\n    lasty = bally;\n    \n    doNumber(28,0,score);\n    doNumber(92,0,score2);\n    if (score == WINSCORE || score2 == WINSCORE) {\n      stopAnimate = 1;\n      break;\n    }\n    }\n }\n\nblankBall(floor(lastx/8),floor(lasty/4));  \nblankBall(floor(ballx/8),floor(bally/4));  \n\nif (score > score2) {\n  ssd1306_char_f6x8(27, 3, \"P L A Y E R 1\"); \n} else {\n  ssd1306_char_f6x8(27, 3, \"P L A Y E R 2\"); \n}\nssd1306_char_f6x8(27, 4, \"             \");\nssd1306_char_f6x8(27, 5, \"   W I N S   \");\n\nfor (int i = 0; i<1000; i = i+ 50){\n  beep(50,i);\n}\n\n\nfor (int incr=0;incr<6;incr++) {\n    ssd1306_setpos(28,0);\n    ssd1306_send_data_start();\n    sendBlock(0);\n    sendBlock(0);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(92,0);\n    ssd1306_send_data_start();\n    sendBlock(0);\n    sendBlock(0);\n    ssd1306_send_data_stop();\n    delay(350);\n    doNumber(28,0,score);\n    doNumber(92,0,score2);\n    delay(350);\n  }\n}\n\nvoid drawPlatform() {\n  if (player != lastPlayer) {\n    ssd1306_setpos(0,lastPlayer/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(0,lastPlayer/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop(); \n    ssd1306_setpos(0,lastPlayer/8+2);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop(); \n  }  \n\n  if (player%8!=0){\n    ssd1306_setpos(0,player/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte((B11111111)<<player%8);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(0,player/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B11111111);\n    ssd1306_send_data_stop();    \n    ssd1306_setpos(0,player/8+2);\n    ssd1306_send_data_start();\n    ssd1306_send_byte((B01111110)>>8-player%8);\n    ssd1306_send_data_stop();\n  } else {\n    ssd1306_setpos(0,player/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B11111111);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(0,player/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B11111111);\n    ssd1306_send_data_stop();\n\n  }\n  lastPlayer = player;\n}\n\nvoid drawPlatform2() {\n\n  if (player2 != lastPlayer2) {\n    ssd1306_setpos(127,lastPlayer2/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(127,lastPlayer2/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop(); \n    ssd1306_setpos(127,lastPlayer2/8+2);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop(); \n  }\n  \n  if (player2%8!=0){\n    ssd1306_setpos(127,player2/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte((B11111111)<<player2%8);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(127,player2/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B11111111);\n    ssd1306_send_data_stop();        \n    ssd1306_setpos(127,player2/8+2);\n    ssd1306_send_data_start();\n    ssd1306_send_byte((B01111110)>>8-player2%8);\n    ssd1306_send_data_stop();\n  } else {\n    ssd1306_setpos(127,player2/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte((B11111111)<<0);\n    ssd1306_send_data_stop();\n    ssd1306_setpos(127,player2/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte((B11111111)<<0);\n    ssd1306_send_data_stop();\n  }\n  lastPlayer2 = player2;\n}\n\nvoid sendBlock(int fill){\n ssd1306_send_byte(B00000000);\n ssd1306_send_byte(B00000000);\n ssd1306_send_byte(B00000000);\n ssd1306_send_byte(B00000000);\n ssd1306_send_byte(B00000000);\n ssd1306_send_byte(B00000000);\n ssd1306_send_byte(B00000000);\n ssd1306_send_byte(B00000000);\n}\n\nvoid blankBall(int x, int y) {\n  if (y%8!=0){\n    ssd1306_setpos(x,y/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop();\n    \n    ssd1306_setpos(x,y/8+1);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop();\n  } else {\n    ssd1306_setpos(x,y/8);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_byte(B00000000);\n    ssd1306_send_data_stop();\n  }\n}\n\n\nvoid drawBall(int x, int y) {\n  if (y%8!=0){\n    ssd1306_setpos(x,y/8);\n    ssd1306_send_data_start();\n    doDrawLS(0,y%8);\n    ssd1306_send_data_stop();\n    \n    ssd1306_setpos(x,y/8+1);\n    ssd1306_send_data_start();\n    doDrawRS(0,8-y%8);\n    ssd1306_send_data_stop();\n  } else {\n    ssd1306_setpos(x,y/8);\n    ssd1306_send_data_start();\n    doDrawLS(0,0);\n    ssd1306_send_data_stop();\n  }\n}\n\nvoid doDrawRS(long P1, byte P2) {\n  ssd1306_send_byte((B00000011 | P1)>>P2);\n  ssd1306_send_byte((B00000011 | P1)>>P2);\n}\nvoid doDrawLS(long P1, byte P2) {\n  ssd1306_send_byte((B00000011 | P1)<<P2);\n  ssd1306_send_byte((B00000011 | P1)<<P2);\n}\n\nvoid startGame(void) {\n  \n    ssd1306_fillscreen(0x00);\n\n    ssd1306_char_f6x8(16, 3, \"-- GET READY --\");\n    doNumber(60,5,3);\n    delay(1000);\n    doNumber(60,5,2);\n    delay(1000);\n    doNumber(60,5,1);\n    delay(1000);\n    ssd1306_fillscreen(0x00);\n\n    for (int i = 800; i>200; i = i - 200){\n    beep(30,i);\n    }\n\n}\n\r\n"
  },
  {
    "path": "BatBonanzaAttinyArcade/font6x8AJ.h",
    "content": "/*\n * SSD1306xLED - Drivers for SSD1306 controlled dot matrix OLED/PLED 128x64 displays\n *\n * @file: font6x8.h\n * @created: 2014-08-12\n * @author: Neven Boyanov\n * \n * Hacked by andy jackson to allow two games (originally by webboggles.com) to \n * fit onto an ATTiny85 at the same time - hence several characters are missing\n * and a couple have been moved to limit the amount of software remapping required\n * to map ASCII values onto locations in this array.\n *\n * Source code available at: https://bitbucket.org/tinusaur/ssd1306xled\n *\n */\n\n// ----------------------------------------------------------------------------\n\n#include <avr/pgmspace.h>\n\n// ----------------------------------------------------------------------------\n\n/* Standard ASCII 6x8 font */\nstatic const uint8_t ssd1306xled_font6x8 [] PROGMEM = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sp\n/*\n  0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // !\n  0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // \"\n  0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // #\n  0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $\n  0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // %\n  0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // &\n  0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // '\n  0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // (\n  0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // )\n  0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // *\n  0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // +\n  0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // ,\n  */\n  0x00, 0x08, 0x08, 0x08, 0x08, 0x08, // -\n  0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // .\n  0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w in place of /\n  //0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // /\n  0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0\n  0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, // 1\n  0x00, 0x42, 0x61, 0x51, 0x49, 0x46, // 2\n  0x00, 0x21, 0x41, 0x45, 0x4B, 0x31, // 3\n  0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, // 4\n  0x00, 0x27, 0x45, 0x45, 0x45, 0x39, // 5\n  0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6\n  0x00, 0x01, 0x71, 0x09, 0x05, 0x03, // 7\n  0x00, 0x36, 0x49, 0x49, 0x49, 0x36, // 8\n  0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, // 9\n  0x00, 0x00, 0x36, 0x36, 0x00, 0x00, // :\n/*\n  0x00, 0x00, 0x56, 0x36, 0x00, 0x00, // ;\n  0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // <\n  0x00, 0x14, 0x14, 0x14, 0x14, 0x14, // =\n  0x00, 0x00, 0x41, 0x22, 0x14, 0x08, // >\n  0x00, 0x02, 0x01, 0x51, 0x09, 0x06, // ?\n  0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, // @\n */\n  0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, // B\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, // C\n  0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, // D\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, // E\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, // F\n  0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, // G\n  0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, // H\n  0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, // I\n  0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, // J\n  0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, // K\n  0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, // L\n  0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M\n  0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, // N\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, // O\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, // P\n  0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q\n  0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, // R\n  0x00, 0x46, 0x49, 0x49, 0x49, 0x31, // S\n  0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, // T\n  0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, // U\n  0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, // V\n  0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, // W\n  0x00, 0x63, 0x14, 0x08, 0x14, 0x63, // X\n  0x00, 0x07, 0x08, 0x70, 0x08, 0x07, // Y\n  0x00, 0x61, 0x51, 0x49, 0x45, 0x43, // Z\n  /*\n  0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, // [\n  0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55, // 55\n  0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, // ]\n  0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^\n  0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _\n  0x00, 0x00, 0x01, 0x02, 0x04, 0x00, // '\n*/\n  0x00, 0x20, 0x54, 0x54, 0x54, 0x78, // a\n  0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, // b\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x20, // c\n  0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, // d\n  0x00, 0x38, 0x54, 0x54, 0x54, 0x18, // e\n  0x00, 0x08, 0x7E, 0x09, 0x01, 0x02, // f\n  0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g\n  0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C, // y (in place of h)\n  //0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h\n  0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, // i\n  0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, // j\n  0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, // k\n  0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, // l\n  0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, // m\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, // n\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x38, // o\n  0x00, 0xFC, 0x24, 0x24, 0x24, 0x18, // p\n  0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, // q\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, // r\n  0x00, 0x48, 0x54, 0x54, 0x54, 0x20, // s\n  0x00, 0x04, 0x3F, 0x44, 0x40, 0x20, // t\n  0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, // u\n  0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, // v\n // 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w\n // 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, // x\n // 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C // y\n};\n\n// ----------------------------------------------------------------------------\n\r\n"
  },
  {
    "path": "Frogger_Attiny_Arcade/Frogger_Attiny_Arcade.ino",
    "content": "/*  2015 / 2016 / 2017\n *  Frogger game by Andy Jackson - Twitter @andyhighnumber\n *  \n *  Special thanks to @senkunmusahi, who created the artwork bitmaps in the game using https://www.riyas.org/2013/12/online-led-matrix-font-generator-with.html\n *  \n *  Inspired by http://webboggles.com/ and includes some code from the #AttinyArcade games on that site\n *  The code that does not fall under the licenses of sources listed below can be used non commercially with attribution.\n *  This software is supplied without warranty of any kind.\n *  \n *  Controls:\n *  On the standard AttinyArcade:\n *  LEFT and RIGHT buttons move the frog across \n *  BOTH BOTTONS TOGETHER move the frog forwards\n *  \n *  HIGHLY RECOMMENDED:\n *  On custom hardware (see schematic in folder where you found this file) there is an additional button to move frog forward  \n *  \n *  Also, from standby....\n *  Press and hold left button to turn sound on and off\n *  Press and hold left button with the right button held to reset high score\n * \n *  This sketch is using the screen control and font functions written by Neven Boyanov for the http://tinusaur.wordpress.com/ project\n *  Source code and font files available at: https://bitbucket.org/tinusaur/ssd1306xled\n *  **Note that this highly size-optimised version requires modified library functions (which are in this source code file) \n *  and a modified font header\n * \n *  Sleep code is based on this blog post by Matthew Little:\n *  http://www.re-innovation.co.uk/web12/index.php/en/blog-75/306-sleep-modes-on-attiny85\n*/\n#include <EEPROM.h>\n#include \"font6x8AJ2.h\"\n#include <avr/pgmspace.h>\n#include <avr/sleep.h>\n#include <avr/interrupt.h> // needed for the additional interrupt\n\n// Uncomment this #define to make the logs smaller (/thinner)\n//#define SMALLLOGS\n\n// Make click delay an even number - it gets halved and then used in an integer comparison\n#define CLICKDELAY 120 \n\n// The basline speed - higher number is slower\n#define MOVEBASE 1000 \n\n#define DIGITAL_WRITE_HIGH(PORT) PORTB |= (1 << PORT)\n#define DIGITAL_WRITE_LOW(PORT) PORTB &= ~(1 << PORT)\n\n// Routines to set and clear bits (used in the sleep code)\n#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))\n#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))\n\n// Defines for OLED output\n#define SSD1306XLED_H\n#define SSD1306_SCL   PORTB4  // SCL, Pin 4 on SSD1306 Board - for webbogles board\n#define SSD1306_SDA   PORTB3  // SDA, Pin 3 on SSD1306 Board - for webbogles board\n#define SSD1306_SA    0x78  // Slave address\n\n// Function prototypes\n\n// Drawing functions - adapted from those at https://bitbucket.org/tinusaur/ssd1306xled\nvoid ssd1306_init(void);\nvoid ssd1306_xfer_start(void);\nvoid ssd1306_xfer_stop(void);\nvoid ssd1306_send_byte(uint8_t byte);\nvoid ssd1306_send_command(uint8_t command);\nvoid ssd1306_send_data_start(void);\nvoid ssd1306_send_data_stop(void);\nvoid ssd1306_setpos(uint8_t x, uint8_t y);\nvoid ssd1306_fillscreen(uint8_t fill_Data);\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]);\nvoid ssd1306_draw_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t bitmap[]);\n\n// Custom draw functions - allow for extra functionality like inverse display\nvoid sendBlock(byte, bool);\nvoid sendByte(byte, bool);\n\n// Other generic functions for games (both originated in code from webboggles.com and the sleep code is by Matthew Little - see above)\nvoid beep(int,int);\nvoid system_sleep(void);\nvoid doNumber (int,int,int);\n\n// Game functions\nvoid playFrogger(void);\nvoid levelUp(int);\nvoid moveBlocks(void);\nvoid initScreen(void);\nvoid drawDocks(void);\nvoid drawLives(void);\nvoid displayTitle(void);\nvoid resetDock(byte);\nvoid checkCollision(void);\n\n// Global variables - yes I know all these global vars is a lazy way to code but it makes it easier to prevent stack overflows when you're working with 512 bytes! \n// Most of these are initialised in the main game function (playFrogger())\nint watchDog;             // Counts drawing cycles so I can shut the game down if there's inactivity - battery saver!\nboolean stopAnimate;      // this is set to 1 when a collision is detected\nint lives;                // Lives in the game - this can go negative to end the game, which is why it's a signed variable  \nbool frogDocks[5];        // Tracks which frog docks are full (at the top of the screen)\nbool flipFlop;            // Used in routines that flip-flop between two states (left and right)\nbool flipFlopShift;       // Same as previous one\nbyte frogColumn;          // Column location of frog (there are 16 altogether)\nbyte frogRow;             // Row locaiton of frog (there are 8, but 0 is the frog docks at the top and 7 is the start row)\nbyte frogLeftLimit;       // Left limit of frog travel on start row (changes as digits in score increases)\nbyte frogRightLimit;      // Right limit of frog travel on start row (changes as lives decrease as there's then more space)\nbyte level;               // Level - starts at 1\nbyte blockShiftL;         // Number of pixels to shift the left-going rows by\nbyte blockShiftR;         // Number of pixels to shift the right-going rows by\nint interimStep;          // Used as timer for incremental movements\nint moveDelay;            // How long to wait until the next movement of logs etc - changes as levels increase to make the game go faster\nint dockedFrogs;          // How many frogs are in the docks at the top\nunsigned long clickBase;  // Timer for debounce\nboolean clickLock;        // For debounce routine\nint score;                // Obvious I hope\nint topScore;             // High score\nboolean newHigh;          // Is there a new high score?\nboolean mute = 0;         // Mute the speaker\nbyte grid[6][16];         // Grid for items like logs, crocs, cars and lorries\nbyte frogMode;            // Represents the frog direction \nbool moveForward=0;       // Captures when the 'forward' button is pressed\nbool moveLeft=0;          // Captures when the 'left' button is pressed\nbool moveRight=0;         // Captures when the 'right' button is pressed\n\n// Bitmaps created by @senkunmusahi using https://www.riyas.org/2013/12/online-led-matrix-font-generator-with.html\nstatic const byte  bitmaps[15][8] PROGMEM = {\n// Frogs\n  {0x83, 0xDC, 0x7A, 0x3F, 0x3F, 0x7A, 0xDC, 0x83},\n  {0x99, 0xBD, 0xDB, 0x7E, 0x7E, 0x3C, 0xE7, 0x81},\n  {0x81, 0xE7, 0x3C, 0x7E, 0x7E, 0xDB, 0xBD, 0x99},\n\n#ifdef SMALLLOGS\n// Small logs\n  {0x1C, 0x22, 0x41, 0x55, 0x55, 0x51, 0x43, 0x61},\n  {0x69, 0x6B, 0x43, 0x61, 0x45, 0x45, 0x61, 0x65},\n  {0x45, 0x55, 0x41, 0x5D, 0x63, 0x5D, 0x22, 0x1C},\n#else\n// Bigger logs\n  {0x3C, 0x7E, 0xD7, 0xB5, 0xAD, 0xBF, 0xFF, 0xED}, \n  {0xAD, 0xAD, 0xFF, 0xB7, 0xF5, 0xBF, 0xB7, 0xAD}, \n  {0xED, 0xBD, 0xC3, 0xBD, 0xA5, 0xBD, 0x42, 0x3C},  \n#endif\n\n// Trucks\n  {0x00, 0x7F, 0x41, 0x55, 0x55, 0x55, 0x55, 0x55},\n  {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}, \n  {0x41, 0x7F, 0x22, 0x7F, 0x7F, 0x63, 0x22, 0x1C},\n\n// Crocs\n  {0x41, 0x63, 0x46, 0x6E, 0x7C, 0x7E, 0x7A, 0x3E},\n  {0xBC, 0xFE, 0x7E, 0x3E, 0xBE, 0xBE, 0xFC, 0x7C},  \n  {0x78, 0x38, 0x38, 0x38, 0x70, 0x60, 0x60, 0x40},\n\n// Cars\n  {0x00, 0x1C, 0x22, 0x63, 0x7F, 0x7F, 0x22, 0x22},\n  {0x22, 0x3E, 0x3E, 0x7F, 0x63, 0x63, 0x22, 0x1C},\n  {0x22, 0x3E, 0x3E, 0x7F, 0x63, 0x63, 0x22, 0x1C}\n  };\n\n// Opening artwork created by @senkunmusahi using https://www.riyas.org/2013/12/online-led-matrix-font-generator-with.html\nstatic const byte titleBmp[] PROGMEM = {\n0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xF0, 0x7C, 0x06, 0x73, 0x59, 0x43,\n0x06, 0x3C, 0x38, 0x30, 0x30, 0x38, 0x3E, 0x26, 0x7B, 0x59, 0x43, 0x06, 0x7C, 0xF0, 0xC0, 0x80,\n0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xFF,\n0xCF, 0x01, 0x00, 0x00, 0x30, 0x60, 0xE0, 0xC0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xC0,\n0xC0, 0x60, 0x30, 0x00, 0x00, 0x00, 0x01, 0xCF, 0xFE, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n0x7C, 0xFE, 0x86, 0x0E, 0x0E, 0x1C, 0x18, 0x31, 0x7F, 0xFE, 0xFC, 0x1C, 0x18, 0x38, 0x38, 0x38,\n0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x18, 0x1C, 0xFC, 0xFE, 0x7F,\n0x39, 0x18, 0x1C, 0x0E, 0x0E, 0xC6, 0xFE, 0x3C, 0x00, 0x01, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xC0,\n0xC0, 0x80, 0x03, 0x07, 0xFC, 0xF8, 0x00, 0x00, 0xF0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xF0,\n0x00, 0x00, 0xF8, 0xFC, 0x0F, 0x03, 0x80, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x03, 0x01, 0x00,\n0x04, 0x06, 0x0F, 0x0F, 0x06, 0x06, 0x03, 0x03, 0x03, 0x63, 0x73, 0x33, 0x3B, 0xFF, 0xFF, 0x7F,\n0x3F, 0x38, 0xF0, 0xC0, 0x00, 0xF0, 0xF8, 0x3F, 0x7F, 0xFF, 0xFF, 0x3B, 0x33, 0x63, 0x63, 0x03,\n0x03, 0x03, 0x06, 0x06, 0x0F, 0x0F, 0x06, 0x00, \n};\n\n// Interrupt handlers\nISR(PCINT0_vect){ // PB0 pin button interrupt           \n  if (clickLock == 0) {\n    moveLeft = 1;\n    clickLock = 1;\n    clickBase = millis();\n  }\n}\n\nvoid playerIncFrogger(){ // PB2 pin button interrupt\n  if (clickLock == 0) {\n    moveRight = 1;\n    clickLock = 1;\n    clickBase = millis();\n  }\n}\n\nvoid displayTitle(void) {\n  int incr = 0;\n  for(int lxn = 2; lxn < 7; lxn++) {\n    ssd1306_setpos(85,lxn); \n    ssd1306_send_data_start();\n    for(int lxn2 = 0; lxn2 < 40; lxn2++) {\n      ssd1306_send_byte(pgm_read_byte(&titleBmp[incr]));      \n      incr++;\n    }\n    ssd1306_send_data_stop();                    \n  }\n}\n\n// Arduino stuff - setup\nvoid setup() {\n  DDRB = 0b00000010;    // set PB1 as output (for the speaker)\n  PCMSK = 0b00000001; // pin change mask: listen to portb bit 1\n  GIMSK |= 0b00100000;  // enable PCINT interrupt \n  sei();          // enable all interrupts\n}\n\n// Arduino stuff - loop\nvoid loop() { \n  ssd1306_init();\n  ssd1306_fillscreen(0x00);\n\n  // The lower case character set is seriously compromised because I've had to truncate the ASCII table\n  // to release space for executable code.\n  // There is no z in the table as this isn't used anywhere in the text here and most of the \n  // symbols are also missing for the same reason (see my hacked version of font6x8.h - font6x8AJ.h for more detail)\n  ssd1306_char_f6x8(0, 2, \"F R O G G E R\");\n  ssd1306_char_f6x8(0, 4, \"andy jackson\"); // see comments above !\n\n  ssd1306_setpos(0,1); \n  for (int incr = 0; incr < 80; incr++) {\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00111000);\n    ssd1306_send_data_stop();                    \n  }\n  ssd1306_setpos(0,3); \n  for (int incr = 0; incr < 80; incr++) {\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00011100);\n    ssd1306_send_data_stop();                    \n  }\n\n  displayTitle();\n\n  ssd1306_char_f6x8(0, 6, \"inspired by\");\n  ssd1306_char_f6x8(0, 7, \"webboggles.com\");\n  delay(1500);\n  ssd1306_char_f6x8(0, 6, \"artwork by \");\n  ssd1306_char_f6x8(0, 7, \"zsenkunmusashi\");  // see comments above - f has been replaced by @ in the ASCII table\n\n  long startT = millis();\n  long nowT =0;\n  boolean sChange = 0;\n\n  while(digitalRead(0) == HIGH) {\n    nowT = millis();\n    if (nowT - startT > 2000) {\n      sChange = 1;     \n      if (digitalRead(2) == HIGH) {\n        EEPROM.write(0,0);\n        EEPROM.write(1,0);\n        ssd1306_char_f6x8(8, 0, \"-HIGH SCORE RESET-\");  \n      } else if (mute == 0) { mute = 1; ssd1306_char_f6x8(32, 0, \"-- MUTE --\"); } else { mute = 0; ssd1306_char_f6x8(31, 0, \"- SOUND ON -\");  }    \n      break;\n    }\n    if (sChange == 1) break;\n  }  \n  while(digitalRead(0) == HIGH);\n\n  if (sChange == 0) {\n    delay(2000);\n\n    ssd1306_init();\n    ssd1306_fillscreen(0x00);\n\n    playFrogger(); \n\n    topScore = EEPROM.read(0);\n    topScore = topScore << 8;\n    topScore = topScore |  EEPROM.read(1);\n\n    newHigh = 0;\n    if (score > topScore) { \n      topScore = score;\n      EEPROM.write(1,score & 0xFF); \n      EEPROM.write(0,(score>>8) & 0xFF); \n      newHigh = 1;\n      }\n\n    ssd1306_fillscreen(0x00);\n    ssd1306_char_f6x8(11, 1, \"----------------\");\n    ssd1306_char_f6x8(11, 2, \"G A M E  O V E R\");\n    ssd1306_char_f6x8(11, 3, \"----------------\");\n    ssd1306_char_f6x8(37, 5, \"SCORE:\");\n    doNumber(75, 5, score);\n    if (!newHigh) {\n      ssd1306_char_f6x8(21, 7, \"HIGH SCORE:\");\n      doNumber(88, 7, topScore);\n    }\n    delay(1000);\n    if (newHigh) {\n      ssd1306_fillscreen(0x00);\n      ssd1306_char_f6x8(10, 1, \"----------------\");\n      ssd1306_char_f6x8(10, 3, \" NEW HIGH SCORE \");\n      ssd1306_char_f6x8(10, 7, \"----------------\");\n      doNumber(50,5,topScore);\n      for (int i = 700; i>200; i = i - 50){\n      beep(30,i);\n      }\n      delay(1200);    \n    } \n  }\n  system_sleep();\n}\n\nvoid doNumber (int x, int y, int value) {\n    char temp[10] = {0,0,0,0,0,0,0,0,0,0};\n    itoa(value,temp,10);\n    ssd1306_char_f6x8(x, y, temp);\n}\n\nvoid ssd1306_init(void){\n  DDRB |= (1 << SSD1306_SDA); // Set port as output\n  DDRB |= (1 << SSD1306_SCL); // Set port as output\n\n  ssd1306_send_command(0xAE); // display off\n  ssd1306_send_command(0x00); // Set Memory Addressing Mode\n  ssd1306_send_command(0x10); // 00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid\n  ssd1306_send_command(0x40); // Set Page Start Address for Page Addressing Mode,0-7\n  ssd1306_send_command(0x81); // Set COM Output Scan Direction\n  ssd1306_send_command(0xCF); // ---set low rowumn address\n  ssd1306_send_command(0xA1); // ---set high rowumn address\n  ssd1306_send_command(0xC8); // --set start line address\n  ssd1306_send_command(0xA6); // --set contrast control register\n  ssd1306_send_command(0xA8);\n  ssd1306_send_command(0x3F); // --set segment re-map 0 to 127\n  ssd1306_send_command(0xD3); // --set normal display\n  ssd1306_send_command(0x00); // --set multiplex ratio(1 to 64)\n  ssd1306_send_command(0xD5); // \n  ssd1306_send_command(0x80); // 0xa4,Output follows RAM content;0xa5,Output ignores RAM content\n  ssd1306_send_command(0xD9); // -set display offset\n  ssd1306_send_command(0xF1); // -not offset\n  ssd1306_send_command(0xDA); // --set display clock divide ratio/oscillator frequency\n  ssd1306_send_command(0x12); // --set divide ratio\n  ssd1306_send_command(0xDB); // --set pre-charge period\n  ssd1306_send_command(0x40); // \n  ssd1306_send_command(0x20); // --set com pins hardware configuration\n  ssd1306_send_command(0x02);\n  ssd1306_send_command(0x8D); // --set vcomh\n  ssd1306_send_command(0x14); // 0x20,0.77xVcc\n  ssd1306_send_command(0xA4); // --set DC-DC enable\n  ssd1306_send_command(0xA6); // \n  ssd1306_send_command(0xAF); // --turn on oled panel \n}\n\nvoid ssd1306_xfer_start(void){\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n}\n\nvoid ssd1306_xfer_stop(void){\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n}\n\nvoid ssd1306_send_byte(uint8_t byte){\n  uint8_t i;\n  for(i=0; i<8; i++)\n  {\n    if((byte << i) & 0x80)\n      DIGITAL_WRITE_HIGH(SSD1306_SDA);\n    else\n      DIGITAL_WRITE_LOW(SSD1306_SDA);\n    \n    DIGITAL_WRITE_HIGH(SSD1306_SCL);\n    DIGITAL_WRITE_LOW(SSD1306_SCL);\n  }\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);\n  DIGITAL_WRITE_LOW(SSD1306_SCL);\n}\n\nvoid ssd1306_send_command(uint8_t command){\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  // Slave address, SA0=0\n  ssd1306_send_byte(0x00);  // write command\n  ssd1306_send_byte(command);\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_send_data_start(void){\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);\n  ssd1306_send_byte(0x40);  //write data\n}\n\nvoid ssd1306_send_data_stop(void){\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_setpos(uint8_t x, uint8_t y)\n{\n  if (y>7) return;\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  //Slave address,SA0=0\n  ssd1306_send_byte(0x00);  //write command\n\n  ssd1306_send_byte(0xb0+y);\n  ssd1306_send_byte(((x&0xf0)>>4)|0x10); // |0x10\n  ssd1306_send_byte((x&0x0f)|0x01); // |0x01\n\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_fillscreen(uint8_t fill_Data){\n  uint8_t m,n;\n  for(m=0;m<8;m++)\n  {\n    ssd1306_send_command(0xb0+m); //page0-page1\n    ssd1306_send_command(0x00);   //low rowumn start address\n    ssd1306_send_command(0x10);   //high rowumn start address\n    ssd1306_send_data_start();\n    for(n=0;n<128;n++)\n    {\n      ssd1306_send_byte(fill_Data);\n    }\n    ssd1306_send_data_stop();\n  }\n}\n\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]){\n  uint8_t c,i,j=0;\n  while(ch[j] != '\\0')\n  {\n    c = ch[j] - 32;\n    if (c >0) c = c - 12;\n    if (c >15) c = c - 6;\n    if (c>40) c=c-9;\n    if(x>126)\n    {\n      x=0;\n      y++;\n    }\n    ssd1306_setpos(x,y);\n    ssd1306_send_data_start();\n    for(i=0;i<6;i++)\n    {\n      ssd1306_send_byte(pgm_read_byte(&ssd1306xled_font6x8[c*6+i]));\n    }\n    ssd1306_send_data_stop();\n    x += 6;\n    j++;\n  }\n}\n\nvoid system_sleep(void) {\n  ssd1306_fillscreen(0x00);\n  ssd1306_send_command(0xAE);\n  cbi(ADCSRA,ADEN);                    // switch analog to digital converter off\n  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here\n  sleep_enable();\n  sleep_mode();                        // system actually sleeps here\n  sleep_disable();                     // system continues execution here when watchdog timed out \n  sbi(ADCSRA,ADEN);                    // switch analog to digital converter on\n  ssd1306_send_command(0xAF);\n}\n\nvoid beep(int bCount,int bDelay){\n  if (mute) return;\n  for (int i = 0; i<=bCount; i++){digitalWrite(1,HIGH);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}digitalWrite(1,LOW);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}}\n}\n\n\n/* ------------------------\n *  Frogger main game code\n */\nvoid playFrogger(){\n  stopAnimate = 0;\n  score = 0;\n  moveDelay = MOVEBASE;\n  level = 1;\n  frogColumn = 8;\n  frogRow = 7;\n  clickLock = 0;\n  frogMode = 1;\n  interimStep =0;\n  blockShiftL = 0;\n  blockShiftR = 0;\n  flipFlop = 1;\n  flipFlopShift = 1;\n  dockedFrogs = 0;\n  lives = 2;\n  frogRightLimit = 12;\n  watchDog = 1; // we use this to see if there's been movement - it's only ever zero when the frog has just moved!\n\n  attachInterrupt(0,playerIncFrogger,CHANGE);\n\n  initScreen();\n  resetDock(0);\n\n  drawFrog(frogMode,0);\n  drawGameScreen(frogMode);\n  drawLives();\n  drawDocks();\n  \n  doNumber(0,7,score);\n  \n  while (lives >= 0) {\n    interimStep++;\n\n    if (watchDog >= 500) lives = -1; // Stop the game if nothing's happening - maybe triggered in someone's pocket so this is to save battery!\n    \n    // Calculate left limit of frog movement so it doesn't hit the score\n    frogLeftLimit = 1;\n    if ((score / 10) % 10 != 0) frogLeftLimit++; \n    if ((score / 100) % 10 != 0) frogLeftLimit++;\n    if ((score / 1000) % 10 != 0) frogLeftLimit++;\n\n    // Move stuff along if it's time to\n    if (interimStep > moveDelay/8) {\n      watchDog++;\n      blockShiftL++;\n      if (flipFlopShift == 1) flipFlopShift = 0; else flipFlopShift = 1;\n      if (flipFlopShift == 1) blockShiftR++;\n      if (blockShiftL == 7) {\n        moveBlocks();\n        blockShiftL = 0;\n      }\n      if (blockShiftR == 7) {\n        blockShiftR = 0;\n      }\n      interimStep = 0;\n      checkCollision();\n      if (stopAnimate == 0) {\n        drawGameScreen(frogMode);\n        drawFrog(frogMode,0);\n      }\n    }\n\n    // Handle input from 'jump' button (the other two buttons are captured in the interrupt routines)\n    if (analogRead(0) < 940 && clickLock == 0) {\n      moveForward = 1;\n      watchDog = 0;   // reset the watchdog so the game doesn't end!\n      clickLock = 1;\n      clickBase = millis();\n    }\n\n    // Handle moving left\n    if(moveLeft == 1 && millis() > clickBase + CLICKDELAY/2) {\n      watchDog = 0;   // reset the watchdog so the game doesn't end!\n      moveLeft = 0;\n      if (digitalRead(2) == HIGH) moveForward = 1; else {\n        drawFrog(0,0);  // delete the frog\n        // move the frog, checking it isn't jumping off the edge of the screen\n        if ((frogRow == 7 && frogColumn > frogLeftLimit) || (frogRow < 7 && frogColumn > 0)) {\n          frogColumn --;\n        } else if (frogRow < 7) stopAnimate = 1;\n        frogMode = 2; // pointing left\n      }\n    }\n\n    // Handle moving right\n    if(moveRight == 1 && millis() > clickBase + CLICKDELAY/2){\n      watchDog = 0;   // reset the watchdog so the game doesn't end!\n      moveRight = 0;\n      if (digitalRead(0) == HIGH) moveForward = 1; else {\n        drawFrog(0,0); // delete the frog\n        // move the frog, checking it isn't jumping off the edge of the screen\n        if ((frogRow == 7 && frogColumn < frogRightLimit) || (frogRow < 7 && frogColumn < 14)) {\n          frogColumn ++;\n        } else if (frogRow < 7) stopAnimate = 1;\n        frogMode = 3; // pointing right    \n      }\n    }\n\n    // Handle 'move forward' button press\n    if (moveForward == 1) {\n      moveForward = 0;\n  \n      score+= level;          // increment the score for every move\n      doNumber(0,7,score);    // display new score\n      drawFrog(0,0);          // delete the frog\n  \n      if (frogRow > 1) {\n        frogRow--; \n        // Correct for the skew in frog position created by the blockShift scrolling parameter\n        if (frogRow == 3 && blockShiftL < 4) frogColumn--;\n        if (frogRow == 2 && blockShiftR + blockShiftL < 5) frogColumn++;\n        if (frogRow == 1 && blockShiftR + blockShiftL < 5) frogColumn--;\n                \n      } else {\n        // frog is at the docks!\n        if (blockShiftL < 4 && frogColumn <15) frogColumn++;  // account for skew due to block shifting\n        byte dockPos = (byte)floor(frogColumn/3);\n        if (frogDocks[dockPos] == 0 ) {\n          dockedFrogs++;          \n          frogDocks[dockPos] = 1;                             // assign this dock as filled\n          frogRow = 7;                                        // reposition the frog at the start\n          frogColumn = 8;\n          for (int i = 1000; i>200; i = i - 100){             // make sound\n          beep(10,i);\n          drawDocks();                                        // redraw the docks\n          }\n        } else stopAnimate = 1;\n      }\n      frogMode = 1;             // mode 1 = forwards position\n\n      // check if all docks are full - if so, then level up!\n      if (dockedFrogs >= 5) {\n        level++;\n        levelUp(level);\n        if (moveDelay > 99) moveDelay -=100; // make the game speed up \n        initScreen();                        // reinitalise the position of game items\n        resetDock(0);                        // reinitliase the dock\n        dockedFrogs = 0;              \n        drawDocks();                         // display the (now empty) docks\n        drawLives();                         // display the lives\n        doNumber(0,7,score);                 // display the score\n      }      \n    }\n\n    // The frog has moved \n    if (watchDog == 0 && stopAnimate == 0) {\n      watchDog = 1;               // set to something other than zero so this routine doesn't run again\n      // redraw the frog\n      drawFrog(frogMode,0);\n      // redraw the screen\n      drawGameScreen(frogMode);\n      // make jump sound\n      beep(30,400);\n      beep(30,300);\n      beep(30,200);\n    }\n    \n    checkCollision();\n    \n    if (clickLock == 1 && millis() > clickBase + CLICKDELAY && digitalRead(2)==0 && digitalRead(0)==0 && analogRead(0) > 940) clickLock = 0; // normal debounce\n\n    // check to see if the frog has been killed\n    if (stopAnimate != 0) {\n      // redraw the screen\n      drawGameScreen(frogMode);\n      // animation for frog death\n      drawFrog(0,1);\n      for (int i = 0; i<250; i = i+ 50){  \n        beep(50,i);\n      }\n      drawFrog(frogMode,1);    \n      for (int i = 250; i<500; i = i+ 50){  \n        beep(50,i);\n      }\n      drawFrog(0,1);\n      for (int i = 500; i<750; i = i+ 50){  \n        beep(50,i);\n      }\n      drawFrog(frogMode,1);\n      for (int i = 750; i<1000; i = i+ 50){  \n        beep(50,i);\n      }\n      delay(600);\n      lives--;          // increment the score for every move\n      frogRightLimit++; // there's one less frog drawn on right so you can move a bit further across (if you really want to!)\n      stopAnimate = 0;  // reset parameter\n      drawLives();      // display number of lives left\n      frogColumn = 8;   // reinitalise frog location\n      frogRow = 7;\n      }\n  }  // Big while loop (main game loop) goes until lives is negative\n} \n\nvoid checkCollision(void) {\n  if (frogRow > 0 && frogRow < 4 && grid[frogRow-1][frogColumn] == 0) stopAnimate = 1; // the frog has fallen in the river\n  if (frogRow > 0 && frogRow < 4 && grid[frogRow-1][frogColumn] > 9) stopAnimate = 1; // the frog has stepped on a croc\n  if ((frogRow < 7 && frogRow > 3) && (grid[frogRow-1][frogColumn] != 0 || grid[frogRow-1][frogColumn-1] != 0)) stopAnimate = 1; // the frog has been hit by a vehicle\n}\n\n// Initialise all the moving objects on the game screen\nvoid initScreen(void) {\n  int initCounter[6] = {3,2,4,2,2,3};       // the length of the objects on each row - doesn't change\n  int gapCounter[6] = {-2,-3,-4,-4,-3,-5};  // the gaps between objects - change with levels to make it harder as you go thru the game\n  int counter[6];                           // used to hold the gap data\n  byte stepMode = 0;                        // which component of the object are we drawing (they all have three - a start a middle and an end)\n  byte stepShift = 0;                       // offset to shift up to the different objects in the array\n  byte crocStartColumn = 0;                 // column at which to stop drawing crocs - is zero at start hence no crocs!\n\n  \n  // Adjust difficulty by changing gaps between objects according to level\n  if (level == 1) {\n    gapCounter[5] = -14;           // easiset setting, for start of game\n  }\n  if (level < 3) {\n    gapCounter[4] = -6;            // make it easier for levels less than 3 by increasing the gap in the cars on this row\n  }\n  if (level < 4) {\n    gapCounter[3] = -7;\n  }\n  if (level > 4) {\n    for (byte incr = 1; incr < 3; incr++) {\n      gapCounter[incr]--;         // increase the gaps between the logs for levels over 4  \n    }\n  }\n  if (level > 7) {                // set smaller gaps between cars for levels over 7\n    gapCounter[3] = -4; \n    gapCounter[4] = -2;\n    gapCounter[5] = -3;\n  }\n  if (level > 2) crocStartColumn = 5; // one croc appears at level 3 and above\n  if (level > 6) crocStartColumn = 9; // two croc appear at level 7 and above\n  \n  // Initialise the counters\n  for (byte incr = 0; incr < 6;incr++) counter[incr] = initCounter[incr];  \n\n  // Initialise array with zeros\n  for (byte col = 0; col < 16; col++) {\n    for (byte row = 0; row < 6; row++) {\n      grid[row][col] = 0;\n    }\n  }\n       \n  stepMode = 0;\n  // Initialise array with obstacles\n  for (byte row = 0; row < 6; row++) {\n    for (byte col = 0; col < 15; col++) {         \n      if (counter[row] > 0) {\n        if (14-row > counter[row]) {\n          if (counter[row] == 1) if (stepMode == 1) stepMode = 2; // the next space is blank and we are drawing the middle - draw the end! \n          if (row > 2) stepShift = 3; else stepShift = 0;         // shift up to the trucks in the array\n          if (row == 4) stepShift = 9;                            // shift up to the cars in the array - also theres no middle\n          \n          if (row > 0) {\n            grid[row][col] = 4+stepMode+stepShift;                // if you are on any row but the first - draw whatever is appropriate from the bitmaps\n          } else if (col >= crocStartColumn) {                    \n            grid[row][col] = 4+stepMode+stepShift;                // if you're on row zero (top row of logs) and you are above where crocs should be drawm, draw logs ...\n          } else grid[row][col] = 10+stepMode;                    // .. otherwise draw crocs\n          if (stepMode == 0) stepMode = 1;                        // we've drawn the left side now switch to central sections\n          if (stepMode == 2) stepMode = 0;                        // we've drawn the end, now reset\n        }\n      } \n      counter[row]--;                                             // decrement the counter\n      if (counter[row] <= gapCounter[row]) {\n        counter[row] = initCounter[row];                          // if we have gone negative enough to account for the gaps - reset the counter and start again\n      }\n    }\n  }\n}\n\n// Display the frog\nvoid drawFrog(byte mode, bool frogDead) {\n  if (frogRow > 6 || frogRow < 1 || frogDead == 1) {           // don't draw the frog when it's on the road or on logs - because they are moving, that's handled in the main drawing routine below- exception is when you are animating frog death\n    if (frogRow == 1 || frogRow == 3) {                        // these allow for the blocks being shifted when animating the frog death on rows with logs\n      ssd1306_setpos(frogColumn*8 + 7 - blockShiftL,frogRow);\n    } else if (frogRow == 2) {\n      ssd1306_setpos(frogColumn*8 + blockShiftR,frogRow);      \n    } else {\n      ssd1306_setpos(frogColumn*8,frogRow); \n    }\n    ssd1306_send_data_start();\n    sendBlock(mode,0);                   // draw the frog - mode is direction\n    ssd1306_send_data_stop();                    \n  }    \n}\n\n// Display the frog and all the moving items on the screen\nvoid drawGameScreen(byte mode) {\n  bool inverse = 0;\n  \n  // Draw objects going left\n  for (byte row = 0; row < 6; row+=2) {\n    if (row >=0 && row < 3) inverse = 1; else inverse = 0;                              // draw everything (except the frog) in inverse video on the river rows (0,1,2)\n    ssd1306_setpos(0,row+1);                                                            // +1 because row 0 here is actually row 1 on the screen\n    ssd1306_send_data_start();\n    for (byte incr = 0; incr < 7-blockShiftL; incr++) if (grid[row][15] == 0) {         // cover the tiny bit to the far left of the screen up to wherever the main blocks will be drawn (depends on how far they are shifted)\n      sendByte(0,inverse);                                                              // draw an empty 8-bit line if there's nothing wrapping around\n    } else {\n      sendByte(pgm_read_byte(&bitmaps[grid[row][15]-1][1+blockShiftL+incr]), inverse);  // pick the correct bit of whatever is wrapping from the right of the screen\n    }\n    for (byte col = 0; col < 15; col++) {         \n      if (frogRow == row+1 && frogColumn == col && frogRow < 4 && frogRow > 0) {\n        sendBlock(mode,0);                                                                          // if we are in a location with the frog, and it's on the logs, draw it - never invert it (hence zero as second parameter here)\n      } else if (stopAnimate == 0 && frogRow == row+1 && frogColumn == col + 1 && frogRow > 3 && frogRow < 7) {         // frog is amongst the cars and needs drawing\n        for (byte incr = 0; incr < blockShiftL; incr++) sendByte(0,0);                              // draw the blank space up to the frog\n        sendBlock(mode,0);                                                                          // draw frog\n        for (byte incr = 0; incr < 7-blockShiftL; incr++) sendByte(0,0);                            // draw the blank space after the frog\n        col++;                                                                                      // we've now drawn two columns so increment\n      } else {\n        sendBlock(grid[row][col],inverse);                                                          // draw the correct object for this space - it's not a frog ;)\n      }\n    }\n    // fill in the bit to the right of the main blocks \n    for (byte incr = 0; incr < blockShiftL; incr++) if (grid[row][15] == 0) sendByte(0,inverse); else sendByte(pgm_read_byte(&bitmaps[grid[row][15]-1][incr]),inverse);\n\n    ssd1306_send_data_stop();\n  }\n  if (frogColumn == 0) drawFrog(mode,1); // this covers the exceptional case where the frog is in the far left colum, in which case the normal routine can't draw it when it's on the road\n  \n  // Draw objects going right - see comments above, works in basically the same way\n  for (byte row = 1; row < 6; row+=2) {\n    if (row > 0 && row < 3) inverse = 1; else inverse = 0;\n    ssd1306_setpos(0,row+1);\n    ssd1306_send_data_start();\n    for (byte incr = 0; incr < blockShiftR; incr++) if (grid[row][15] == 0) sendByte(0, inverse); else sendByte(pgm_read_byte(&bitmaps[grid[row][15]-1][incr+(8-blockShiftR)]),inverse);\n    for (byte col = 0; col < 15; col++) {         \n      if (frogRow == row+1 && frogColumn == col && frogRow < 4 && frogRow > 0) {\n        sendBlock(mode,0);    \n      } else if (stopAnimate == 0 && frogRow == row+1 && frogColumn == col + 1 && frogRow > 3 && frogRow < 7) {  \n        for (byte incr = 0; incr < 7-blockShiftR; incr++) sendByte(0,0);\n        sendBlock(mode,0); // draw frog\n        for (byte incr = 0; incr < blockShiftR; incr++) sendByte(0,0);\n        col++;        \n      } else {\n        sendBlock(grid[row][col],inverse);        \n      }\n    }\n    for (byte incr = 0; incr < 7-blockShiftR; incr++) if (grid[row][15] == 0) sendByte(0,inverse); else sendByte(pgm_read_byte(&bitmaps[grid[row][15]-1][incr]),inverse);\n    ssd1306_send_data_stop();\n  }\n  if (frogColumn == 0) drawFrog(mode,1);\n}\n\n// Send one byte to the screen\nvoid sendByte(byte fill, bool inverse) {\n  if (inverse == 0) ssd1306_send_byte(fill); else ssd1306_send_byte(~fill);\n}\n\n// Send one block of 8 bytes to the screen - inverse means inverse video, for the river section\nvoid sendBlock(byte fill, bool inverse){\n  for (int incr = 0; incr < 8; incr++) {\n    if (fill > 0) {\n      if (inverse == 0) ssd1306_send_byte(pgm_read_byte(&bitmaps[fill-1][incr])); else ssd1306_send_byte(~pgm_read_byte(&bitmaps[fill-1][incr]));  \n    } else if (inverse ==0) ssd1306_send_byte(0); else ssd1306_send_byte(0xFF); \n  }\n}\n\n// Draw the frog lives (in the right hand corner)\nvoid drawLives(void) {\n  byte tempRow = frogColumn;\n  byte tempCol = frogRow;\n  frogRow = 7;\n\n  for (int incr = 2; incr > 0; incr--) {\n    frogColumn = 15-incr;\n    drawFrog(0,1);\n  }\n\n  for (int incr = lives; incr > 0; incr--) {\n    frogColumn = 15-incr;\n    drawFrog(1,1);\n  }\n  frogRow = tempCol;\n  frogColumn = tempRow;    \n}\n\n// Draw the docks for the frog to land in at top of screen\nvoid drawDocks(void) {\n  byte drawPos = 3;\n  for (byte incr = 0; incr < 5; incr++) {\n    ssd1306_setpos(drawPos,0);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B11111111);\n    ssd1306_send_byte(B00000001);\n    ssd1306_send_byte(B00000001);\n    if (frogDocks[incr] == 1) sendBlock(1,0); else for(byte lxn = 0; lxn < 8; lxn++) ssd1306_send_byte(B00000001);\n    ssd1306_send_byte(B00000001);\n    ssd1306_send_byte(B00000001);\n    ssd1306_send_byte(B11111111);\n    ssd1306_send_data_stop();\n    drawPos+= 24;\n    }    \n}\n\n// Set all the frog docks to a single value\nvoid resetDock(byte value) {   for (byte incr = 0; incr < 5;incr++) frogDocks[incr] = value; }\n\n// Handle what happens at the end of a level\nvoid levelUp(int number) {  \n  // Flash the frog docks\n  delay(200);\n  for (byte incr = 0; incr < 5; incr ++) {\n    resetDock(0);\n    drawDocks();\n    for (int i = 800; i>200; i = i - 200){\n    beep(20,i);\n    }\n    resetDock(1);\n    drawDocks();\n    for (int i = 800; i>200; i = i - 200){\n    beep(20,i);\n    }\n  }  \n  delay(500);\n  ssd1306_fillscreen(0x00);\n  ssd1306_char_f6x8(35, 1, \"---------\");\n  ssd1306_char_f6x8(35, 3, \" LEVEL \");\n  ssd1306_char_f6x8(35, 5, \"---------\");\n  doNumber(77,3,number);\n  delay(1500);    \n  ssd1306_fillscreen(0x00);\n}\n\n// Move all the items on the game screen (wrapping at the ends) and check for frog dropping off the end of the screen\nvoid moveBlocks(void) {\n  int direct = 0;\n\n  if (flipFlop == 1) flipFlop = 0; else flipFlop = 1;\n  \n  for (byte row = 0; row < 6; row++) {\n    // Move the frog along and check to see whether it's gone off the screen, in which case it dies\n    if (frogRow < 4 && frogRow > 0) { \n      if (frogRow == row + 1) {\n        if (direct == 1 && flipFlop == 1) {\n          if (frogColumn >= 14) stopAnimate = 1; else frogColumn++; \n        } else if (direct == 0) {\n          if (frogColumn < 1) stopAnimate = 1; else frogColumn--;\n        }\n      }  \n    }\n    if (direct == 0) { // move left\n      byte temp = grid[row][0];\n      for (byte col = 0; col < 15; col++) {         \n        grid[row][col] = grid[row][col+1];\n      }\n      grid[row][15] = temp; // wrap around\n      direct = 1;\n    } else { // move right\n      if (flipFlop == 1) {\n        byte temp = grid[row][15];\n        for (byte col = 15; col > 0; col--) {         \n          grid[row][col] = grid[row][col-1];\n          }\n        grid[row][0] = temp; // wrap around\n        }\n      direct = 0;  \n      }\n    }\n  }\r\n"
  },
  {
    "path": "Frogger_Attiny_Arcade/font6x8AJ2.h",
    "content": "/*\n * SSD1306xLED - Drivers for SSD1306 controlled dot matrix OLED/PLED 128x64 displays\n *\n * @file: font6x8.h\n * @created: 2014-08-12\n * @author: Neven Boyanov\n * \n * Hacked by andy jackson to allow two games (originally by webboggles.com) to \n * fit onto an ATTiny85 at the same time - hence several characters are missing\n * and a couple have been moved to limit the amount of software remapping required\n * to map ASCII values onto locations in this array.\n *\n * Source code available at: https://bitbucket.org/tinusaur/ssd1306xled\n *\n */\n\n// ----------------------------------------------------------------------------\n\n#include <avr/pgmspace.h>\n\n// ----------------------------------------------------------------------------\n\n/* Standard ASCII 6x8 font */\nstatic const uint8_t ssd1306xled_font6x8 [] PROGMEM = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sp\n/*\n  0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // !\n  0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // \"\n  0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // #\n  0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $\n  0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // %\n  0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // &\n  0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // '\n  0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // (\n  0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // )\n  0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // *\n  0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // +\n  0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // ,\n  */\n  0x00, 0x08, 0x08, 0x08, 0x08, 0x08, // -\n  0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // .\n  0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w in place of /\n  //0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // /\n  0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0\n  0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, // 1\n  0x00, 0x42, 0x61, 0x51, 0x49, 0x46, // 2\n  0x00, 0x21, 0x41, 0x45, 0x4B, 0x31, // 3\n  0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, // 4\n  0x00, 0x27, 0x45, 0x45, 0x45, 0x39, // 5\n  0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6\n  0x00, 0x01, 0x71, 0x09, 0x05, 0x03, // 7\n  0x00, 0x36, 0x49, 0x49, 0x49, 0x36, // 8\n  0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, // 9\n  0x00, 0x00, 0x36, 0x36, 0x00, 0x00, // :\n/*\n  0x00, 0x00, 0x56, 0x36, 0x00, 0x00, // ;\n  0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // <\n  0x00, 0x14, 0x14, 0x14, 0x14, 0x14, // =\n  0x00, 0x00, 0x41, 0x22, 0x14, 0x08, // >\n  0x00, 0x02, 0x01, 0x51, 0x09, 0x06, // ?\n  0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, // @\n */\n  0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, // B\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, // C\n  0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, // D\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, // E\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, // F\n  0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, // G\n  0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, // H\n  0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, // I\n  0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, // J\n  0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, // K\n  0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, // L\n  0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M\n  0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, // N\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, // O\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, // P\n  0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q\n  0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, // R\n  0x00, 0x46, 0x49, 0x49, 0x49, 0x31, // S\n  0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, // T\n  0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, // U\n  0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, // V\n  0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, // W\n/*\n  0x00, 0x63, 0x14, 0x08, 0x14, 0x63, // X\n  0x00, 0x07, 0x08, 0x70, 0x08, 0x07, // Y\n  0x00, 0x61, 0x51, 0x49, 0x45, 0x43, // Z\n  0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, // [\n  0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55, // 55\n  0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, // ]\n  0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^\n  0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _\n  0x00, 0x00, 0x01, 0x02, 0x04, 0x00, // '\n*/\n  0x00, 0x20, 0x54, 0x54, 0x54, 0x78, // a\n  0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, // b\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x20, // c\n  0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, // d\n  0x00, 0x38, 0x54, 0x54, 0x54, 0x18, // e\n  0x00, 0x08, 0x7E, 0x09, 0x01, 0x02, // f\n  0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g\n  0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h\n  0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, // i\n  0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, // j\n  0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, // k\n  0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, // l\n  0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, // m\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, // n\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x38, // o\n  0x00, 0xFC, 0x24, 0x24, 0x24, 0x18, // p\n  0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, // q\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, // r\n  0x00, 0x48, 0x54, 0x54, 0x54, 0x20, // s\n  0x00, 0x04, 0x3F, 0x44, 0x40, 0x20, // t\n  0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, // u\n  0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, // v\n  0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w\n  0x00, 0x44, 0x28, 0x10, 0x28, 0x44, // x\n  0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C,  // y\n  0x00, 0x32, 0x49, 0x59, 0x51, 0x3E // @ in place of z\n};\n\n// ----------------------------------------------------------------------------\n\r\n"
  },
  {
    "path": "Frogger_MAKERbuino/Frogger_MAKERbuino.ino",
    "content": "/*  2018\r\n *   \r\n *  Frogger for MakerBuino and GameBuino by Andy Jackson - Twitter @andyhighnumber\r\n *  \r\n *  You need to install the 'Classic' GameBuino libraries in your Arduino IDE, like this:\r\n *  http://legacy.gamebuino.com/wiki/index.php?title=Getting_started#Install_the_Gamebuino_Library_.28Automatic.29\r\n *  \r\n *  Everything you need to build and run this game is contained in this file and the font \r\n *  header (font6x8AJ3.h) \r\n *  \r\n *  This is a port of a Frogger clone written for the AttinyArcade, which is why some of\r\n *  the display routines look a bit weird. More info here:\r\n *  https://github.com/andyhighnumber/Attiny-Arduino-Games\r\n *  \r\n *  Permission is hereby granted, free of charge, to any person obtaining a copy of \r\n *  this software and associated documentation files (the \"Software\"), to deal in the \r\n *  Software without restriction, including without limitation the rights to use, copy, \r\n *  modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, \r\n *  and to permit persons to whom the Software is furnished to do so, subject to the \r\n *  following conditions: \r\n *  \r\n *  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, \r\n *  INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR \r\n *  PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE \r\n *  FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR \r\n *  OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \r\n *  DEALINGS IN THE SOFTWARE.\r\n * \r\n*/\r\n\r\n//imports the SPI library (needed to communicate with Gamebuino's screen)\r\n#include <SPI.h>\r\n//imports the Gamebuino library\r\n#include <Gamebuino.h>\r\n//creates a Gamebuino object named gb\r\nGamebuino gb;\r\n\r\n\r\n#include <EEPROM.h>\r\n#include \"font6x8AJ4.h\"\r\n\r\n\r\n// Uncomment this #define to make the logs smaller (/thinner)\r\n//#define SMALLLOGS\r\n\r\n// Make click delay an even number - it gets halved and then used in an integer comparison\r\n#define CLICKDELAY 120 \r\n\r\n// The basline speed - higher number is slower\r\n#define MOVEBASE 1000 \r\n\r\n#define DIGITAL_WRITE_HIGH(PORT) PORTB |= (1 << PORT)\r\n#define DIGITAL_WRITE_LOW(PORT) PORTB &= ~(1 << PORT)\r\n\r\n// Routines to set and clear bits (used in the sleep code)\r\n#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))\r\n#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))\r\n\r\n// Defines for OLED output\r\n#define lcdDisplayXLED_H\r\n#define lcdDisplay_SCL   PORTB4  // SCL, Pin 4 on lcdDisplay Board - for webbogles board\r\n#define lcdDisplay_SDA   PORTB3  // SDA, Pin 3 on lcdDisplay Board - for webbogles board\r\n#define lcdDisplay_SA    0x78  // Slave address\r\n\r\n// Function prototypes\r\n\r\n// Custom draw functions - allow for extra functionality like inverse display\r\nvoid sendBlock(byte, bool);\r\nvoid sendByte(byte, bool);\r\n\r\n// Other generic functions for games (both originated in code from webboggles.com and the sleep code is by Matthew Little - see above)\r\nvoid beep(int,int);\r\nvoid system_sleep(void);\r\nvoid doNumber (int,int,int);\r\n\r\n// Game functions\r\nvoid playFrogger(void);\r\nvoid levelUp(int);\r\nvoid moveBlocks(void);\r\nvoid initScreen(void);\r\nvoid drawDocks(void);\r\nvoid drawLives(void);\r\nvoid displayTitle(void);\r\nvoid resetDock(byte);\r\nvoid checkCollision(void);\r\n\r\n// Global variables - yes I know all these global vars is a lazy way to code but it makes it easier to prevent stack overflows when you're working with 512 bytes! \r\n// Most of these are initialised in the main game function (playFrogger())\r\nint watchDog;             // Counts drawing cycles so I can shut the game down if there's inactivity - battery saver!\r\nboolean stopAnimate;      // this is set to 1 when a collision is detected\r\nint lives;                // Lives in the game - this can go negative to end the game, which is why it's a signed variable  \r\nbool frogDocks[5];        // Tracks which frog docks are full (at the top of the screen)\r\nbool flipFlop;            // Used in routines that flip-flop between two states (left and right)\r\nbool flipFlopShift;       // Same as previous one\r\nbyte frogColumn;          // Column location of frog (there are 16 altogether)\r\nbyte frogRow;             // Row locaiton of frog (there are 8, but 0 is the frog docks at the top and 7 is the start row)\r\nbyte frogLeftLimit;       // Left limit of frog travel on start row (changes as digits in score increases)\r\nbyte frogRightLimit;      // Right limit of frog travel on start row (changes as lives decrease as there's then more space)\r\nbyte level;               // Level - starts at 1\r\nbyte blockShiftL;         // Number of pixels to shift the left-going rows by\r\nbyte blockShiftR;         // Number of pixels to shift the right-going rows by\r\nint interimStep;          // Used as timer for incremental movements\r\nint moveDelay;            // How long to wait until the next movement of logs etc - changes as levels increase to make the game go faster\r\nint dockedFrogs;          // How many frogs are in the docks at the top\r\nunsigned long clickBase;  // Timer for debounce\r\nboolean clickLock;        // For debounce routine\r\nint score;                // Obvious I hope\r\nint topScore;             // High score\r\nboolean newHigh;          // Is there a new high score?\r\nboolean mute = 0;         // Mute the speaker\r\nbyte grid[6][16];         // Grid for items like logs, crocs, cars and lorries\r\nbyte frogMode;            // Represents the frog direction \r\nbool moveForward=0;       // Captures when the 'forward' button is pressed\r\nbool moveLeft=0;          // Captures when the 'left' button is pressed\r\nbool moveRight=0;         // Captures when the 'right' button is pressed\r\nbool moveBack=0;         // Captures when the 'right' button is pressed\r\n\r\nint screenLeft = 0;       // Current left position of the displayed screen\r\nint screenTop = 0;        // Current top of the displayed screen\r\nbyte currentX = 0;        // Current X positon to draw\r\nbyte currentY = 0;        // Current Y positon to draw\r\n\r\n// Bitmaps created by @senkunmusahi using https://www.riyas.org/2013/12/online-led-matrix-font-generator-with.html\r\nstatic const byte  bitmaps[16][8] PROGMEM = {\r\n// Frogs\r\n  {0x83, 0xDC, 0x7A, 0x3F, 0x3F, 0x7A, 0xDC, 0x83},\r\n  {0x99, 0xBD, 0xDB, 0x7E, 0x7E, 0x3C, 0xE7, 0x81},\r\n  {0x81, 0xE7, 0x3C, 0x7E, 0x7E, 0xDB, 0xBD, 0x99},\r\n  {0xC1, 0x3B, 0x5E, 0xFC, 0xFC, 0x5E, 0x3B, 0xC1},\r\n\r\n#ifdef SMALLLOGS\r\n// Small logs\r\n  {0x1C, 0x22, 0x41, 0x55, 0x55, 0x51, 0x43, 0x61},\r\n  {0x69, 0x6B, 0x43, 0x61, 0x45, 0x45, 0x61, 0x65},\r\n  {0x45, 0x55, 0x41, 0x5D, 0x63, 0x5D, 0x22, 0x1C},\r\n#else\r\n// Bigger logs\r\n  {0x3C, 0x7E, 0xD7, 0xB5, 0xAD, 0xBF, 0xFF, 0xED}, \r\n  {0xAD, 0xAD, 0xFF, 0xB7, 0xF5, 0xBF, 0xB7, 0xAD}, \r\n  {0xED, 0xBD, 0xC3, 0xBD, 0xA5, 0xBD, 0x42, 0x3C},  \r\n#endif\r\n\r\n// Trucks\r\n  {0x00, 0x7F, 0x41, 0x55, 0x55, 0x55, 0x55, 0x55},\r\n  {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}, \r\n  {0x41, 0x7F, 0x22, 0x7F, 0x7F, 0x63, 0x22, 0x1C},\r\n\r\n// Crocs\r\n  {0x41, 0x63, 0x46, 0x6E, 0x7C, 0x7E, 0x7A, 0x3E},\r\n  {0xBC, 0xFE, 0x7E, 0x3E, 0xBE, 0xBE, 0xFC, 0x7C},  \r\n  {0x78, 0x38, 0x38, 0x38, 0x70, 0x60, 0x60, 0x40},\r\n\r\n// Cars\r\n  {0x00, 0x1C, 0x22, 0x63, 0x7F, 0x7F, 0x22, 0x22},\r\n  {0x22, 0x3E, 0x3E, 0x7F, 0x63, 0x63, 0x22, 0x1C},\r\n  {0x22, 0x3E, 0x3E, 0x7F, 0x63, 0x63, 0x22, 0x1C}\r\n  };\r\n\r\n// Opening artwork created by @senkunmusahi using https://www.riyas.org/2013/12/online-led-matrix-font-generator-with.html\r\nstatic const byte titleBmp[] PROGMEM = {\r\n0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xF0, 0x7C, 0x06, 0x73, 0x59, 0x43,\r\n0x06, 0x3C, 0x38, 0x30, 0x30, 0x38, 0x3E, 0x26, 0x7B, 0x59, 0x43, 0x06, 0x7C, 0xF0, 0xC0, 0x80,\r\n0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xFF,\r\n0xCF, 0x01, 0x00, 0x00, 0x30, 0x60, 0xE0, 0xC0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xC0,\r\n0xC0, 0x60, 0x30, 0x00, 0x00, 0x00, 0x01, 0xCF, 0xFE, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n0x7C, 0xFE, 0x86, 0x0E, 0x0E, 0x1C, 0x18, 0x31, 0x7F, 0xFE, 0xFC, 0x1C, 0x18, 0x38, 0x38, 0x38,\r\n0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x18, 0x1C, 0xFC, 0xFE, 0x7F,\r\n0x39, 0x18, 0x1C, 0x0E, 0x0E, 0xC6, 0xFE, 0x3C, 0x00, 0x01, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xC0,\r\n0xC0, 0x80, 0x03, 0x07, 0xFC, 0xF8, 0x00, 0x00, 0xF0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xF0,\r\n0x00, 0x00, 0xF8, 0xFC, 0x0F, 0x03, 0x80, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x03, 0x01, 0x00,\r\n0x04, 0x06, 0x0F, 0x0F, 0x06, 0x06, 0x03, 0x03, 0x03, 0x63, 0x73, 0x33, 0x3B, 0xFF, 0xFF, 0x7F,\r\n0x3F, 0x38, 0xF0, 0xC0, 0x00, 0xF0, 0xF8, 0x3F, 0x7F, 0xFF, 0xFF, 0x3B, 0x33, 0x63, 0x63, 0x03,\r\n0x03, 0x03, 0x06, 0x06, 0x0F, 0x0F, 0x06, 0x00\r\n};\r\n\r\n\r\n// Opening artwork created by @senkunmusahi using https://www.riyas.org/2013/12/online-led-matrix-font-generator-with.html\r\nconst byte PROGMEM openScreen[] = {\r\n    57,35,\r\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r\n    0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00,\r\n    0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x00,\r\n    0x00,0x00,0x0f,0xe0,0x00,0x00,0x00,0x00,\r\n    0x00,0x00,0x07,0xfc,0x00,0x00,0x00,0x00,\r\n    0x00,0x00,0x03,0xff,0xe0,0x00,0x00,0x00,\r\n    0x00,0x00,0xff,0xff,0xf8,0x00,0x00,0x00,\r\n    0x00,0x00,0x7f,0xff,0xfc,0x00,0x00,0x00,\r\n    0x00,0x00,0x1f,0xff,0xe0,0x00,0x00,0x00,\r\n    0x00,0x80,0x07,0xff,0xfc,0x20,0x00,0x00,\r\n    0x00,0xe0,0x0f,0xff,0xfc,0x30,0x00,0x00,\r\n    0x00,0xf0,0x00,0x7f,0xfe,0x30,0x00,0x00,\r\n    0x00,0x78,0x00,0x7f,0xbf,0x78,0x00,0x00,\r\n    0x00,0x0b,0xf0,0xff,0x7f,0x78,0x00,0x00,\r\n    0x00,0x3b,0xff,0xfe,0xff,0x78,0x00,0x00,\r\n    0x00,0xff,0xff,0xfd,0xff,0xfc,0x00,0x00,\r\n    0x00,0x0e,0x8f,0xfb,0xff,0xfc,0x00,0x00,\r\n    0x00,0x09,0x87,0xf7,0xff,0xfe,0x00,0x00,\r\n    0x00,0x7a,0x37,0xff,0xff,0xfe,0x00,0x00,\r\n    0x00,0x62,0x37,0xff,0xff,0xff,0x00,0x00,\r\n    0x00,0xc2,0x07,0xff,0xff,0xff,0x00,0x00,\r\n    0x00,0x02,0x07,0xff,0xff,0xff,0x80,0x00,\r\n    0x00,0x02,0x0f,0xff,0xfb,0xff,0xc0,0x00,\r\n    0x00,0x01,0x0f,0x0f,0xf1,0xff,0xc0,0x00,\r\n    0x00,0x00,0x9e,0x07,0xe0,0xff,0xe0,0x00,\r\n    0x00,0x00,0x7c,0x63,0xe0,0xff,0xe0,0x00,\r\n    0x00,0x00,0x78,0x63,0xf0,0xde,0xf0,0x00,\r\n    0x00,0x00,0x78,0x01,0xf0,0xde,0x30,0x00,\r\n    0x00,0x00,0x7c,0x01,0x78,0x8e,0x10,0x00,\r\n    0x00,0x00,0x3e,0x02,0x38,0x0e,0x00,0x00,\r\n    0x00,0x00,0x02,0x02,0x7e,0x06,0x00,0x00,\r\n    0x00,0x00,0x03,0x0c,0x7f,0x02,0x00,0x00,\r\n    0x00,0x00,0x00,0xf0,0xc9,0x02,0x00,0x00,\r\n    0x00,0x00,0x00,0x01,0xcd,0x80,0x00,0x00\r\n  };\r\n  \r\n// Display functions - a legacy from the AttinyArcade version - could be replaced with GameBuino function calls if you wish\r\nvoid lcdDisplay_send_byte(uint8_t byte);\r\nvoid lcdDisplay_setpos(uint8_t x, uint8_t y);\r\nvoid lcdDisplay_fillscreen(uint8_t fill_Data);\r\nvoid lcdDisplay_char_f6x8(uint8_t x, uint8_t y, const char ch[]);\r\n\r\n// Other generic functions for games (both originated in code from webboggles.com)\r\nvoid doNumber (int, int, int);\r\nvoid beep(int,int);\r\n\r\nvoid displayTitle(void) {\r\n  int incr = 0;\r\n  for(int lxn = 0; lxn < 5; lxn++) {\r\n    lcdDisplay_setpos(84,lxn); \r\n    for(int lxn2 = 0; lxn2 < 40; lxn2++) {\r\n      lcdDisplay_send_byte(pgm_read_byte(&titleBmp[incr]));      \r\n      incr++;\r\n    }\r\n  }\r\n}\r\n\r\nvoid beep(int bCount,int bDelay){\r\n  if (mute) return;\r\n  for (int i = 0; i<=bCount; i++){\r\n    digitalWrite(3,HIGH);\r\n    for(int i2=0; i2<bDelay; i2++){\r\n      __asm__(\"nop\\n\\t\"); // 62.5ns delay @ 16MHz\r\n      }\r\n    digitalWrite(3,LOW);\r\n    for(int i2=0; i2<bDelay; i2++) {\r\n      __asm__(\"nop\\n\\t\"); // 62.5ns delay @ 16Mhz\r\n    }\r\n  }\r\n}\r\n\r\n// Arduino stuff - setup\r\nvoid setup() {\r\n  // initialize the Gamebuino object\r\n  gb.begin();\r\n  //display the main menu:\r\n  //gb.titleScreen(F(\"FROGGER\"),openScreen);\r\n  gb.titleScreen(openScreen);\r\n}\r\n\r\nvoid displayOpenScreen(int incr) {\r\n    lcdDisplay_fillscreen(1);\r\n    if (incr < 99) screenLeft = incr;\r\n    \r\n    lcdDisplay_char_f6x8(0, 1, \"F R O G G E R\");\r\n    lcdDisplay_char_f6x8(0, 3, \"andy jackson\");\r\n    lcdDisplay_char_f6x8(64, 5, \"Press A...\");\r\n\r\n    lcdDisplay_setpos(0, 0);\r\n    for (int incr2 = 0; incr2 < 76; incr2++) {\r\n      lcdDisplay_send_byte(B00111000);\r\n    }\r\n    \r\n    lcdDisplay_setpos(0, 2);\r\n    for (int incr2 = 0; incr2 < 76; incr2++) {\r\n      lcdDisplay_send_byte(B00011100);\r\n    }\r\n\r\n    displayTitle();\r\n}\r\n\r\n// Arduino stuff - loop\r\nvoid loop() {\r\n  lcdDisplay_fillscreen(1);\r\n  int sChange = 0;\r\n\r\n  screenLeft = 0;\r\n  screenTop = 0;\r\n  \r\n  if (gb.buttons.pressed(BTN_B) == true) {\r\n      sChange = 1;     \r\n      EEPROM.write(0,0);\r\n      EEPROM.write(1,0);\r\n      lcdDisplay_char_f6x8(0, 0, \"--------------\");\r\n      lcdDisplay_char_f6x8(0, 1, \"HI SCORE RESET\");\r\n      lcdDisplay_char_f6x8(0, 3, \"--------------\");\r\n      while(!gb.update());\r\n      delay(2000);\r\n  }\r\n  \r\n  if (sChange == 0) {\r\n\r\n    lcdDisplay_fillscreen(1);\r\n\r\n    playFrogger();\r\n\r\n    screenLeft = 0;\r\n    screenTop = 0;\r\n\r\n    topScore = EEPROM.read(0);\r\n    topScore = topScore << 8;\r\n    topScore = topScore |  EEPROM.read(1);\r\n\r\n    newHigh = 0;\r\n    if (score > topScore) {\r\n      topScore = score;\r\n      EEPROM.write(1, score & 0xFF);\r\n      EEPROM.write(0, (score >> 8) & 0xFF);\r\n      newHigh = 1;\r\n    }\r\n\r\n    screenLeft = 0;\r\n\r\n    lcdDisplay_fillscreen(0x00);\r\n    lcdDisplay_char_f6x8(0, 0, \"------------\");\r\n    lcdDisplay_char_f6x8(0, 1, \"GAME  OVER\");\r\n    lcdDisplay_char_f6x8(0, 3, \"------------\");\r\n    showScore();\r\n    while(!gb.update());\r\n    delay(2500);\r\n    lcdDisplay_fillscreen(0x00);\r\n    lcdDisplay_char_f6x8(0, 0, \"---------------\");\r\n    lcdDisplay_char_f6x8(0, 3, \"---------------\");\r\n    doNumber(24, 2, topScore);\r\n    if (!newHigh) {\r\n      lcdDisplay_char_f6x8(0, 1, \"HIGH SCORE:\");\r\n    } else {\r\n      lcdDisplay_char_f6x8(0, 1, \"NEW HIGH:\");\r\n      for (int i = 700; i>200; i = i - 50){\r\n        beep(30,i);\r\n      }\r\n    }\r\n    while(!gb.update());\r\n    delay(2500);\r\n  }\r\n\r\n  lcdDisplay_fillscreen(1);\r\n  gb.display.update();\r\n\r\n  while(gb.buttons.pressed(BTN_A) == true) { while(!gb.update()); delay(5);}\r\n\r\n  gb.sound.playNote(63,1,0);\r\n  while(!gb.update());\r\n  \r\n  screenLeft = 0;\r\n  for (int incr = 0; incr < 46 ; incr+=3) {\r\n    displayOpenScreen(incr);\r\n    gb.display.update();\r\n    if (incr == 0) delay(1700);\r\n  }\r\n\r\n  while(gb.buttons.pressed(BTN_A) == false && gb.buttons.pressed(BTN_B) == false ) {\r\n    displayOpenScreen(100);    \r\n    while(!gb.update());\r\n  }\r\n\r\n}\r\n\r\nvoid doNumber (int x, int y, int value) {\r\n  char temp[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\r\n  itoa(value, temp, 10);\r\n  lcdDisplay_char_f6x8(x, y, temp);\r\n}\r\n\r\nvoid showScore(void) {\r\n  lcdDisplay_char_f6x8(0, 2, \"SCORE:\");\r\n  doNumber(44, 2, score);\r\n}\r\n\r\nvoid lcdDisplay_send_byte(uint8_t input) {\r\n  uint8_t *disp;\r\n\r\n  disp = gb.display.getBuffer();\r\n\r\n  if ( (currentX >= screenLeft) && (currentX < screenLeft + 84) && (currentY >= screenTop) && (currentY <= screenTop + 5)) {\r\n    *(disp + currentX - screenLeft + ((currentY - screenTop) * 84)) = input;\r\n  }\r\n  currentX++;\r\n}\r\n\r\nvoid lcdDisplay_setpos(uint8_t x, uint8_t y)\r\n{\r\n  currentX = x;\r\n  currentY = y;\r\n}\r\n\r\nvoid lcdDisplay_fillscreen(uint8_t fill_Data) {\r\n  gb.display.setColor(WHITE, BLACK);\r\n\r\n  for (int i = 0; i < 64; i++) {\r\n    for (int j = 0; j < 128; j++) {\r\n      gb.display.drawPixel(j, i);\r\n    }\r\n  }\r\n\r\n}\r\n\r\nvoid lcdDisplay_char_f6x8(uint8_t x, uint8_t y, const char ch[]) {\r\n  uint8_t c, i, j = 0;\r\n  while (ch[j] != '\\0')\r\n  {\r\n    c = ch[j] - 32;\r\n    if (c > 0) c = c - 12;\r\n    if (c > 15) c = c - 6;\r\n    if (c > 40) c = c - 9;\r\n    if (x > 126)\r\n    {\r\n      x = 0;\r\n      y++;\r\n    }\r\n    lcdDisplay_setpos(x, y);\r\n    for (i = 0; i < 6; i++)\r\n    {\r\n      lcdDisplay_send_byte(pgm_read_byte(&lcdDisplayxled_font6x8[c * 6 + i]));\r\n    }\r\n    x += 6;\r\n    j++;\r\n  }\r\n}\r\n\r\n/* ------------------------\r\n *  Frogger main game code\r\n */\r\nvoid playFrogger(){\r\n  stopAnimate = 0;\r\n  score = 0;\r\n  moveDelay = MOVEBASE;\r\n  level = 1;\r\n  frogColumn = 8;\r\n  frogRow = 7;\r\n  clickLock = 0;\r\n  frogMode = 1;\r\n  interimStep =0;\r\n  blockShiftL = 0;\r\n  blockShiftR = 0;\r\n  flipFlop = 1;\r\n  flipFlopShift = 1;\r\n  dockedFrogs = 0;\r\n  lives = 2;\r\n  frogRightLimit = 12;\r\n  watchDog = 1; // we use this to see if there's been movement - it's only ever zero when the frog has just moved!\r\n\r\n  initScreen();\r\n  resetDock(0);\r\n\r\n  drawFrog(frogMode,0);\r\n  drawLives();\r\n  \r\n  doNumber(0,7,score);\r\n\r\n  drawGameScreen(frogMode);\r\n  drawDocks();\r\n\r\n  screenLeft = 0;\r\n  screenTop = 0;\r\n  \r\n  while(!gb.update());\r\n  while (lives >= 0) {\r\n    drawFrog(frogMode,0);\r\n    drawLives();\r\n    doNumber(0,7,score);  \r\n    drawGameScreen(frogMode);\r\n    drawDocks();\r\n    \r\n  \r\n    if (frogColumn*8 < screenLeft + 40) screenLeft--;\r\n    if (frogColumn*8 > screenLeft + 50) screenLeft++;\r\n    if (frogColumn*8 < screenLeft + 15) screenLeft--;\r\n    if (frogColumn*8 > screenLeft + 60) screenLeft++;\r\n\r\n    /*\r\n    if (frogRow == 1 || frogRow == 3) {\r\n      screenLeft = frogColumn*8 - 30 - blockShiftL;\r\n    } else if (frogRow == 2) {\r\n      screenLeft = frogColumn*8 - 30 + blockShiftR;\r\n    } else {\r\n      screenLeft = frogColumn*8 - 30;\r\n    }\r\n    */\r\n    \r\n    screenTop =  frogRow - 3;\r\n\r\n    if (screenLeft < 0) screenLeft = 0;\r\n    if (screenTop < 0) screenTop = 0;\r\n    if (screenLeft > 43) screenLeft = 43;\r\n    if (screenTop > 2) screenTop = 2;\r\n    \r\n    while(!gb.update());\r\n    interimStep++;\r\n\r\n    if (watchDog >= 500) lives = -1; // Stop the game if nothing's happening - maybe triggered in someone's pocket so this is to save battery!\r\n    \r\n    // Calculate left limit of frog movement so it doesn't hit the score\r\n    frogLeftLimit = 1;\r\n    if ((score / 10) % 10 != 0) frogLeftLimit++; \r\n    if ((score / 100) % 10 != 0) frogLeftLimit++;\r\n    if ((score / 1000) % 10 != 0) frogLeftLimit++;\r\n\r\n    // Move stuff along if it's time to\r\n    //if (interimStep > moveDelay/8) {\r\n      watchDog++;\r\n      blockShiftL++;\r\n      if (flipFlopShift == 1) flipFlopShift = 0; else flipFlopShift = 1;\r\n      if (flipFlopShift == 1) blockShiftR++;\r\n      if (blockShiftL == 7) {\r\n        moveBlocks();\r\n        blockShiftL = 0;\r\n      }\r\n      if (blockShiftR == 7) {\r\n        blockShiftR = 0;\r\n      }\r\n      interimStep = 0;\r\n      checkCollision();\r\n      /*\r\n      if (stopAnimate == 0) {\r\n        drawGameScreen(frogMode);\r\n        drawFrog(frogMode,0);\r\n      }\r\n      */\r\n    //}\r\n\r\n    // Handle input \r\n    if (gb.buttons.pressed(BTN_UP) == true && clickLock == 0) {\r\n      moveForward = 1;\r\n      watchDog = 0;   // reset the watchdog so the game doesn't end!\r\n      clickLock = 1;\r\n      clickBase = millis();\r\n    }\r\n\r\n    if (gb.buttons.pressed(BTN_DOWN) == true && clickLock == 0) {\r\n      moveBack = 1;\r\n      watchDog = 0;   // reset the watchdog so the game doesn't end!\r\n      clickLock = 1;\r\n      clickBase = millis();\r\n    }\r\n\r\n    if (gb.buttons.pressed(BTN_LEFT) == true && clickLock == 0) {\r\n      moveLeft = 1;\r\n      watchDog = 0;   // reset the watchdog so the game doesn't end!\r\n      clickLock = 1;\r\n      //clickBase = millis();\r\n    }\r\n\r\n    if (gb.buttons.pressed(BTN_RIGHT) == true && clickLock == 0) {\r\n      moveRight = 1;\r\n      watchDog = 0;   // reset the watchdog so the game doesn't end!\r\n      clickLock = 1;\r\n      //clickBase = millis();\r\n    }\r\n\r\n    // Handle moving left\r\n//    if(moveLeft == 1 && millis() > clickBase + CLICKDELAY/2) {\r\n    if(moveLeft == 1) {\r\n      watchDog = 0;   // reset the watchdog so the game doesn't end!\r\n      moveLeft = 0;\r\n      drawFrog(0,0);  // delete the frog\r\n      // move the frog, checking it isn't jumping off the edge of the screen\r\n      if ((frogRow == 7 && frogColumn > frogLeftLimit) || (frogRow < 7 && frogColumn > 0)) {\r\n        frogColumn --;\r\n      } else if (frogRow < 7) stopAnimate = 1;\r\n      frogMode = 2; // pointing left\r\n    }\r\n\r\n    // Handle moving right\r\n//    if(moveRight == 1 && millis() > clickBase + CLICKDELAY/2){\r\n    if(moveRight == 1){\r\n      watchDog = 0;   // reset the watchdog so the game doesn't end!\r\n      moveRight = 0;\r\n      drawFrog(0,0); // delete the frog\r\n      // move the frog, checking it isn't jumping off the edge of the screen\r\n      if ((frogRow == 7 && frogColumn < frogRightLimit) || (frogRow < 7 && frogColumn < 14)) {\r\n        frogColumn ++;\r\n      } else if (frogRow < 7) stopAnimate = 1;\r\n      frogMode = 3; // pointing right    \r\n    }\r\n\r\n\r\n    // Handle 'move back' button press\r\n    if (moveBack == 1) {\r\n      moveBack = 0;\r\n      if (frogRow < 7) score-= level;          // decrement the score for every move back\r\n      if (frogRow < 7) {\r\n        // Correct for the skew in frog position created by the blockShift scrolling parameter\r\n        if (frogRow == 3 && blockShiftL < 4) frogColumn++;\r\n        if (frogRow == 2 && blockShiftR + blockShiftL < 5) frogColumn--;\r\n        if (frogRow == 1 && blockShiftR + blockShiftL < 5) frogColumn++;\r\n        frogRow++; \r\n        frogMode = 4;             // mode 1 = forwards position              \r\n      }\r\n    }\r\n\r\n    // Handle 'move forward' button press\r\n    if (moveForward == 1) {\r\n      moveForward = 0;\r\n  \r\n      score+= level;          // increment the score for every move\r\n      doNumber(0,7,score);    // display new score\r\n      drawFrog(0,0);          // delete the frog\r\n  \r\n      if (frogRow > 1) {\r\n        frogRow--; \r\n        // Correct for the skew in frog position created by the blockShift scrolling parameter\r\n        if (frogRow == 3 && blockShiftL < 4) frogColumn--;\r\n        if (frogRow == 2 && blockShiftR + blockShiftL < 5) frogColumn++;\r\n        if (frogRow == 1 && blockShiftR + blockShiftL < 5) frogColumn--;\r\n                \r\n      } else {\r\n        // frog is at the docks!\r\n        if (blockShiftL < 4 && frogColumn <15) frogColumn++;  // account for skew due to block shifting\r\n        byte dockPos = (byte)floor(frogColumn/3);\r\n        if (frogDocks[dockPos] == 0 ) {\r\n          dockedFrogs++;          \r\n          frogDocks[dockPos] = 1;                             // assign this dock as filled\r\n          frogRow = 7;                                        // reposition the frog at the start\r\n          frogColumn = 8;\r\n          drawFrog(frogMode,0);\r\n          drawLives();\r\n          doNumber(0,7,score);  \r\n          drawGameScreen(frogMode);\r\n          drawDocks();\r\n          while(!gb.update());\r\n          for (int i = 1000; i>200; i = i - 100){             // make sound\r\n          beep(10,i);\r\n          }\r\n          delay(600);\r\n        } else stopAnimate = 1;\r\n      }\r\n      frogMode = 1;             // mode 1 = forwards position\r\n\r\n      // check if all docks are full - if so, then level up!\r\n      if (dockedFrogs >= 5) {\r\n        level++;\r\n        levelUp(level);\r\n        if (moveDelay > 99) moveDelay -=100; // make the game speed up \r\n        initScreen();                        // reinitalise the position of game items\r\n        resetDock(0);                        // reinitliase the dock\r\n        dockedFrogs = 0;              \r\n        drawDocks();                         // display the (now empty) docks\r\n        drawLives();                         // display the lives\r\n        doNumber(0,7,score);                 // display the score\r\n      }      \r\n    }\r\n\r\n    // The frog has moved \r\n    if (watchDog == 0 && stopAnimate == 0) {\r\n      watchDog = 1;               // set to something other than zero so this routine doesn't run again\r\n      // redraw the screen\r\n      drawGameScreen(frogMode);\r\n      // redraw the frog\r\n      drawFrog(frogMode,0);\r\n      // make jump sound\r\n      beep(30,400);\r\n      beep(30,300);\r\n      beep(30,200);\r\n    }\r\n    \r\n    checkCollision();\r\n    \r\n    //if (clickLock == 1 && millis() > clickBase + CLICKDELAY && digitalRead(2)==0 && digitalRead(0)==0 && analogRead(0) > 940) clickLock = 0; // normal debounce\r\n    clickLock = 0; // No Debounce\r\n\r\n    // check to see if the frog has been killed\r\n    if (stopAnimate != 0) {\r\n      // redraw the screen\r\n      drawGameScreen(frogMode);\r\n      // animation for frog death\r\n      drawGameScreen(frogMode);\r\n      drawDocks();\r\n      drawFrog(0,1);\r\n      while(!gb.update());\r\n      for (int i = 0; i<250; i = i+ 50){  \r\n        beep(50,i);\r\n      }\r\n      drawGameScreen(frogMode);\r\n      drawDocks();\r\n      drawFrog(frogMode,1);    \r\n      for (int i = 250; i<500; i = i+ 50){  \r\n        beep(50,i);\r\n      }\r\n      drawGameScreen(frogMode);\r\n      drawDocks();\r\n      drawFrog(0,1);\r\n      while(!gb.update());\r\n      for (int i = 500; i<750; i = i+ 50){  \r\n        beep(50,i);\r\n      }\r\n      drawGameScreen(frogMode);\r\n      drawDocks();\r\n      drawFrog(frogMode,1);\r\n      for (int i = 750; i<1000; i = i+ 50){  \r\n        beep(50,i);\r\n      }\r\n      while(!gb.update());\r\n      delay(600);\r\n      lives--;          // increment the score for every move\r\n      //frogRightLimit++; // there's one less frog drawn on right so you can move a bit further across (if you really want to!)\r\n      stopAnimate = 0;  // reset parameter\r\n      drawLives();      // display number of lives left\r\n      frogColumn = 8;   // reinitalise frog location\r\n      frogRow = 7;\r\n      while(!gb.update());\r\n      }\r\n  }  // Big while loop (main game loop) goes until lives is negative\r\n} \r\n\r\nvoid checkCollision(void) {\r\n  if (frogRow > 0 && frogRow < 4 && grid[frogRow-1][frogColumn] == 0) stopAnimate = 1; // the frog has fallen in the river\r\n  if (frogRow > 0 && frogRow < 4 && grid[frogRow-1][frogColumn] > 9) stopAnimate = 1; // the frog has stepped on a croc\r\n  if ((frogRow < 7 && frogRow > 3) && (grid[frogRow-1][frogColumn] != 0 || grid[frogRow-1][frogColumn-1] != 0)) stopAnimate = 1; // the frog has been hit by a vehicle\r\n}\r\n\r\n// Initialise all the moving objects on the game screen\r\nvoid initScreen(void) {\r\n  int initCounter[6] = {3,2,4,2,2,3};       // the length of the objects on each row - doesn't change\r\n  int gapCounter[6] = {-2,-3,-4,-4,-3,-5};  // the gaps between objects - change with levels to make it harder as you go thru the game\r\n  int counter[6];                           // used to hold the gap data\r\n  byte stepMode = 0;                        // which component of the object are we drawing (they all have three - a start a middle and an end)\r\n  byte stepShift = 0;                       // offset to shift up to the different objects in the array\r\n  byte crocStartColumn = 0;                 // column at which to stop drawing crocs - is zero at start hence no crocs!\r\n\r\n  \r\n  // Adjust difficulty by changing gaps between objects according to level\r\n  if (level == 1) {\r\n    gapCounter[5] = -14;           // easiset setting, for start of game\r\n  }\r\n  if (level < 3) {\r\n    gapCounter[4] = -6;            // make it easier for levels less than 3 by increasing the gap in the cars on this row\r\n  }\r\n  if (level < 4) {\r\n    gapCounter[3] = -7;\r\n  }\r\n  if (level > 4) {\r\n    for (byte incr = 1; incr < 3; incr++) {\r\n      gapCounter[incr]--;         // increase the gaps between the logs for levels over 4  \r\n    }\r\n  }\r\n  if (level > 7) {                // set smaller gaps between cars for levels over 7\r\n    gapCounter[3] = -4; \r\n    gapCounter[4] = -2;\r\n    gapCounter[5] = -3;\r\n  }\r\n  if (level > 2) crocStartColumn = 5; // one croc appears at level 3 and above\r\n  if (level > 6) crocStartColumn = 9; // two croc appear at level 7 and above\r\n  \r\n  // Initialise the counters\r\n  for (byte incr = 0; incr < 6;incr++) counter[incr] = initCounter[incr];  \r\n\r\n  // Initialise array with zeros\r\n  for (byte col = 0; col < 16; col++) {\r\n    for (byte row = 0; row < 6; row++) {\r\n      grid[row][col] = 0;\r\n    }\r\n  }\r\n       \r\n  stepMode = 0;\r\n  // Initialise array with obstacles\r\n  for (byte row = 0; row < 6; row++) {\r\n    for (byte col = 0; col < 15; col++) {         \r\n      if (counter[row] > 0) {\r\n        if (14-row > counter[row]) {\r\n          if (counter[row] == 1) if (stepMode == 1) stepMode = 2; // the next space is blank and we are drawing the middle - draw the end! \r\n          if (row > 2) stepShift = 3; else stepShift = 0;         // shift up to the trucks in the array\r\n          if (row == 4) stepShift = 9;                            // shift up to the cars in the array - also theres no middle\r\n          \r\n          if (row > 0) {\r\n            grid[row][col] = 5+stepMode+stepShift;                // if you are on any row but the first - draw whatever is appropriate from the bitmaps\r\n          } else if (col >= crocStartColumn) {                    \r\n            grid[row][col] = 5+stepMode+stepShift;                // if you're on row zero (top row of logs) and you are above where crocs should be drawm, draw logs ...\r\n          } else grid[row][col] = 11+stepMode;                    // .. otherwise draw crocs\r\n          if (stepMode == 0) stepMode = 1;                        // we've drawn the left side now switch to central sections\r\n          if (stepMode == 2) stepMode = 0;                        // we've drawn the end, now reset\r\n        }\r\n      } \r\n      counter[row]--;                                             // decrement the counter\r\n      if (counter[row] <= gapCounter[row]) {\r\n        counter[row] = initCounter[row];                          // if we have gone negative enough to account for the gaps - reset the counter and start again\r\n      }\r\n    }\r\n  }\r\n}\r\n\r\n// Display the frog\r\nvoid drawFrog(byte mode, bool frogDead) {\r\n  if (frogRow > 6 || frogRow < 1 || frogDead == 1) {           // don't draw the frog when it's on the road or on logs - because they are moving, that's handled in the main drawing routine below- exception is when you are animating frog death\r\n    if (frogRow == 1 || frogRow == 3) {                        // these allow for the blocks being shifted when animating the frog death on rows with logs\r\n      lcdDisplay_setpos(frogColumn*8 + 7 - blockShiftL,frogRow);\r\n    } else if (frogRow == 2) {\r\n      lcdDisplay_setpos(frogColumn*8 + blockShiftR,frogRow);      \r\n    } else {\r\n      lcdDisplay_setpos(frogColumn*8,frogRow); \r\n    }\r\n    sendBlock(mode,0);                   // draw the frog - mode is direction\r\n  }    \r\n}\r\n\r\n// Display the frog and all the moving items on the screen\r\nvoid drawGameScreen(byte mode) {\r\n  bool inverse = 0;\r\n  \r\n  // Draw objects going left\r\n  for (byte row = 0; row < 6; row+=2) {\r\n    if (row >=0 && row < 3) inverse = 1; else inverse = 0;                              // draw everything (except the frog) in inverse video on the river rows (0,1,2)\r\n    lcdDisplay_setpos(0,row+1);                                                            // +1 because row 0 here is actually row 1 on the screen\r\n    for (byte incr = 0; incr < 7-blockShiftL; incr++) if (grid[row][15] == 0) {         // cover the tiny bit to the far left of the screen up to wherever the main blocks will be drawn (depends on how far they are shifted)\r\n      sendByte(0,inverse);                                                              // draw an empty 8-bit line if there's nothing wrapping around\r\n    } else {\r\n      sendByte(pgm_read_byte(&bitmaps[grid[row][15]-1][1+blockShiftL+incr]), inverse);  // pick the correct bit of whatever is wrapping from the right of the screen\r\n    }\r\n    for (byte col = 0; col < 15; col++) {         \r\n      if (frogRow == row+1 && frogColumn == col && frogRow < 4 && frogRow > 0) {\r\n        sendBlock(mode,0);                                                                          // if we are in a location with the frog, and it's on the logs, draw it - never invert it (hence zero as second parameter here)\r\n      } else if (stopAnimate == 0 && frogRow == row+1 && frogColumn == col + 1 && frogRow > 3 && frogRow < 7) {         // frog is amongst the cars and needs drawing\r\n        for (byte incr = 0; incr < blockShiftL; incr++) sendByte(0,0);                              // draw the blank space up to the frog\r\n        sendBlock(mode,0);                                                                          // draw frog\r\n        for (byte incr = 0; incr < 7-blockShiftL; incr++) sendByte(0,0);                            // draw the blank space after the frog\r\n        col++;                                                                                      // we've now drawn two columns so increment\r\n      } else {\r\n        sendBlock(grid[row][col],inverse);                                                          // draw the correct object for this space - it's not a frog ;)\r\n      }\r\n    }\r\n    // fill in the bit to the right of the main blocks \r\n    for (byte incr = 0; incr < blockShiftL; incr++) if (grid[row][15] == 0) sendByte(0,inverse); else sendByte(pgm_read_byte(&bitmaps[grid[row][15]-1][incr]),inverse);\r\n\r\n  }\r\n  if (frogColumn == 0) drawFrog(mode,1); // this covers the exceptional case where the frog is in the far left colum, in which case the normal routine can't draw it when it's on the road\r\n  \r\n  // Draw objects going right - see comments above, works in basically the same way\r\n  for (byte row = 1; row < 6; row+=2) {\r\n    if (row > 0 && row < 3) inverse = 1; else inverse = 0;\r\n    lcdDisplay_setpos(0,row+1);\r\n    for (byte incr = 0; incr < blockShiftR; incr++) if (grid[row][15] == 0) sendByte(0, inverse); else sendByte(pgm_read_byte(&bitmaps[grid[row][15]-1][incr+(8-blockShiftR)]),inverse);\r\n    for (byte col = 0; col < 15; col++) {         \r\n      if (frogRow == row+1 && frogColumn == col && frogRow < 4 && frogRow > 0) {\r\n        sendBlock(mode,0);    \r\n      } else if (stopAnimate == 0 && frogRow == row+1 && frogColumn == col + 1 && frogRow > 3 && frogRow < 7) {  \r\n        for (byte incr = 0; incr < 7-blockShiftR; incr++) sendByte(0,0);\r\n        sendBlock(mode,0); // draw frog\r\n        for (byte incr = 0; incr < blockShiftR; incr++) sendByte(0,0);\r\n        col++;        \r\n      } else {\r\n        sendBlock(grid[row][col],inverse);        \r\n      }\r\n    }\r\n    for (byte incr = 0; incr < 7-blockShiftR; incr++) if (grid[row][15] == 0) sendByte(0,inverse); else sendByte(pgm_read_byte(&bitmaps[grid[row][15]-1][incr]),inverse);\r\n  }\r\n  if (frogColumn == 0) drawFrog(mode,1);\r\n}\r\n\r\n// Send one byte to the screen\r\nvoid sendByte(byte fill, bool inverse) {\r\n  if (inverse == 0) lcdDisplay_send_byte(fill); else lcdDisplay_send_byte(~fill);\r\n}\r\n\r\n// Send one block of 8 bytes to the screen - inverse means inverse video, for the river section\r\nvoid sendBlock(byte fill, bool inverse){\r\n  for (int incr = 0; incr < 8; incr++) {\r\n    if (fill > 0) {\r\n      if (inverse == 0) lcdDisplay_send_byte(pgm_read_byte(&bitmaps[fill-1][incr])); else lcdDisplay_send_byte(~pgm_read_byte(&bitmaps[fill-1][incr]));  \r\n    } else if (inverse ==0) lcdDisplay_send_byte(0); else lcdDisplay_send_byte(0xFF); \r\n  }\r\n}\r\n\r\n// Draw the frog lives (in the right hand corner)\r\nvoid drawLives(void) {\r\n  byte tempRow = frogColumn;\r\n  byte tempCol = frogRow;\r\n  frogRow = 7;\r\n\r\n  for (int incr = 2; incr > 0; incr--) {\r\n    frogColumn = 15-incr;\r\n    drawFrog(0,1);\r\n  }\r\n\r\n  for (int incr = lives; incr > 0; incr--) {\r\n    frogColumn = 15-incr;\r\n    drawFrog(1,1);\r\n  }\r\n  frogRow = tempCol;\r\n  frogColumn = tempRow;    \r\n}\r\n\r\n// Draw the docks for the frog to land in at top of screen\r\nvoid drawDocks(void) {\r\n  byte drawPos = 3;\r\n  for (byte incr = 0; incr < 5; incr++) {\r\n    lcdDisplay_setpos(drawPos,0);\r\n    lcdDisplay_send_byte(B11111111);\r\n    lcdDisplay_send_byte(B00000001);\r\n    lcdDisplay_send_byte(B00000001);\r\n    if (frogDocks[incr] == 1) sendBlock(1,0); else for(byte lxn = 0; lxn < 8; lxn++) lcdDisplay_send_byte(B00000001);\r\n    lcdDisplay_send_byte(B00000001);\r\n    lcdDisplay_send_byte(B00000001);\r\n    lcdDisplay_send_byte(B11111111);\r\n    drawPos+= 24;\r\n    }    \r\n}\r\n\r\n// Set all the frog docks to a single value\r\nvoid resetDock(byte value) {   for (byte incr = 0; incr < 5;incr++) frogDocks[incr] = value; }\r\n\r\n// Handle what happens at the end of a level\r\nvoid levelUp(int number) {  \r\n  // Flash the frog docks\r\n  screenLeft = 0;\r\n  screenTop = 0;\r\n\r\n  delay(200);\r\n  for (byte incr = 0; incr < 5; incr ++) {\r\n    resetDock(0);\r\n    drawDocks();\r\n    drawGameScreen(frogMode);\r\n    while(!gb.update());\r\n    for (int i = 800; i>200; i = i - 200){\r\n    beep(20,i);\r\n    }\r\n    resetDock(1);\r\n    drawDocks();\r\n    drawGameScreen(frogMode);\r\n    while(!gb.update());\r\n    for (int i = 800; i>200; i = i - 200){\r\n    beep(20,i);\r\n    }\r\n  }  \r\n  delay(500);\r\n  lcdDisplay_fillscreen(0x00);  \r\n  lcdDisplay_char_f6x8(14, 1,  \"---------\");\r\n  lcdDisplay_char_f6x8(14, 2, \"  LEVEL  \");\r\n  lcdDisplay_char_f6x8(14, 4, \"---------\");\r\n  doNumber(32, 3, level);\r\n  while(!gb.update());\r\n  delay(1500);    \r\n  lcdDisplay_fillscreen(0x00);\r\n  while(!gb.update());\r\n}\r\n\r\n// Move all the items on the game screen (wrapping at the ends) and check for frog dropping off the end of the screen\r\nvoid moveBlocks(void) {\r\n  int direct = 0;\r\n\r\n  if (flipFlop == 1) flipFlop = 0; else flipFlop = 1;\r\n  \r\n  for (byte row = 0; row < 6; row++) {\r\n    // Move the frog along and check to see whether it's gone off the screen, in which case it dies\r\n    if (frogRow < 4 && frogRow > 0) { \r\n      if (frogRow == row + 1) {\r\n        if (direct == 1 && flipFlop == 1) {\r\n          if (frogColumn >= 14) stopAnimate = 1; else frogColumn++; \r\n        } else if (direct == 0) {\r\n          if (frogColumn < 1) stopAnimate = 1; else frogColumn--;\r\n        }\r\n      }  \r\n    }\r\n    if (direct == 0) { // move left\r\n      byte temp = grid[row][0];\r\n      for (byte col = 0; col < 15; col++) {         \r\n        grid[row][col] = grid[row][col+1];\r\n      }\r\n      grid[row][15] = temp; // wrap around\r\n      direct = 1;\r\n    } else { // move right\r\n      if (flipFlop == 1) {\r\n        byte temp = grid[row][15];\r\n        for (byte col = 15; col > 0; col--) {         \r\n          grid[row][col] = grid[row][col-1];\r\n          }\r\n        grid[row][0] = temp; // wrap around\r\n        }\r\n      direct = 0;  \r\n      }\r\n    }\r\n  }\r\n"
  },
  {
    "path": "Frogger_MAKERbuino/HEX and INF/FROGGER.HEX",
    "content": ":100000000C94C1030C94E9030C94E9030C94E903E8\r\n:100010000C94E9030C94E9030C94E9030C94E903B0\r\n:100020000C94E9030C94E9030C94E9030C944A063C\r\n:100030000C94E9030C94E9030C94E9030C94E90390\r\n:100040000C94F5050C94E9030C94E9030C94E90372\r\n:100050000C94E9030C94E9030C94E9030C94E90370\r\n:100060000C94E9030C94E9030101FF030101F70378\r\n:100070006C00680000000000240027002A00000037\r\n:100080000000250028002B000500893008023802F6\r\n:100090004978681400000500380168010000175312\r\n:1000A00044001613780016131400151020001520B4\r\n:1000B0001000540A03E181867F3E186D830F0F0EF6\r\n:1000C0000183866033186DC3198F1803C38E6033A4\r\n:1000D000186DE330CF1803C39E603630CDE360CF98\r\n:1000E0003006C79E7E3E30CDB360CF300CC6F66082\r\n:1000F0003330D9B660CF33CFCCF66061B0DB1E6051\r\n:10010000CF30D86CE6C061B0DB1E618F19986CC629\r\n:10011000C063B19B0E330F0FB078C6FF7E1F1B0666\r\n:100120001E0F003923000000000000000000000046\r\n:100130000000000000000070000000000000003E11\r\n:10014000000000000000000FE000000000000007B9\r\n:10015000FC00000000000003FFE00000000000FFC2\r\n:10016000FFF800000000007FFFFC00000000001FFF\r\n:10017000FFE0000000008007FFFC20000000E00F0F\r\n:10018000FFFC30000000F0007FFE3000000078002F\r\n:100190007FBF780000000BF0FF7F780000003BFF7E\r\n:1001A000FEFF78000000FFFFFDFFFC0000000E8F47\r\n:1001B000FBFFFC0000000987F7FFFE0000007A3714\r\n:1001C000FFFFFE0000006237FFFFFF000000C207D4\r\n:1001D000FFFFFF0000000207FFFFFF800000020F8B\r\n:1001E000FFFBFFC00000010F0FF1FFC00000009EE9\r\n:1001F00007E0FFE00000007C63E0FFE00000007823\r\n:1002000063F0DEF00000007801F0DE300000007CDA\r\n:1002100001788E100000003E02380E00000000023F\r\n:10022000027E0600000000030C7F020000000000B8\r\n:10023000F0C902000000000001CD800000000000B5\r\n:10024000000000000080C0F07C06735943063C3873\r\n:100250003030383E267B5943067CF0C080000000D9\r\n:10026000000000000000000000000078FFCF010047\r\n:10027000003060E0C080808080808080C0C06030BE\r\n:1002800000000001CFFE780000000000007CFE8628\r\n:100290000E0E1C18317FFEFC1C18383838393939DD\r\n:1002A0003939393938383838181CFCFE7F39181C70\r\n:1002B0000E0EC6FE3C0001070E1C3870C0C0800345\r\n:1002C00007FCF80000F0C0C0C0C0C0E0F00000F8BB\r\n:1002D000FC0F0380C0E070381C0E03010004060F01\r\n:1002E0000F06060303036373333BFFFF7F3F38F0C2\r\n:1002F000C000F0F83F7FFFFF3B3363630303030657\r\n:10030000060F0F06000000000000000000080808AB\r\n:1003100000000060600000002010080402003E5150\r\n:1003200049453E0000427F4000004261514946007D\r\n:100330002141454B31001814127F100027454545D7\r\n:1003400039003C4A4949300001710905030036492A\r\n:1003500049493600064949291E000036360000008A\r\n:100360007C1211127C007F49494936003E414141CF\r\n:1003700022007F4141221C007F49494941007F09F9\r\n:10038000090901003E4149497A007F0808087F00B9\r\n:1003900000417F4100002040413F01007F081422BE\r\n:1003A00041007F40404040007F020C027F007F04FC\r\n:1003B00008107F003E4141413E007F0909090600C7\r\n:1003C0003E4151215E007F091929460046494949AD\r\n:1003D000310001017F0101003F4040403F001F20EC\r\n:1003E00040201F003F4038403F00205454547800C4\r\n:1003F0007F4844443800384444442000384444484A\r\n:100400007F00385454541800087E0901020018A4D3\r\n:10041000A4A47C007F080404780000447D40000010\r\n:100420004080847D00007F102844000000417F4010\r\n:1004300000007C04180478007C0804047800384428\r\n:1004400044443800FC242424180018242418FC00F8\r\n:100450007C0804040800485454542000043F4440DD\r\n:1004600020003C4040207C001C2040201C003C40E0\r\n:1004700030403C004428102844001CA0A0A07C83ED\r\n:10048000DC7A3F3F7ADC8399BDDB7E7E3CE781816D\r\n:10049000E73C7E7EDBBD99C13B5EFCFC5E3BC13C24\r\n:1004A0007ED7B5ADBFFFEDADADFFB7F5BFB7ADEDD5\r\n:1004B000BDC3BDA5BD423C007F4155555555555561\r\n:1004C00055555555555555417F227F7F63221C4117\r\n:1004D00063466E7C7E7A3EBCFE7E3EBEBEFC7C7871\r\n:1004E00038383870606040001C22637F7F222222EF\r\n:1004F0003E3E7F6363221C223E3E7F6363221C4597\r\n:100500000068010000F6E8DBCFC3B8AEA49B928A76\r\n:10051000827B746E68625C57524E4945413E3A3761\r\n:1005200034312E2C29272523210A0A153A49676ED2\r\n:100530006F7265006D560A0A504C45415345205470\r\n:1005400055524E204F464620004C4F5720424154B2\r\n:100550005445525921200003053F213F1208120A39\r\n:10056000100A0E1C0E0C1E0C141A14161F161E1345\r\n:100570001E1E1B1E1E1F1E3F213F3A2F3A173D17FE\r\n:100580003F213F181F02040A041F0E04040E1F0A15\r\n:100590001F0A0E0E1F04110E2E252E2F2A2E26297D\r\n:1005A00029021F02081F08150E04040E150E15154A\r\n:1005B0001B151B040604040C0400000000170003B4\r\n:1005C00000031F0A1F16371A1904130A153A0003ED\r\n:1005D00000000E11110E000A040A040E040030007F\r\n:1005E0000404040010001804031F111F121F101D23\r\n:1005F000151711151F07041F17151D1F151D0101C4\r\n:100600001F1F151F17151F000A00003200040A11D2\r\n:100610000A0A0A110A040115020E11171E051E1FEF\r\n:10062000150A0E110A1F110E1F15111F05010E11BB\r\n:100630001D1F041F111F1108100F1F041B1F101076\r\n:100640001F061F1E040F0E110E1F09060E112E1F6E\r\n:10065000051A121509011F011F101F0F180F1F0C7B\r\n:100660001F1B041B031C03191513001F110304187F\r\n:10067000111F000201022020200001020C121E1F87\r\n:10068000120C0C12120C121F0C1A14041E05242A30\r\n:100690001E1F021C141D1020201D1F0814111F10E6\r\n:1006A0001E041E1E021C0C120C3E0A040C123E1EDE\r\n:1006B000040214160A020F120E101E0E100E1E084F\r\n:1006C0001E120C1226281E322A26041E21001F008C\r\n:1006D000211E040102013F213F172B152010204C41\r\n:1006E0004F4144455200172B16201314000A4E6F39\r\n:1006F0002053442063617264206F720A6E6F204C35\r\n:100700004F414445522E4845580A0A153A457869E2\r\n:1007100074001D20466C617368696E670A20206C46\r\n:100720006F616465722E2E2E0A0A444F4E275420A4\r\n:100730005455524E204F4646210000000000230031\r\n:100740002600290004040404040404040202020232\r\n:100750000202030303030303010204081020408084\r\n:100760000102040810200102040810200000000803\r\n:100770000002010000030407000000000000000068\r\n:10078000AA1F11241FBECFEFD8E0DEBFCDBF11E0FE\r\n:10079000A0E0B1E0ECE5F4E402C005900D92A03ACF\r\n:1007A000B107D9F724E0A0EAB1E001C01D92A53C51\r\n:1007B000B207E1F713E0C1ECD3E004C02197FE01DA\r\n:1007C0000E942122C03CD107C9F70E94BB150C949E\r\n:1007D0002C220C940000CF92DF92EF92FF920F93A5\r\n:1007E0001F93CF93DF936C017A018B01C0E0D0E0BF\r\n:1007F000CE15DF0589F0D8016D918D01D601ED91FF\r\n:10080000FC910190F081E02DC6010995892B11F42E\r\n:100810007E0102C02196ECCFC701DF91CF911F91DD\r\n:100820000F91FF90EF90DF90CF90089590912E025E\r\n:10083000292F30E0E0910F02F09110022E173F07B0\r\n:1008400024F1AF014D5A5F4F42175307F4F0409126\r\n:100850002D0250E060910D0270910E02461757076D\r\n:10086000A4F0DB011596A417B5077CF02E1B3F0BF7\r\n:10087000461B570B64E5649FF001659FF00D112442\r\n:10088000E20FF31FE55CFD4F80839F5F90932E0284\r\n:100890000895EF92FF920F931F93CF93DF93F82E5B\r\n:1008A000E62E88E0F89E80011124C8E0D0E0FF2009\r\n:1008B00061F0F801EC1BFD0BE158FB4FE11002C0A9\r\n:1008C000849108C08491809505C0E11002C080E049\r\n:1008D00001C08FEF0E941604219749F7DF91CF9155\r\n:1008E0001F910F91FF90EF900895611180950C94E6\r\n:1008F0001604089580E090E008950E942722833036\r\n:1009000081F028F4813099F08230A1F00895873089\r\n:10091000A9F08830B9F08430D1F4809180008F7DC7\r\n:1009200003C0809180008F7780938000089584B504\r\n:100930008F7702C084B58F7D84BD08958091B0000B\r\n:100940008F7703C08091B0008F7D8093B0000895B1\r\n:100950001F93CF93DF93282F30E0F901E459F84F2C\r\n:100960008491F901E85AF84FD491F901EC5BF84F02\r\n:10097000C491CC23C9F0162F81110E947F04EC2F63\r\n:10098000F0E0EE0FFF1FE258FF4FA591B4918FB733\r\n:10099000F894111105C09C91ED2FE095E92302C058\r\n:1009A000EC91ED2BEC938FBFDF91CF911F910895C8\r\n:1009B000CF93DF9390E0FC01E85AF84F2491FC01BB\r\n:1009C000EC5BF84F8491882361F190E0880F991FC8\r\n:1009D000FC01EC58FF4FC591D491FC01E258FF4F48\r\n:1009E000A591B491611109C09FB7F89488812095B1\r\n:1009F00082238883EC912E230BC0623061F49FB771\r\n:100A0000F8943881822F809583238883EC912E2B54\r\n:100A10002C939FBF06C08FB7F894E8812E2B2883B4\r\n:100A20008FBFDF91CF9108951F93CF93DF93182F3E\r\n:100A3000EB0161E00E94D804209711F460E004C04B\r\n:100A4000CF3FD10539F461E0812FDF91CF911F9124\r\n:100A50000C94A804E12FF0E0E459F84FE491E3305E\r\n:100A6000F9F048F4E130B9F0E230A1F584B58062E4\r\n:100A700084BDC8BD34C0E730E9F0E83019F1E43096\r\n:100A800049F580918000806280938000D0938B0034\r\n:100A9000C0938A0024C084B5806884BDC7BD1FC0D0\r\n:100AA00080918000806880938000D0938900C093FB\r\n:100AB000880015C08091B00080688093B000C0931A\r\n:100AC000B3000DC08091B00080628093B000C093ED\r\n:100AD000B40005C0C038D1050CF0B5CFAFCFDF9161\r\n:100AE000CF911F9108958E3008F08E5087708064EA\r\n:100AF00080937C0080917A00806480937A0080915A\r\n:100B00007A0086FDFCCF809178002091790090E0FA\r\n:100B1000922B08953FB7F894809135029091360258\r\n:100B2000A0913702B091380226B5A89B05C02F3F8F\r\n:100B300019F00196A11DB11D3FBFBA2FA92F982F03\r\n:100B40008827820F911DA11DB11DBC01CD0142E07E\r\n:100B5000660F771F881F991F4A95D1F708958F92C6\r\n:100B60009F92AF92BF92CF92DF92EF92FF926B0172\r\n:100B70007C010E948A054B015C01C114D104E1048F\r\n:100B8000F104F1F00E948A05DC01CB018819990972\r\n:100B9000AA09BB09883E9340A105B10570F321E085\r\n:100BA000C21AD108E108F10888EE880E83E0981E89\r\n:100BB000A11CB11CC114D104E104F10419F7DDCF6B\r\n:100BC000FF90EF90DF90CF90BF90AF909F908F906D\r\n:100BD00008952FB7F894609131027091320280919C\r\n:100BE0003302909134022FBF08951F920F920FB6D7\r\n:100BF0000F9211242F933F938F939F93AF93BF93A3\r\n:100C00008091310290913202A0913302B09134026E\r\n:100C10003091300223E0230F2D3720F40196A11DDF\r\n:100C2000B11D05C026E8230F0296A11DB11D20931A\r\n:100C300030028093310290933202A0933302B0933A\r\n:100C400034028091350290913602A0913702B09122\r\n:100C500038020196A11DB11D809335029093360292\r\n:100C6000A0933702B0933802BF91AF919F918F91BB\r\n:100C70003F912F910F900FBE0F901F90189580916C\r\n:100C80003B04882319F080913D0401C080E08093EB\r\n:100C9000B40008951F920F920FB60F9211242F9354\r\n:100CA0003F934F935F936F937F938F939F93AF93F4\r\n:100CB000BF93EF93FF9360913C04662321F18091F1\r\n:100CC0002F028F5F80932F02909139028917D8F0FD\r\n:100CD00090913B0481E0892780933B0410922F027E\r\n:100CE00080913A02882369F08091000193E4899F02\r\n:100CF000802D1124895B809300010E94ED21909347\r\n:100D00003D040E943F06FF91EF91BF91AF919F91EB\r\n:100D10008F917F916F915F914F913F912F910F90A4\r\n:100D20000FBE0F901F9018951F93CF93DF93EC0188\r\n:100D3000162FF89460E08F850E94A8048889181601\r\n:100D40001CF460E00E94A8041EBD00000DB407FE64\r\n:100D5000FDCF8EB5888918161CF461E00E94A804A6\r\n:100D60007894DF91CF911F910895EF92FF921F9396\r\n:100D7000CF93DF93EC018C858F5F8C878BE3E82E1C\r\n:100D800082E0F82E10E0612F6064CE010E9494068C\r\n:100D900060E8CE010E94940661E08F850E94A8045D\r\n:100DA000888918161CF460E00E94A80480E090E096\r\n:100DB000F701E80FF91F20812EBD00000DB407FEDA\r\n:100DC000FDCF2EB501968435910591F788891816C7\r\n:100DD0001CF461E00E94A8041F5F84E5E80EF11C8A\r\n:100DE000163089F660E4CE01DF91CF911F91FF901C\r\n:100DF000EF900C9494060F931F93CF93DF9300E032\r\n:100E000012E0C3E0C0932E0210922D028FEF0E94D9\r\n:100E1000160481E00E94160481E00E941604F80185\r\n:100E200081918F01882329F060E081E00E944904CC\r\n:100E300006C0D8E081E00E941604D150D9F781E0C5\r\n:100E40000E94160481E00E9416048FEF0E9416048F\r\n:100E5000C85ECB37B9F6DF91CF911F910F910895FE\r\n:100E6000909109022FEF290F263080F4662321F19B\r\n:100E7000913011F0933051F420910A02220F220F89\r\n:100E8000220F30910802231B295F0FC020910A0214\r\n:100E9000923041F43091070248E0249F300D112434\r\n:100EA000232F03C0220F220F220F20932E02909394\r\n:100EB0002D0260E00C9449040895FF920F931F9354\r\n:100EC000CF93DF9310910A020091090287E080938B\r\n:100ED00009028DE080930A0261E080E00E94300701\r\n:100EE0008EE080930A0261E080E00E943007C091AA\r\n:100EF0000502D09106028FE0F82E1C161D0654F450\r\n:100F00008F2D8C1B80930A0261E081E00E943007E4\r\n:100F10002197F3CF0093090210930A02DF91CF913A\r\n:100F20001F910F91FF9008954F925F926F927F9261\r\n:100F30008F929F92AF92BF92CF92DF92EF92FF92E9\r\n:100F40000F931F93CF93DF93182FAFEACA2EA1E020\r\n:100F5000DA2EC1E0D0E0B7E0AB2EB12C9C2F01E03F\r\n:100F60008C2F8150833008F000E010922E02909375\r\n:100F70002D02F12C2F2D30E0E0910802F0E0C501A8\r\n:100F80008E1B9F0B28173907A4F4D6018C91882358\r\n:100F900059F03196E20FF31FB8E08B9FE00DF11D81\r\n:100FA0001124E958FB4F8491602F0E947504F3943B\r\n:100FB000E1CF712C7E01E1E0EE1AF1084701F4E087\r\n:100FC000880C991CFA95E1F760910902262F30E010\r\n:100FD0002C173D0769F460900A02671009C08FEF73\r\n:100FE000860F833028F460E0812F0E94490441C0BD\r\n:100FF00040910C02872D90E0411131C02C173D0724\r\n:1010000071F520910A0230E0AC014F5F5F4F241769\r\n:10101000350729F56450633010F5612C8091080282\r\n:10102000681628F480E00E9416046394F7CF60E00D\r\n:10103000812F0E944904612C862D90E020910802A6\r\n:10104000A501421B5109841795072CF480E00E94EA\r\n:1010500016046394F1CF66246394670C0AC0880D6C\r\n:10106000991DFC01E056FE4F602F80810E944904CB\r\n:10107000672C77247394760C5EE0571508F0A4CFA4\r\n:10108000912CC701E4E0880F991FEA95E1F7DC0194\r\n:10109000A155BE4F7D01809108029816C0F4D7017A\r\n:1010A000EC91E11103C0602F80E00DC0F0E03197BA\r\n:1010B00073E0EE0FFF1F7A95E1F7E90DF11DE1589E\r\n:1010C000FB4F8491602F0E9475049394E4CF229685\r\n:1010D000B0E2CB0ED11CC730D10509F03FCF8091D3\r\n:1010E0000A02811104C061E0812F0E9430074FEB9A\r\n:1010F000C42E41E0D42EC2E0D0E058E0452E512C61\r\n:1011000067E0A62EB12C9C2F01E08C2F82508230FC\r\n:1011100008F000E010922E0290932D02F12C8091A5\r\n:101120000702F816C8F4F6019081911103C0602FF0\r\n:1011300080E00EC0F201E81BF109EF0DF11D28E07F\r\n:10114000929FE00DF11D1124E958FB4F8491602F0F\r\n:101150000E947504F394E3CF712C7E0131E0E31A11\r\n:10116000F108470134E0880C991C3A95E1F7609149\r\n:101170000902262F30E02C173D0769F460900A021F\r\n:10118000671009C08FEF860F833028F460E0812F4D\r\n:101190000E94490441C040910C02872D90E041110A\r\n:1011A00031C02C173D0771F520910A0230E0AC01E7\r\n:1011B0004F5F5F4F2417350729F56450633010F5F2\r\n:1011C000612C862D90E020910702A501421B510958\r\n:1011D000841795072CF480E00E9416046394F1CFE5\r\n:1011E00060E0812F0E944904612C809107026816FB\r\n:1011F00028F480E00E9416046394F7CF6624639479\r\n:10120000670C0AC0880D991DFC01E056FE4F602F47\r\n:1012100080810E944904672C77247394760C5EE0E9\r\n:10122000571508F0A4CF912CC70124E0880F991F0F\r\n:101230002A95E1F7DC01A155BE4F7D01E92DF0E0D3\r\n:10124000809107029501281B3109E217F3078CF4FE\r\n:10125000D7018C91882341F0B8E08B9FE00DF11D00\r\n:101260001124E958FB4F8491602F0E9475049394D8\r\n:10127000E5CF229630E2C30ED11CC830D10509F06B\r\n:1012800042CF80910A02811114C061E0812FDF9169\r\n:10129000CF911F910F91FF90EF90DF90CF90BF9073\r\n:1012A000AF909F908F907F906F905F904F900C9435\r\n:1012B0003007DF91CF911F910F91FF90EF90DF905A\r\n:1012C000CF90BF90AF909F908F907F906F905F90E6\r\n:1012D0004F9008952F923F924F925F926F927F921C\r\n:1012E0008F929F92AF92BF92CF92DF92EF92FF9236\r\n:1012F0000F931F93CF93DF93CDB7DEB7A6970FB6AB\r\n:10130000F894DEBF0FBECDBF8CE0E1E0F1E0DE017E\r\n:10131000599601900D928A95E1F78CE0EDE0F1E0AD\r\n:10132000DE011D9601900D928A95E1F780910B02E6\r\n:10133000813029F422EF3FEF388F2F8B02C08330AA\r\n:1013400028F42AEF3FEF3E8B2D8B02C0833041F40F\r\n:1013500029EF3FEF3C8B2B8B8330F0F4512C23C0D3\r\n:101360008430F9F02F85388921503109388B2F8747\r\n:1013700029893A89215031093A8B298B883060F0CC\r\n:101380002CEF3FEF3C8B2B8B2EEF3FEF3E8B2D8BCB\r\n:101390002DEF3FEF388F2F8B873018F0B9E05B2EA1\r\n:1013A00002C0A5E05A2EDE015996CE0101969EA3F9\r\n:1013B0008DA3AE014B5D5F4F9C01CD01FC0161919E\r\n:1013C0007191CF01F901619371939F018417950782\r\n:1013D000A9F760EA71E0AB0120E030E0FA01119278\r\n:1013E000AF01C90180569E4FFC01108A10A210AABD\r\n:1013F0008C01005C1F4FF8011082805B9F4FFC0145\r\n:1014000010822F5F3F4F2031310541F77E01FDE013\r\n:10141000EF0EF11C20E030E010E0FEE0AF2EB12C2A\r\n:10142000EDA1FEA180819181F701C190D1907F0152\r\n:1014300040E050E04501821A930A422E1816190620\r\n:1014400084F5881599056CF58130910519F41130F2\r\n:1014500009F412E01B01240E351E2330310528F05B\r\n:10146000F4E04F1639F003E001C000E0211531052A\r\n:1014700029F402C009E002C0451540F0E5E07E2EE7\r\n:10148000710E672C600EF101608204C00BE0010F49\r\n:10149000F1010083112321F0123019F410E001C092\r\n:1014A00011E00197C816D9061CF08D919C911197F7\r\n:1014B0004F5F5F4F4F30510509F6EDA1FEA18193BB\r\n:1014C0009193FEA3EDA32F5F3F4F1296605F7F4F76\r\n:1014D0002630310509F0A4CFA6960FB6F894DEBFEA\r\n:1014E0000FBECDBFDF91CF911F910F91FF90EF9075\r\n:1014F000DF90CF90BF90AF909F908F907F906F9034\r\n:101500005F904F903F902F900895809109029FEF38\r\n:10151000980F9330A0F490910A02E82FF0E03197F1\r\n:1015200034E0EE0FFF1F3A95E1F7E90FF11DE056A9\r\n:10153000FE4F9081911129C091E090930C029CEF95\r\n:10154000980F933028F590E09C012150310980914B\r\n:101550000A02E82FF0E0C90124E0880F991F2A95BC\r\n:10156000E1F7DC01AE0FBF1FA056BE4F2C91211139\r\n:1015700008C08E0F9F1FFC01E156FE4F808188231B\r\n:1015800039F081E080930C0208959A30A8F6D7CF05\r\n:101590000895AF92BF92CF92DF92EF92FF920F9396\r\n:1015A0001F93CF93DF931F92CDB7DEB7182F7A0129\r\n:1015B00000E0F701E00FF11D8081882381F1803286\r\n:1015C00061F194ED980F903130F09EEC980F9932C4\r\n:1015D00010F095EC980F1F3710F06F5F10E010932C\r\n:1015E0002E0260932D0286E0989F50011124C12C99\r\n:1015F000D12CF601EA0DFB1DEB5FFC4F8491698352\r\n:101600000E9416048FEFC81AD80A698186E0C816AE\r\n:10161000D10479F71A5F0F5FCCCF90E0DCCF0F9049\r\n:10162000DF91CF911F910F91FF90EF90DF90CF90BE\r\n:10163000BF90AF900895EF92FF920F931F93CF93B7\r\n:10164000DF93CDB7DEB72A970FB6F894DEBF0FBE93\r\n:10165000CDBFF82EE62ECA018E010F5F1F4F2AE084\r\n:10166000F80111922A95E9F74AE0B8010E94B51FE6\r\n:10167000A8016E2D8F2D0E94C90A2A960FB6F894E4\r\n:10168000DEBF0FBECDBFDF91CF911F910F91FF90B5\r\n:10169000EF900895EF92FF920F931F93CF93DF93F4\r\n:1016A0007C018B01C0E0D0E0EC16FD06E4F061E0C7\r\n:1016B00083E00E94A80420E030E02017310724F4E2\r\n:1016C00000002F5F3F4FF9CF60E083E00E94A80445\r\n:1016D00020E030E02017310724F400002F5F3F4F57\r\n:1016E000F9CF2196E1CFDF91CF911F910F91FF901C\r\n:1016F000EF900895FC01643508F053C0403308F0C2\r\n:1017000050C090A1742F759575957595262F062E4E\r\n:10171000000C330B542F57709230A1F4F901E55CA3\r\n:10172000FD4F84E57802E00DF11D1124808190E0E9\r\n:10173000052E02C0959587950A94E2F78095982F1B\r\n:1017400091700AC0933041F484858170462740959A\r\n:101750004170841303C014C0911112C084E5780253\r\n:10176000200D311D1124F901E55CFD4F81E090E071\r\n:1017700001C0880F5A95EAF780959081892310C09F\r\n:1017800084E57802200D311D1124F901E55CFD4F3F\r\n:1017900081E090E001C0880F5A95EAF79081892B8B\r\n:1017A00080830895BF92CF92DF92EF92FF920F93C2\r\n:1017B0001F93CF93DF931F92CDB7DEB77C01D62E58\r\n:1017C000C42E002E000C110B040F111D47FD1A959D\r\n:1017D0004C2D0C2C000C550B401751077CF4B12CF0\r\n:1017E000B21654F46B2D6D0D4C2DC70129830E9448\r\n:1017F0007A0BB3942981F4CFC394EACF0F90DF9191\r\n:10180000CF911F910F91FF90EF90DF90CF90BF90FD\r\n:1018100008956F927F928F929F92AF92BF92CF92D4\r\n:10182000DF92EF92FF920F931F93CF93DF93EC0120\r\n:101830006A3019F42D819885A1C06D3009F4A4C0D7\r\n:101840001885BA84D98488A083E58D150CF47FC0EF\r\n:101850008FE28B150CF47BC08C8190E00197189F70\r\n:101860009001199F300D1124C9018D0D911DD7FCD8\r\n:101870009A95181619060CF06AC08D81819FC001D7\r\n:1018800011248B0D911DB7FC9A95181619060CF0B2\r\n:101890005EC09D2CCD2CE62EF12CEC2DED190E2EDC\r\n:1018A000000CFF0B8C8190E0E817F9070CF04EC09C\r\n:1018B0000197E817F90779F0E89E9001E99E300D4D\r\n:1018C000F89E300D1124E20FF31F8E8D9F8DE80FCF\r\n:1018D000F91F749001C0712C6B2CAB2C2A2D2B1985\r\n:1018E000022E000C330B8D8190E0281739075CF530\r\n:1018F00070FE10C0113031F44A2D6C2DCE010E94C3\r\n:101900007A0B1DC0012F212F462D692DCE010E947B\r\n:10191000D20B15C089A198A1891789F088A311302D\r\n:1019200031F44A2D6C2DCE010E947A0B07C0012F95\r\n:10193000212F462D692DCE010E94D20B88A27694CC\r\n:10194000A394610ECBCFC394910EA7CF88A2288514\r\n:101950003C818985329F800D112489879F8199233D\r\n:1019600099F0082E000C990B44E550E0239F401994\r\n:1019700051091124481759073CF49D818A85299FF4\r\n:10198000800D11248A87198681E090E0DF91CF9144\r\n:101990001F910F91FF90EF90DF90CF90BF90AF908D\r\n:1019A0009F908F907F906F900895CF93DF931092C8\r\n:1019B000AC0481E08093AD04D0E0C0E04D2F6C2FEB\r\n:1019C0008CE894E00E947A0BCF5FC038B9F7DF5FF4\r\n:1019D000D03499F7DF91CF910895EF92FF920F9352\r\n:1019E0001F93CF93DF938C0181E00E94D50C0336C7\r\n:1019F000110524F41093100200930F024FE651E0FA\r\n:101A000061E080E00E94C90A4DE751E063E080E0B8\r\n:101A10000E94C90A4AE851E065E080E40E94C90AD0\r\n:101A200010922E0210922D020CE410E088E30E9426\r\n:101A3000160401501109D1F710922E0282E0809312\r\n:101A40002D020CE410E08CE10E94160401501109F3\r\n:101A5000D1F7C0E0E12CF12CD4E5D0932E02C09355\r\n:101A60002D0200E010E0F801EE0DFF1DE35CFD4FDC\r\n:101A700084910E9416040F5F1F4F0832110599F7D9\r\n:101A800088E2E80EF11CCF5FC53039F7DF91CF91C6\r\n:101A90001F910F91FF90EF9008954F925F926F9278\r\n:101AA0007F928F929F92AF92BF92CF92DF92EF92EE\r\n:101AB000FF920F931F93CF93DF9300D000D01F921C\r\n:101AC000CDB7DEB7C090BE04D090BF04E090C00494\r\n:101AD000F090C1040E94E905C61AD70AE80AF90A7B\r\n:101AE0008091BD0490E0A0E0B0E04091B904509135\r\n:101AF000BA046091BB047091BC048C159D05AE05C1\r\n:101B0000BF0530F4411551056105710509F03CC36D\r\n:101B1000452B462B472B09F035C380915504815046\r\n:101B20008E3FC0F5809154048130C9F580916804DE\r\n:101B30008F5F6091690487FD09C0082E000C990B26\r\n:101B400070E06F5F7F4F0E94F921682F60936804F7\r\n:101B500086EE96E09093C3048093C20488E4809359\r\n:101B6000C40480E00E94C9128FEF94E09093710446\r\n:101B700080937004109276041092750481E0809333\r\n:101B8000640489E08093790410927C0410927E04AE\r\n:101B9000109280048091550481508E3F70F48091A2\r\n:101BA0005304813009F095C389ED96E09093C30406\r\n:101BB0008093C20488E48093C40480E00E949C1354\r\n:101BC00080916404882309F4ABC08091780481116A\r\n:101BD000A7C08091700490917104E0917504F09118\r\n:101BE0007604EE0FFF1FE80FF91F45915491411540\r\n:101BF0005105F1F420917404222331F010927604FF\r\n:101C000010927504FC0112C0109264048091630468\r\n:101C1000882341F080E00E949C13E0917504F091CC\r\n:101C200076042DC080E00E94B4127AC04591549190\r\n:101C30009A01369527953695279540FF51C0CA01E0\r\n:101C400016E0969587951A95E1F78F71952F9695E1\r\n:101C50009695969590512F70223071F1F8F42111DC\r\n:101C600017C08B3008F08AE080937904E091750406\r\n:101C7000F09176043196F0937604E0937504EE0FBC\r\n:101C8000FF1F8091700490917104E80FF91FCECF6F\r\n:101C9000213061F760E00E940614E8CF2330B1F0F4\r\n:101CA000243021F720916704829F802D1124809396\r\n:101CB000800490938104DACF20916704829F802D65\r\n:101CC000112480937C0490937D04D0CF20916704ED\r\n:101CD000829F802D112480937E0490937F04C6CF31\r\n:101CE0002F732093770480916704859F802D1124A2\r\n:101CF00080937804109288041092870410928604CE\r\n:101D000081E080937A0480933B0410927B0480915D\r\n:101D100075049091760401969093760480937504EF\r\n:101D200080917A04882309F4EEC0809178048111AF\r\n:101D300003C00E94B412E7C0815080937804809160\r\n:101D40008804811146C020918604309187042F5F5A\r\n:101D50003F4FC901880F991FE0918204F0918304DD\r\n:101D6000E80FF91F65917491862F8770809389041D\r\n:101D7000AB01E3E056954795EA95E1F7CA019695E0\r\n:101D80008795972F9695969590938A048F73909147\r\n:101D90006704899F802D11248093880441704093AB\r\n:101DA0003A0230938704209386048091840490E063\r\n:101DB0002817390770F020918504222339F0821BFF\r\n:101DC0009109909387048093860403C080E00E9469\r\n:101DD000B4128091880481508093880480917B04A0\r\n:101DE00021E0280F20937B044091770430918A04EE\r\n:101DF000340F80916F04380F3093650460917E0436\r\n:101E0000662371F070E0822F022E000C990B0E9465\r\n:101E1000F92180917F04869F300D11243093650451\r\n:101E20008091650490E0849664E270E00E94F9215C\r\n:101E300080936504309179043093660460917C044A\r\n:101E4000662381F0062E000C770B822F022E000CE9\r\n:101E5000990B0E94F92180917D04869F300D1124F9\r\n:101E600030936604609180046623A1F0822F220FD4\r\n:101E7000990B70E00E94F921CB0162E070E00E94B2\r\n:101E8000F9212091810490916604289F900D1124DE\r\n:101E900090936604809166044F3341F08A300CF0D1\r\n:101EA00089E087FD80E08093660402C0109266049A\r\n:101EB000F894E0916504F0E0EB5FFA4FE491E09371\r\n:101EC00039023091660420918B0432039001112471\r\n:101ED000409189044203C001439F900D112400905A\r\n:101EE000680402C0880F991F0A94E2F797FF02C0A6\r\n:101EF00081589F4F880F892F881F990B80933C042E\r\n:101F000080933D0478948091C404882309F48DC0A3\r\n:101F10008C3020F49CE0E92EE81A01C0E12CFF246B\r\n:101F2000F394F09294041092AC041092AD043091AA\r\n:101F300091044DE2D42E1D2D131B1E0D03E0030F43\r\n:101F40002EE4412F63E08CE894E03D830E94D20BA5\r\n:101F50003D810CEF030F1D5F202F41E0612F80E5D5\r\n:101F60000E94D714202F42E0612F83E00E94D714F3\r\n:101F7000F092AC04F092AD040091910413E0100FC4\r\n:101F8000D01ADE0C23E04D2D622F8CE894E02D83D7\r\n:101F90000E947A0B2D812F5F2135A9F71D0DFF249B\r\n:101FA000FA94F10E23E04F2D622F8CE894E02D83FC\r\n:101FB0000E947A0B2D812F5F2135A9F7035033E062\r\n:101FC000D30E402F6D2D80E00E94BF14402F6D2D49\r\n:101FD00083E50E94BF1441E06D2D83E00E9441140F\r\n:101FE00042E06D2D80E50E944114145044E0612FC1\r\n:101FF00080E50E94411448E0612F83E00E94411473\r\n:1020000084E08093950480919104E81A8E2D815D7F\r\n:10201000809396048091C2049091C3040E9434136B\r\n:102020008091C40481508093C40480915A0490919B\r\n:102030005B04892B09F47CC011E01093AC0410926E\r\n:10204000AD049091900485E5891B809395041092CE\r\n:10205000960480915704813009F44DC030F090917E\r\n:102060005604853008F05FC05AC080E00E94C91253\r\n:1020700010939404E7E5F5E0E491EF5FE0939004BA\r\n:10208000E8E5F5E0E491EF5FE093910489E595E000\r\n:102090009093AB048093AA0410925B0410925A04AC\r\n:1020A0001092920418EA0E944D0D8823E1F389E40E\r\n:1020B00095E00E943413609158047091590480E0B7\r\n:1020C00090E04AE00E94321584E395E00E943413C8\r\n:1020D000612F62956F7070E080E090E04AE00E94AE\r\n:1020E000321589E295E00E943413809153048130C7\r\n:1020F00009F0F5C01DC08091AF049091B004A0918B\r\n:10210000B104B091B2048F709927AA27BB27089712\r\n:10211000A105B10510F487E009C088E707C099233D\r\n:1021200039F08B5F03C0992319F08FE20E94731579\r\n:102130008CE894E00E94B5068091920481110EC053\r\n:1021400088EF91E0EBE3F2E0DF019C011D9221506A\r\n:102150003040E1F710929504109296040E948A058F\r\n:102160006093B9047093BA048093BB049093BC0449\r\n:102170002091B5043091B604621B730B7093B404C4\r\n:102180006093B30480E0C5C00E94E9052091BD04BE\r\n:10219000DC01CB01820F911DA11DB11D8093BE04F6\r\n:1021A0009093BF04A093C004B093C1048091AF0486\r\n:1021B0009091B004A091B104B091B2040196A11D18\r\n:1021C000B11D8093AF049093B004A093B104B09379\r\n:1021D000B2041092B9041092BA041092BB04109287\r\n:1021E000BC040E948A056093B5047093B604809382\r\n:1021F000B7049093B80480913F04909140042FE07D\r\n:10220000289F8001299F100D112485E10E947305EC\r\n:10221000800F911F24E0969587952A95E1F790937A\r\n:10222000400480933F0420913E04222309F44BC0D4\r\n:1022300060914204262F30E040E050E029833A8349\r\n:102240004B835C83C0904304D12CE12CF12C409152\r\n:102250004604509147044A01A12CB12C209144041A\r\n:10226000309145042901612C712C8217930728F0C5\r\n:102270009C014817590708F49A01C901A0E0B0E091\r\n:102280009C01AD01241935094609570969817A81F4\r\n:102290008B819C816C197D098E099F090E94DD212B\r\n:1022A000A501940124193509460957090E94002007\r\n:1022B000C20ED31EE41EF51EC09241046C2D70E0C8\r\n:1022C00085E00E9414050E94E0120E947E1581E0C4\r\n:1022D00020C0893209F071CC0E9463136ECC11507A\r\n:1022E00009F0E1CE60E070E085E00E94140583B75C\r\n:1022F000817F846083BF83B7816083BF83B7816040\r\n:1023000083BF889583B78E7F83BF83B78E7F83BF5C\r\n:10231000CACE0F900F900F900F900F90DF91CF913A\r\n:102320001F910F91FF90EF90DF90CF90BF90AF90F3\r\n:102330009F908F907F906F905F904F9008958F92B5\r\n:102340009F92AF92BF92CF92DF92EF92FF920F9344\r\n:102350001F93CF93DF93FB0124913196C490F090AB\r\n:10236000AC04022E000C330B121613060CF0D7C06F\r\n:1023700080330CF0D4C0482F082E000C550BFA0106\r\n:10238000EC0DF11DC7FCFA951E161F060CF0C7C018\r\n:102390006E5F7F4FD901179693E0B595A7959A95F3\r\n:1023A000E1F787FF0BC0C80EA49FC001A59F900D49\r\n:1023B000B49F900D1124681B790B80E04C2D0C2CE0\r\n:1023C000000C550B480F511D87FD5A95413351059F\r\n:1023D0001CF090E3C92EC81A2535310514F024E508\r\n:1023E00030E0109198041827982F977031E001C0C1\r\n:1023F000330F9A95EAF7859585958595F4E58F02D3\r\n:10240000C0011124855C9D4F00E00C2C000CDD0800\r\n:10241000BB24B394402F50E04C155D050CF07FC0F9\r\n:10242000FB01E490F1E0FF1218C0FB01EC0140E871\r\n:10243000542F5E2119F05881532B588350E0559545\r\n:1024400047954115510519F43196E49040E82196DD\r\n:102450005C2F581B521760F359C0F1101AC0A32EFD\r\n:10246000A094FB01EC0140E8542F5E2119F0588143\r\n:102470005A21588350E0559547954115510519F457\r\n:102480003196E49040E821965C2F581B521760F378\r\n:102490003DC043E0F41223C0932E9094FB01EC0165\r\n:1024A00040E8A82E8C2E881A542F5E2141F08126F8\r\n:1024B000588180FE02C0532B01C05921588350E03F\r\n:1024C000559547954115510519F43196E49040E82A\r\n:1024D00021965C2F5A19521728F31B2517C0FB01B0\r\n:1024E000EC0140E8542F5E2119F05881532758839E\r\n:1024F00050E0559547954115510519F43196E490F2\r\n:1025000040E821965C2F581B521760F3330F19F4E3\r\n:102510008C5A9F4F31E00F5F6A0F7B1F7BCFDF919B\r\n:10252000CF911F910F91FF90EF90DF90CF90BF90D0\r\n:10253000AF909F908F900895BC01009791F0FC019F\r\n:1025400001900020E9F73197AF01481B590BE0914A\r\n:102550008C04F0918D040280F381E02D8CE894E0EE\r\n:10256000099480E090E00895811112C010927A04DD\r\n:1025700010927804109287041092860410927B04C3\r\n:1025800010923D0410923C0410923B040C943F06C0\r\n:102590000895811114C010927A0410927804109258\r\n:1025A00087041092860410927B0410923D041092CE\r\n:1025B0003C0410923B040E943F061092640408956C\r\n:1025C000CF92DF92EF92FF920F931F93CF93DF93FF\r\n:1025D000C8E4D4E00FE414E0FF24FA9497E0E92E75\r\n:1025E000E00E62E088810E94D804288130E0F90181\r\n:1025F000E459F84F8491F901E85AF84FC490F90171\r\n:10260000EC5BF84FD490DD2071F081110E947F04C3\r\n:10261000ED2DF0E0EE0FFF1FE65CF84FA591B491B1\r\n:10262000EC91EC21B1F4F80180818F5F808360E050\r\n:1026300088810E94D80421960F5F1F4FE012D1CFEE\r\n:10264000DF91CF911F910F91FF90EF90DF90CF908E\r\n:102650000895F8018081882371F3F8018F3F11F408\r\n:102660001082E5CFF082E3CF0F931F93CF93DF93D8\r\n:102670008C01C0E0D0E0F801EC0FFD1F64916623EF\r\n:1026800071F0E0918C04F0918D040190F081E02DC7\r\n:102690008CE894E00995892B11F02196ECCFCE01BE\r\n:1026A000DF91CF911F910F910895CF93DF930E94F7\r\n:1026B0003413EC0185E991E00E949C128C0F9D1F60\r\n:1026C000DF91CF91089588EF91E0EBE3F2E0DF0135\r\n:1026D0009C011D9221503040E1F710929504109218\r\n:1026E000960482E197E00E9434138CE894E00E9403\r\n:1026F000B5068CB583608CBD8DB58E7F8DBD88E9A8\r\n:1027000091E0EEEFFFE30995109292048DEE96E0D2\r\n:102710000E9455138CE894E00E94B5060E94E012D6\r\n:1027200080915304813039F062E370E080E090E002\r\n:102730000E94AF05F3CF0895AF92BF92CF92DF9280\r\n:10274000EF92FF920F931F93CF93DF93C82ED12C5C\r\n:10275000E601C25CDB4F9DA1992309F44CC07E01C8\r\n:102760009FEFE91AF90AF70195A1911144C09EA5BE\r\n:102770008601000F111F025C1B4FF80134A525A52F\r\n:10278000E32FF22FE90FF11DE90FF11D259134918F\r\n:102790002F3FFFEF3F0711F41DA22DC039ABF6010B\r\n:1027A000EE0FFF1FE85BFB4F3327220F331F05A0FF\r\n:1027B000F6A1E02DE20FF31FA590B490811117C090\r\n:1027C0000E94C912F801B3AAA2AAF601EE0FFF1FD8\r\n:1027D000E05BFB4F16A215A281E0F70185A389E01B\r\n:1027E0008BAF1EAEFE017B9615A2329615A22996DE\r\n:1027F0008DA18F5F8DA3DF91CF911F910F91FF90DE\r\n:10280000EF90DF90CF90BF90AF90089570E0DB0124\r\n:10281000AA0FBB1FA25CBB4FD4962C91D497D59620\r\n:102820009C91D597E22FF92FE80FF11DE80FF11DCC\r\n:10283000259134915F9696963C932E939597F90146\r\n:102840008591949190916704989F802D1124625CEA\r\n:102850007B4FFB01B19685A3F901A591B4914B2F54\r\n:1028600050E0E82FF0E04E175F0720F4F9012591C2\r\n:102870003491832FFB01B296899F802D112485A36B\r\n:102880000895AF92BF92CF92DF92EF92FF920F9393\r\n:102890001F93CF93DF93182F062FC1E0D3E08AEF69\r\n:1028A000D82E9EEFE92E842F8470C82E842F82703C\r\n:1028B000B82E842F8870A82E4170F42E8C2F880F8C\r\n:1028C0008F5FE80ECC2081F04D2F400F6C2F610FF1\r\n:1028D0008CE894E00E947A0B4C2F400F6D2F610F13\r\n:1028E0008CE894E00E947A0BBB2081F0402F4D1BB6\r\n:1028F0006C2F610F8CE894E00E947A0B402F4C1BE8\r\n:102900006D2F610F8CE894E00E947A0BAA2081F071\r\n:102910004C2F400F612F6D1B8CE894E00E947A0BC6\r\n:102920004D2F400F612F6C1B8CE894E00E947A0BB6\r\n:10293000FF2081F0402F4C1B612F6D1B8CE894E031\r\n:102940000E947A0B402F4D1B612F6C1B8CE894E08A\r\n:102950000E947A0BCD1744F4E7FC04C0D150D39405\r\n:10296000D394ED0CCF5FAACFDF91CF911F910F9140\r\n:10297000FF90EF90DF90CF90BF90AF9008950F93AE\r\n:102980001F93CF93DF93182F062FD42FC0E0CD17BE\r\n:102990004CF44C2F400F612F8CE894E00E947A0B8E\r\n:1029A000CF5FF5CFDF91CF911F910F9108959F9247\r\n:1029B000AF92BF92CF92DF92EF92FF920F931F934D\r\n:1029C000CF93DF93F82EE62EB22E03E0020FD0E075\r\n:1029D000C3E08AEFC82E1EEF842F8170982EAA24A0\r\n:1029E000A394A20E4270D42EDF5F802F8B19180F94\r\n:1029F000992081F04C2F440F4A0D6E2D6C1B8D2FAA\r\n:102A00008F0D0E94BF14402F6E2D6D1B8C2F8F0DCC\r\n:102A10000E94BF14DD2081F04C2F440F4A0D6E2D13\r\n:102A20006C1B8F2D8D1B0E94BF14402F6E2D6D1BB4\r\n:102A30008F2D8C1B0E94BF14DC1744F417FD04C0BB\r\n:102A4000C150C394C3941C0D0E5FCECFDF91CF91C4\r\n:102A50001F910F91FF90EF90DF90CF90BF90AF90BC\r\n:102A60009F9008958F929F92AF92BF920F931F9362\r\n:102A7000CF93DF93CDB7DEB7A1970FB6F894DEBF43\r\n:102A80000FBECDBF19A2423008F44AE08E010F5D9F\r\n:102A90001F4F842E912CA12CB12CA50194010E94D2\r\n:102AA0002A20E62FB901CA0101501109EA3014F4B5\r\n:102AB000E05D01C0E95CD801EC93232B242B252B8E\r\n:102AC00061F7C8010E949C12A1960FB6F894DEBF70\r\n:102AD0000FBECDBFDF91CF911F910F91BF90AF90EF\r\n:102AE0009F908F900895E0918C04F0918D04019057\r\n:102AF000F081E02D682F8CE894E0099480915A04CD\r\n:102B000090915B04892BB1F1809162048F7169F51A\r\n:102B100084E10E947305BC01990F880B990B0E94F8\r\n:102B20008C2026EE3FE34EEC50E40E9448210E94A8\r\n:102B30005B209B017093590460935804672B91F0BC\r\n:102B400084E080935704EAE5F4E080E041915191FC\r\n:102B50002417350718F48093570408958F5F843045\r\n:102B6000A9F703C08FEF80935704809162048F5FB1\r\n:102B7000809362040895CF93DF9300D000D000D0FB\r\n:102B8000CDB7DEB7789484B5826084BD84B58160AA\r\n:102B900084BD85B5826085BD85B5816085BD809128\r\n:102BA0006E00816080936E001092810080918100A0\r\n:102BB0008260809381008091810081608093810098\r\n:102BC000809180008160809380008091B10084605A\r\n:102BD0008093B1008091B00081608093B0008091BB\r\n:102BE0007A00846080937A0080917A00826080937A\r\n:102BF0007A0080917A00816080937A0080917A00D7\r\n:102C0000806880937A001092C10082E38093BD04B3\r\n:102C100081E090E0A0E0B0E08093B9049093BA0422\r\n:102C2000A093BB04B093BC048FEF8093AE04E0E8A4\r\n:102C3000F7E7259134912130304C09F049C0E6E99D\r\n:102C4000F7E7E491E0939704E7E9F7E7E491E0938D\r\n:102C50004204E8E9F7E7E491E0934304E9E9F7E7A0\r\n:102C6000859194919093450480934404EBE9F7E7B0\r\n:102C700085919491909347048093460487E08093D4\r\n:102C80006904EEE9F7E7E491E0936804EFE9F7E718\r\n:102C9000E491E093AE04E0EAF7E785919491909394\r\n:102CA0005B0480935A04E2EAF7E78591949190934C\r\n:102CB0005D0480935C04E4EAF7E785919491909336\r\n:102CC0005F0480935E04E6EAF7E7859194912CC057\r\n:102CD0009CE390939704109242048093430480E213\r\n:102CE00093E0909345048093440484ED93E09093A3\r\n:102CF00047048093460487E08093690480936804C6\r\n:102D00008CEA9DE090935B0480935A048EED9DE0E5\r\n:102D100090935D0480935C0484E79EE090935F044D\r\n:102D200080935E048CE39FE0909361048093600441\r\n:102D300011E010933E046FEF70E085E00E941405EF\r\n:102D400088E08093480489E08093490487E0809379\r\n:102D50004A0486E080934B0404E000934C0482E034\r\n:102D600080934D0481E180934E040E94E0128CE335\r\n:102D70009FE0909359048093580400935704109354\r\n:102D800062048BE080939A048DE08093990480E143\r\n:102D900080939B048EE080939D048FE080939C043D\r\n:102DA000109394041093AC041092AD041093930408\r\n:102DB000E7E5F5E0E491EF5FE0939004E8E5F5E006\r\n:102DC000E491EF5FE093910489E595E09093AB0483\r\n:102DD0008093AA041FB7F89480911102811127C033\r\n:102DE000EEE4F7E08491E2E6F7E09491E82FF0E07A\r\n:102DF000EE0FFF1FEC58FF4FA591B491EC91E92322\r\n:102E000021F461E08AE00E94A80461E08AE00E9467\r\n:102E1000D8048CB580618CBD8CB580648CBD61E0BC\r\n:102E20008DE00E94D80461E08BE00E94D80480917C\r\n:102E300011028F5F809311021FBF8CB58F7D8CBDF7\r\n:102E40008CB58C7F81608CBD8DB581608DBD8CB55E\r\n:102E50008C608CBD61E080919A040E94D80461E08E\r\n:102E6000809199040E94D80461E080919B040E94A3\r\n:102E7000D80480919D0418161CF461E00E94D804C7\r\n:102E800080919C0418161CF461E00E94D804809183\r\n:102E90009D04181674F460E00E94A8046AE070E0D3\r\n:102EA00080E090E00E94AF0561E080919D040E9467\r\n:102EB000A80480919904082E000C990BFC01EC5B8E\r\n:102EC000F84FE491F0E0EE0FFF1FE258FF4F25911D\r\n:102ED00034913093A1042093A004FC01E85AF84FE8\r\n:102EE000E491E093A70480919A04082E000C990BBA\r\n:102EF000FC01EC5BF84FE491F0E0EE0FFF1FE258AD\r\n:102F0000FF4F2591349130939F0420939E04FC0140\r\n:102F1000E85AF84FE491E093A60480919C04082EAF\r\n:102F2000000C990BFC01EC5BF84FE491F0E0EE0F24\r\n:102F3000FF1FE258FF4F259134913093A304209353\r\n:102F4000A204FC01E85AF84FE491E093A8048091B0\r\n:102F50009B04082E000C990BFC01EC5BF84FE491EC\r\n:102F6000F0E0EE0FFF1FE258FF4F259134913093B0\r\n:102F7000A5042093A404FC01E85AF84FE491E093DF\r\n:102F8000A90461E28CE894E00E94940664E18CE874\r\n:102F900094E00E9494068091970487FF03C08FE716\r\n:102FA000809397046091970460688CE894E00E9495\r\n:102FB000940660E28CE894E00E9494066CE08CE851\r\n:102FC00094E00E9494068CE894E00E94B50611E01B\r\n:102FD0001093670484E080938B0480E790E09093E3\r\n:102FE00073048093720460E080E00E94061461E044\r\n:102FF00070E083E00E9414058091B100887F8160B9\r\n:103000008093B100F8941092800010928100109289\r\n:1030100085001092840088E191E09093890080936C\r\n:103020008800809181008860809381008091810078\r\n:1030300081608093810080916F00826080936F0037\r\n:1030400078940E947E1580915404813019F4109276\r\n:1030500068041CC0809157048823C9F380E00E9453\r\n:10306000C91288E890E090937104809370041092E4\r\n:103070007604109275041093640489E080937904B7\r\n:1030800010927C0410927E04109280048091AE0411\r\n:10309000882309F458C181E080939404109293042A\r\n:1030A00010929204109256048093AC048093AD0465\r\n:1030B00072E2672E71E0772EECE0FE2E0FEF14E047\r\n:1030C000EE24E394F9E0DF2E0E944D0D8823E1F316\r\n:1030D000F3018491882319F0C090910401C0C12CA0\r\n:1030E00062EB70E080E00E949F1163E271E08CE08F\r\n:1030F0008C0D0E949F1110929504F092960482E22A\r\n:1031000091E00E94341380919004982F990F890FB9\r\n:1031100081958D5A8093950480919104982F990FF1\r\n:10312000890F8195835D809396048091AF0484FF1D\r\n:1031300003C08EEA90E002C08AEA90E00E94551334\r\n:1031400080919004982F990F890F81958D5A8093C3\r\n:103150009504809196048F5F809396048091680413\r\n:10316000882319F086EA90E002C082EA90E00E948B\r\n:10317000551380919004982F990F890F81958D5A3E\r\n:1031800080939504809196048F5F809396048EE9D6\r\n:1031900090E00E94551380915404813039F580915C\r\n:1031A00068048F5F6091690487FD09C0082E000CD8\r\n:1031B000990B70E06F5F7F4F0E94F921682F609339\r\n:1031C000680480E00E94C912109371040093700497\r\n:1031D0001092760410927504E0926404D0927904FF\r\n:1031E00010927C0410927E0410928004809153040B\r\n:1031F0008130B9F08091AE04482F50E060E070E07B\r\n:103200008090AF049090B004A090B104B090B2044C\r\n:1032100084169506A606B70608F483C68F3F09F400\r\n:1032200080C68FEF8093AE0480E00E94C91280E0D8\r\n:103230000E94C91286E990E0909371048093700413\r\n:10324000109276041092750481E08093640499E0F2\r\n:103250009093790410927C0410927E041092800462\r\n:103260008093560470C060E080E090E00E94F21FFE\r\n:1032700060E081E090E00E94F21F4BE351E060E0EB\r\n:1032800080E00E94C90A40E651E061E080E00E94CF\r\n:10329000C90A4BE351E063E080E00E94C90A0E9442\r\n:1032A0004D0D8823E1F360ED77E080E090E00E942F\r\n:1032B000AF0581E00E94D50C8CE894E00E94B50631\r\n:1032C00080915304813009F421C68FE38093770401\r\n:1032D0008091670480937804109288041092870488\r\n:1032E0001092860481E080937A0480933B041092CC\r\n:1032F0007B040E944D0D8823E1F31092100210927E\r\n:103300000F0200E010E0C8010E94ED0C8CE894E090\r\n:103310000E94B5060115110531F464EA76E080E0FB\r\n:1033200090E00E94AF050D5F1F4F0033110559F764\r\n:1033300080915304813009F0FFC580E090E0892B33\r\n:1033400011F00E94000081E00E94D50C1092100242\r\n:1033500010920F0210920E0210920D0280915404EE\r\n:10336000813009F480CF81E00E94D50C10920C02CC\r\n:10337000109229021092280288EE93E0909327027F\r\n:103380008093260281E080930B0298E090930A02DA\r\n:1033900097E09093090210922502809324021092E4\r\n:1033A00023021092220210920802109207028093C8\r\n:1033B00021028093200210921F0210921E0282E0CE\r\n:1033C00090E090930602809305028CE080931D02AA\r\n:1033D00081E090E090931C0280931B020E946A0996\r\n:1033E0001092000210920102109202021092030247\r\n:1033F0001092040260E081E00E9430070E945D07A5\r\n:1034000040E050E067E070E080E090E00E941B0B3D\r\n:10341000809124020E9494070E94FB0610921002E1\r\n:1034200010920F0210920E0210920D020E944D0D8A\r\n:103430008823E1F332E0632E712C88248394912C4D\r\n:103440009AE0E92EF12C28EE422E23E0522E8091B4\r\n:1034500005029091060297FDB1C460E080912402BC\r\n:103460000E9430070E945D07409128025091290276\r\n:1034700067E070E080E090E00E941B0B80912402E6\r\n:103480000E9494070E94FB0620910F0230911002C7\r\n:1034900080910A02F8E08F9FC0011124A901495DC3\r\n:1034A0005F4F4817590734F021503109309310020B\r\n:1034B00020930F0220910F0230911002A9014E5C5F\r\n:1034C0005F4F4817590734F42F5F3F4F3093100276\r\n:1034D00020930F0220910F0230911002A901425F48\r\n:1034E0005F4F4817590734F02150310930931002CB\r\n:1034F00020930F0220910F0230911002A901445C29\r\n:103500005F4F4817590734F42F5F3F4F3093100235\r\n:1035100020930F028091090290E0039790930E028E\r\n:1035200080930D0220910F023091100237FF0BC0E3\r\n:103530001092100210920F0297FF13C010920E0209\r\n:1035400010920D0202C097FDF9CF80910F02909169\r\n:1035500010028C9734F02BE230E03093100220936D\r\n:103560000F0280910D0290910E02039724F0709249\r\n:103570000E0260920D020E944D0D8E838823D9F3B6\r\n:1035800020911B0230911C02243F41E0340734F0AB\r\n:103590006FEF7FEF709306026093050271E0709306\r\n:1035A0001A020091280210912902C801B7010E9455\r\n:1035B000F921CB01B7010E94F921892B19F082E092\r\n:1035C00080931A02C80164E670E00E94F921CB01E1\r\n:1035D000B7010E94F921892B29F080911A028F5F8F\r\n:1035E00080931A02C801B2010E94F921CB01B701F0\r\n:1035F0000E94F921892B29F080911A028F5F809314\r\n:103600001A022F5F3F4F30931C0220931B028091C0\r\n:1036100008028F5F8093080290912002992319F08D\r\n:103620001092200203C091E090932002909120021A\r\n:10363000992329F0909107029F5F909307028730AA\r\n:1036400009F086C0809121028823E9F010922102BE\r\n:1036500060910902AA24AA94A60EA62FB0E0BD8309\r\n:10366000AC83B090210290910A02B0910C02BB830E\r\n:10367000EFEAF1E0FA83E983E0EAF1E040E050E0CC\r\n:1036800020E030E004C0F1E0F0932102E1CF62E0FD\r\n:10369000D62EDA14B8F06A016FEFC61AD60AAC81DA\r\n:1036A000BD81AC15BD0571F42130310531F4BB206D\r\n:1036B000C9F19E30F8F49F5F1EC0992309F439C404\r\n:1036C000915002C0232BB9F4308020E030E06F012C\r\n:1036D000C20ED31ED60111962C9011972C922F5FFB\r\n:1036E0003F4F2F30310599F7A981BA813C9221E0F3\r\n:1036F00030E01AC0BB82BB20A9F0A981BA813C90FE\r\n:1037000020E030E06F01C20ED31ED6011E962C9031\r\n:103710001E971F962C9221503109213FBFEF3B0786\r\n:1037200089F7308220E030E04F5F5F4F69817A8116\r\n:10373000605F7F4F7A83698370964630510509F048\r\n:10374000A6CF90930A027B8170930C02109208021C\r\n:1037500080910702873011F4109207021092230221\r\n:10376000109222020E94850A809150048130B1F4A7\r\n:1037700090912502911112C08093190210921C029F\r\n:1037800010921B02809325020E94E90560931502A6\r\n:10379000709316028093170290931802809152043E\r\n:1037A0008130B1F490912502911112C080931402DE\r\n:1037B00010921C0210921B02809325020E94E905C0\r\n:1037C000609315027093160280931702909318026B\r\n:1037D00080914F04813061F490912502911108C0CD\r\n:1037E0008093130210921C0210921B0280932502F8\r\n:1037F00080915104813061F490912502911108C0AB\r\n:103800008093120210921C0210921B0280932502D8\r\n:1038100080911302882339F110921C0210921B022E\r\n:103820001092130260E080E00E943007809109024C\r\n:10383000873039F490910A0280911A02891738F082\r\n:103840000FC0873068F480910A02882331F080919C\r\n:103850000A02815080930A0203C081E080930C0227\r\n:1038600082E08093240280911202882339F1109221\r\n:103870001C0210921B021092120260E080E00E9473\r\n:10388000300780910902873039F490910A028091C3\r\n:103890001D02981738F00FC0873068F480910A0233\r\n:1038A0008E3030F480910A028F5F80930A0203C049\r\n:1038B00091E090930C0283E08093240280911402A3\r\n:1038C0008823E1F110921402809109028730B0F54B\r\n:1038D00090910B02091B11091093290200932802F1\r\n:1038E000833029F490910802943010F51CC0823086\r\n:1038F00071F4909107022091080230E0290F311DE8\r\n:1039000025303105ACF490910A0291500FC08130FE\r\n:1039100079F4909107022091080230E0290F311DBF\r\n:10392000253031052CF490910A029F5F90930A0292\r\n:103930008F5F8093090284E08093240280911902B2\r\n:10394000882309F47CC11092190280910B024091E6\r\n:10395000280250912902480F511D5093290240938B\r\n:10396000280267E070E080E090E00E941B0B60E0BE\r\n:1039700080E00E94300780910902823070F181500E\r\n:1039800080930902833031F480910802843008F07A\r\n:1039900088C01FC0823081F4209107028091080204\r\n:1039A00090E0820F911D05970CF07BC080910A0278\r\n:1039B0008F5F80930A0275C0813009F072C0209138\r\n:1039C00007028091080290E0820F911D05970CF08C\r\n:1039D00068C080910A028150ECCF80910802843047\r\n:1039E00038F480910A028F3018F48F5F80930A02B6\r\n:1039F00080910A026BEA869F612D1124669570E022\r\n:103A000080E090E00E948C200E94C7200E945B20F2\r\n:103A1000E62FF0E0E050FE4F808181113FC08091A1\r\n:103A20001E0290911F02019690931F0280931E0226\r\n:103A3000A1E0A08387E08093090288E080930A02D6\r\n:103A400060E0809124020E9430070E945D0740914F\r\n:103A500028025091290267E070E080E090E00E9427\r\n:103A60001B0B809124020E9494070E94FB060E9477\r\n:103A70004D0D8823E1F308EE13E0B8018AE090E0F1\r\n:103A80000E944A0B04561109083C1105B1F768E57C\r\n:103A900072E080E090E00E94AF0503C0B1E0B09317\r\n:103AA0000C02E1E0E093240280911E0290911F023B\r\n:103AB00005970CF4C4C080910B028F5F80930B02BA\r\n:103AC0001092100210920F0210920E0210920D022C\r\n:103AD00068EC70E080E090E00E94AF0515E0109285\r\n:103AE0000002109201021092020210920302109240\r\n:103AF00004020E94FB06809124020E9494070E9407\r\n:103B00004D0D8823E1F360E273E084E190E00E94D0\r\n:103B10004A0B68E572E084E190E00E944A0B60E99C\r\n:103B200071E084E190E00E944A0BF1E0F093000222\r\n:103B3000F0930102F0930202F0930302F093040267\r\n:103B40000E94FB06809124020E9494070E944D0D62\r\n:103B50008823E1F360E273E084E190E00E944A0B85\r\n:103B600068E572E084E190E00E944A0B60E971E050\r\n:103B700084E190E00E944A0B115009F0B0CF64EF4D\r\n:103B800071E080E090E00E94AF0580E00E94D50CDB\r\n:103B900040E451E061E08EE00E94C90A45E251E054\r\n:103BA00062E08EE00E94C90A40E451E064E08EE0E9\r\n:103BB0000E94C90A40910B0250E063E070E080E28D\r\n:103BC00090E00E941B0B0E944D0D8823E1F36CEDE9\r\n:103BD00075E080E090E00E94AF0580E00E94D50C87\r\n:103BE0000E944D0D8823E1F38091260290912702D7\r\n:103BF0008436910534F0845691099093270280937E\r\n:103C000026020E946A09109200021092010210928C\r\n:103C10000202109203021092040210921F021092EC\r\n:103C20001E020E94FB060E945D07409128025091EF\r\n:103C3000290267E070E080E090E00E941B0B809119\r\n:103C40001B0290911C02892B19F580910C028111A5\r\n:103C50001FC090921C0280921B0210912402812F9F\r\n:103C60000E94940760E0812F0E94300760E971E0B4\r\n:103C70008EE190E00E944A0B6CE271E08EE190E0F0\r\n:103C80000E944A0B68EC70E08EE190E00E944A0BC3\r\n:103C90000E94850A1092250280910C02882309F463\r\n:103CA000D6CB10912402812F0E949407812F0E946D\r\n:103CB00094070E94FB0661E080E00E9430070E94AA\r\n:103CC0004D0D8823E1F300E010E0B80182E390E0BD\r\n:103CD0000E944A0B0E5C1F4F0A3F1105B1F710916D\r\n:103CE0002402812F0E9494070E94FB0661E0812F2D\r\n:103CF0000E9430075AEFE52EF12CB70182E390E0E5\r\n:103D00000E944A0B22E3E20EF11C34EFE31631E08D\r\n:103D1000F30699F7812F0E9494070E94FB0661E049\r\n:103D200080E00E9430070E944D0D8823E1F304EFEC\r\n:103D300011E0B80182E390E00E944A0B0E5C1F4F35\r\n:103D40000E3E42E01407A9F710912402812F0E9431\r\n:103D500094070E94FB0661E0812F0E9430070EEE5F\r\n:103D600012E0B80182E390E00E944A0B0E5C1F4F04\r\n:103D7000083E63E01607A9F70E944D0D8823E1F382\r\n:103D800068E572E080E090E00E94AF058091050256\r\n:103D9000909106020197909306028093050210927B\r\n:103DA0000C020E945D0788E080930A0287E08093FE\r\n:103DB00009020E944D0D8823E1F342CB10921002BC\r\n:103DC00010920F0210920E0210920D0280E090E00D\r\n:103DD0000E94EA1F082F10E0102F002710932C02DA\r\n:103DE00000932B0281E090E00E94EA1F082B1093C1\r\n:103DF0002C0200932B0210922A02609128027091EB\r\n:103E00002902061717078CF470932C0260932B027B\r\n:103E100081E090E00E94F21F6091290280E090E032\r\n:103E20000E94F21F81E080932A02109210021092E9\r\n:103E30000F0280E00E94D50C4DE351E060E080E08D\r\n:103E40000E94C90A4FE251E061E080E00E94C90A85\r\n:103E50004DE351E063E080E00E94C90A4FE451E085\r\n:103E600062E080E00E94C90A409128025091290234\r\n:103E700062E070E08CE290E00E941B0B0E944D0D0E\r\n:103E80008823E1F364EC79E080E090E00E94AF05E4\r\n:103E900080E00E94D50C4AE351E060E080E00E949F\r\n:103EA000C90A4AE351E063E080E00E94C90A4091F8\r\n:103EB0002B0250912C0262E070E088E190E00E94B9\r\n:103EC0001B0B80912A02811106C04AE451E061E097\r\n:103ED0000E94C90A12C046E551E061E080E00E94FC\r\n:103EE000C90A0CEB12E0B8018EE190E00E944A0B87\r\n:103EF00002531109083C1105B1F70E944D0D8823AA\r\n:103F0000E1F364EC79E080E090E0D1C90E944D0DCE\r\n:103F10008823E1F365E070E080E090E00E94AF0567\r\n:103F2000CFC980915504813009F0CEC80E94631337\r\n:103F3000CBC8DE80DB82C8CB80915404813009F489\r\n:103F4000FCC984E690E00E94ED0C0E944D0D882390\r\n:103F5000E1F3EEC910928F0410928E048DE191E08E\r\n:103F600090938D0480938C040895BB274A3031F4DC\r\n:103F7000992322F4BDE2909581959F4F0C94C11F27\r\n:103F8000BB27FB015527AA27880F991FAA1FA41733\r\n:103F900010F0A41B83955051B9F7A05DAA3308F027\r\n:103FA000A95DA193009779F7B111B1931192CB015B\r\n:103FB0000C94DA1FDC01FC01672F71917723E1F784\r\n:103FC000329704C07C916D9370836291AE17BF07E6\r\n:103FD000C8F30895F999FECF92BD81BDF89A99274B\r\n:103FE00080B50895262FF999FECF1FBA92BD81BDE5\r\n:103FF00020BD0FB6F894FA9AF99A0FBE019608956B\r\n:10400000052E97FB1EF400940E94172057FD07D041\r\n:104010000E942A2007FC03D04EF40C9417205095E0\r\n:104020004095309521953F4F4F4F5F4F08959095A4\r\n:104030008095709561957F4F8F4F9F4F08950E9497\r\n:104040004C20A59F900DB49F900DA49F800D911DB5\r\n:1040500011240895A1E21A2EAA1BBB1BFD010DC05D\r\n:10406000AA1FBB1FEE1FFF1FA217B307E407F50728\r\n:1040700020F0A21BB30BE40BF50B661F771F881F04\r\n:10408000991F1A9469F760957095809590959B019A\r\n:10409000AC01BD01CF010895A29FB001B39FC00143\r\n:1040A000A39F700D811D1124911DB29F700D811D64\r\n:1040B0001124911D08950E940F2188F09F5798F0B8\r\n:1040C000B92F9927B751B0F0E1F0660F771F881F1D\r\n:1040D000991F1AF0BA95C9F714C0B13091F00E9437\r\n:1040E0004121B1E008950C944121672F782F882752\r\n:1040F000B85F39F0B93FCCF3869577956795B3955E\r\n:10410000D9F73EF490958095709561957F4F8F4FCC\r\n:104110009F4F0895E89409C097FB3EF490958095D1\r\n:10412000709561957F4F8F4F9F4F9923A9F0F92F7D\r\n:1041300096E9BB279395F695879577956795B795FB\r\n:10414000F111F8CFFAF4BB0F11F460FF1BC06F5FE1\r\n:104150007F4F8F4F9F4F16C0882311F096E911C0F3\r\n:10416000772321F09EE8872F762F05C0662371F014\r\n:1041700096E8862F70E060E02AF09A95660F771F28\r\n:10418000881FDAF7880F9695879597F908950E940A\r\n:10419000292190F09F3748F4911116F00C94422198\r\n:1041A00060E070E080E89FEB089526F41B16611D27\r\n:1041B000711D811D0C94DE200C94F920882371F46C\r\n:1041C000772321F09850872B762F07C0662311F4B0\r\n:1041D00099270DC09051862B70E060E02AF09A95E7\r\n:1041E000660F771F881FDAF7880F9695879597F9DE\r\n:1041F00008959F3F31F0915020F48795779567950A\r\n:10420000B795880F911D9695879597F9089557FD55\r\n:104210009058440F551F59F05F3F71F04795880F34\r\n:1042200097FB991F61F09F3F79F0879508951216CB\r\n:1042300013061406551FF2CF4695F1DF08C0161677\r\n:1042400017061806991FF1CF869571056105089428\r\n:1042500008950E940F21A0F0BEE7B91788F4BB278C\r\n:104260009F3860F41616B11D672F782F8827985F46\r\n:10427000F7CF869577956795B11D93959639C8F3D5\r\n:104280000895E894BB2766277727CB0197F908950F\r\n:104290000E945B210C94CC210E94BE2138F00E9428\r\n:1042A000C52120F0952311F00C94B5210C94BB216D\r\n:1042B00011240C9442210E94072170F3959FC1F3B1\r\n:1042C000950F50E0551F629FF001729FBB27F00DC4\r\n:1042D000B11D639FAA27F00DB11DAA1F649F662719\r\n:1042E000B00DA11D661F829F2227B00DA11D621F68\r\n:1042F000739FB00DA11D621F839FA00D611D221F22\r\n:10430000749F3327A00D611D231F849F600D211D05\r\n:10431000822F762F6A2F11249F5750409AF0F1F088\r\n:1043200088234AF0EE0FFF1FBB1F661F771F881FF1\r\n:1043300091505040A9F79E3F510580F00C94B52153\r\n:104340000C9442215F3FE4F3983ED4F38695779531\r\n:104350006795B795F795E7959F5FC1F7FE2B880F97\r\n:10436000911D9695879597F9089597F99F6780E82D\r\n:1043700070E060E008959FEF80EC089500240A94B7\r\n:104380001616170618060906089500240A94121630\r\n:104390001306140605060895092E0394000C11F463\r\n:1043A000882352F0BB0F40F4BF2B11F460FF04C010\r\n:1043B0006F5F7F4F8F4F9F4F0895DB018F939F93C8\r\n:1043C0000E941F20BF91AF91A29F800D911DA39FBE\r\n:1043D000900DB29F900D11240895991B79E004C0AF\r\n:1043E000991F961708F0961B881F7A95C9F7809534\r\n:1043F000089597FB072E16F4009407D077FD09D097\r\n:104400000E940D2207FC05D03EF4909581959F4FA8\r\n:104410000895709561957F4F0895AA1BBB1B51E1CC\r\n:1044200007C0AA1FBB1FA617B70710F0A61BB70B24\r\n:10443000881F991F5A95A9F780959095BC01CD01C9\r\n:104440000895EE0FFF1F0590F491E02D099481E08F\r\n:0C44500090E0F8940C942C22F894FFCF1C\r\n:10445C0001030002000400020002000300FEFFFD45\r\n:10446C00FFFCFFFCFFFDFFFBFF00000000090CEB55\r\n:10447C00037A04790420204C4556454C20200047F3\r\n:10448C00414D4520204F564552002D2D2D2D2D2DC3\r\n:10449C002D2D2D2D2D2D2D2D2D00484947482053E8\r\n:1044AC00434F52453A004E455720484947483A0039\r\n:1044BC0048492053434F52452052455345540046DA\r\n:1044CC002052204F204720472045205200616E6427\r\n:1044DC0079206A61636B736F6E0050726573732021\r\n:1044EC00412E2E2E000D0A004C4F41444552000027\r\n:00000001FF\r\n"
  },
  {
    "path": "Frogger_MAKERbuino/font6x8AJ4.h",
    "content": "/*\n * Font file - originally from SSD1306xLED - Drivers for SSD1306 controlled dot matrix OLED/PLED 128x64 displays\n *\n * @file: font6x8AJ4.h\n * @created: 2014-08-12, edited by andy jackson 2018 (see below)\n * @author: Neven Boyanov\n * \n * Hacked by andy jackson to optimise size for the AttinyArcade - hence several characters \n * are missing and a couple have been moved to limit the amount of software remapping required\n * to map ASCII values onto locations in this array.\n *\n * Source code available at: https://bitbucket.org/tinusaur/ssd1306xled\n *\n */\n\n// ----------------------------------------------------------------------------\n\n#include <avr/pgmspace.h>\n\n// ----------------------------------------------------------------------------\n\n/* Standard ASCII 6x8 font */\nstatic const uint8_t lcdDisplayxled_font6x8 [] PROGMEM = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sp\n/*\n  0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // !\n  0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // \"\n  0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // #\n  0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $\n  0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // %\n  0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // &\n  0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // '\n  0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // (\n  0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // )\n  0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // *\n  0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // +\n  0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // ,\n  */\n  0x00, 0x00, 0x08, 0x08, 0x08, 0x00, // -\n  0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // .\n  0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // /\n  0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0\n  0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, // 1\n  0x00, 0x42, 0x61, 0x51, 0x49, 0x46, // 2\n  0x00, 0x21, 0x41, 0x45, 0x4B, 0x31, // 3\n  0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, // 4\n  0x00, 0x27, 0x45, 0x45, 0x45, 0x39, // 5\n  0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6\n  0x00, 0x01, 0x71, 0x09, 0x05, 0x03, // 7\n  0x00, 0x36, 0x49, 0x49, 0x49, 0x36, // 8\n  0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, // 9\n  0x00, 0x00, 0x36, 0x36, 0x00, 0x00, // :\n/*\n  0x00, 0x00, 0x56, 0x36, 0x00, 0x00, // ;\n  0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // <\n  0x00, 0x14, 0x14, 0x14, 0x14, 0x14, // =\n  0x00, 0x00, 0x41, 0x22, 0x14, 0x08, // >\n  0x00, 0x02, 0x01, 0x51, 0x09, 0x06, // ?\n  0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, // @\n */\n  0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, // B\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, // C\n  0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, // D\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, // E\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, // F\n  0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, // G\n  0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, // H\n  0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, // I\n  0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, // J\n  0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, // K\n  0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, // L\n  0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M\n  0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, // N\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, // O\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, // P\n  0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q\n  0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, // R\n  0x00, 0x46, 0x49, 0x49, 0x49, 0x31, // S\n  0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, // T\n  0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, // U\n  0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, // V\n  0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, // W\n  /*\n  0x00, 0x63, 0x14, 0x08, 0x14, 0x63, // X\n  0x00, 0x07, 0x08, 0x70, 0x08, 0x07, // Y\n  0x00, 0x61, 0x51, 0x49, 0x45, 0x43, // Z\n  0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, // [\n  0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55, // 55\n  0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, // ]\n  0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^\n  0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _\n  0x00, 0x00, 0x01, 0x02, 0x04, 0x00, // '\n*/\n  0x00, 0x20, 0x54, 0x54, 0x54, 0x78, // a\n  0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, // b\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x20, // c\n  0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, // d\n  0x00, 0x38, 0x54, 0x54, 0x54, 0x18, // e\n  0x00, 0x08, 0x7E, 0x09, 0x01, 0x02, // f\n  0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g\n  0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h\n  0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, // i\n  0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, // j\n  0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, // k\n  0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, // l\n  0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, // m\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, // n\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x38, // o\n  0x00, 0xFC, 0x24, 0x24, 0x24, 0x18, // p\n  0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, // q\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, // r\n  0x00, 0x48, 0x54, 0x54, 0x54, 0x20, // s\n  0x00, 0x04, 0x3F, 0x44, 0x40, 0x20, // t\n  0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, // u\n  0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, // v\n  0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w\n  0x00, 0x44, 0x28, 0x10, 0x28, 0x44, // x\n  0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C  // y\n};\n\n// ----------------------------------------------------------------------------\n\r\n"
  },
  {
    "path": "MorseAttinyArcade/MorseAttinyArcade.ino",
    "content": "/*  2015 / 2016 / 2017\n *  Morse decoder for Attiny85 and the #AttinyArcade by Andy Jackson (M0RCL) - Twitter @andyhighnumber\n *   \n *  Displays morse code coming in on the assigned pin in real time, via a 5-line scrolling display \n *   \n *  Inspired by, and designed to run on the Attiny Arcade hardware. Check out www.webboggles.com for info on this hardware.\n *   \n *  When running, use:\n *   - The right button to send morse\n *   - The left button to start and stop the software running\n *   \n *  Any code not covered by the licences below can be used freely with attribution. No warranties whatsoever are provided or implied.\n *   \n *  ****************************************************************************************************\n *  * The core morse decoder here is a slightly modified version of WB7FHC's Morse Code Decoder v. 1.1 *\n *  * (c) 2014, Budd Churchward - WB7FHC                                                               *\n *  * This is an Open Source Project                                                                   *\n *  * http://opensource.org/licenses/MIT                                                               *\n *  * Search YouTube for 'WB7FHC' to see several videos of this project as it was developed.           *\n *  * Also see https://github.com/kareiva/wb7fhc-cw-decoder                                            *\n *  ****************************************************************************************************\n *  \n *  This sketch is using the screen control and font functions written by Neven Boyanov for the http://tinusaur.wordpress.com/ project\n *  Source code and font files available at: https://bitbucket.org/tinusaur/ssd1306xled\n * \n *  Sleep code is based on this blog post by Matthew Little:\n *  http://www.re-innovation.co.uk/web12/index.php/en/blog-75/306-sleep-modes-on-attiny85\n */\n \n#include <EEPROM.h>\n#include \"font6x8AJ.h\"\n#include <avr/pgmspace.h>\n#include <avr/sleep.h>\n#include <avr/interrupt.h> // needed for the additional interrupt\n\n#define DIGITAL_WRITE_HIGH(PORT) PORTB |= (1 << PORT)\n#define DIGITAL_WRITE_LOW(PORT) PORTB &= ~(1 << PORT)\n\n// Routines to set and clear bits (used in the sleep code)\n#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))\n#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))\n\n// Defines for OLED output\n#define SSD1306XLED_H\n#define SSD1306_SCL   PORTB4  // SCL, Pin 4 on SSD1306 Board - for webbogles board\n#define SSD1306_SDA   PORTB3  // SDA, Pin 3 on SSD1306 Board - for webbogles board\n#define SSD1306_SA    0x78  // Slave address\n\n#define FIRSTLINE 2     // The first displayed line of decoded morse on the LCD\n#define LASTLINE 6      // The last displayed line of decoded morse on the LCD\n#define LINELENGTH 20   // The number of characters on one completed line\n#define MAXWORD 17      // The longest any single word can be (needed to manage buffer limits)\n\n// Drawing functions - adapted from those at https://bitbucket.org/tinusaur/ssd1306xled\nvoid ssd1306_init(void);\nvoid ssd1306_xfer_start(void);\nvoid ssd1306_xfer_stop(void);\nvoid ssd1306_send_byte(uint8_t byte);\nvoid ssd1306_send_command(uint8_t command);\nvoid ssd1306_send_data_start(void);\nvoid ssd1306_send_data_stop(void);\nvoid ssd1306_setpos(uint8_t x, uint8_t y);\nvoid ssd1306_fillscreen(uint8_t fill_Data);\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, char ch[]);\nvoid ssd1306_draw_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t bitmap[]);\n\n// Custom draw functions - allow for extra functionality like inverse display\nvoid sendBlock(byte, bool);\nvoid sendByte(byte, bool);\n\nint stopRunning = 0;\n\n// Other generic functions (both originated in code from webboggles.com and the sleep code is by Matthew Little - see above)\nvoid beep(int,int);\nvoid system_sleep(void);\nvoid doNumber (int,int,int);\n\n// Specific main function to decode morse\nvoid decodeMorse(void);\n\n// Variable declarations for decoder\nint inputPin = 2;         // input data comes in here (key or decoder)\nint audio = 1;            // will store the value we read on this pin\nboolean mute = 0;         // Mute the speaker\nint letterCount = 0;\nint LCDline = FIRSTLINE;          // keeps track of which line we're printing on\nboolean ditOrDah = true;  // We have either a full dit or a full dah\nint dit;            \n\n// The following values will auto adjust to the sender's speed\nint averageDah;                   // A dah should be 3 times as long as a dit\nint averageWordGap;               // will auto adjust\n\nboolean characterDone = true; // A full character has been sent\n\nint downTime = 0;        // How long the tone was on in milliseconds\nint upTime = 0;          // How long the tone was off in milliseconds\nint myBounce = 2;        // Used as a short delay between key up and down\nlong startDownTime = 0;  // Arduino's internal timer when tone first comes on\nlong startUpTime = 0;    // Arduino's internal timer when tone first goes off\n\nint currentWordLength = 0;\nint currentWordPos = 0;\nchar currentWord[MAXWORD];\nchar screenText[LASTLINE-FIRSTLINE+1][LINELENGTH+1];\nint lastWordLength = 0;\n\nboolean justDid = true; // Makes sure we only print one space during long gaps\n\nint myNum = 0;           // We will turn dits and dahs into a binary number stored here\nchar mySet[] =\"##TEMNAIOGKDWRUS##QZYCXBJP#L#FVH09#8###7#####/-61#######2###3#45\";\nchar decodedCharacter = ' ';       // We will store the actual character decoded here\n\n// Interrupt handlers\nISR(PCINT0_vect){ // PB0 pin button interrupt           \n  stopRunning = 1; // stop the programme :)\n}\n\nvoid playerIncMorse(){ // PB2 pin button interrupt\n}\n\n\n// Arduino stuff - setup\nvoid setup() {\n  DDRB = 0b00000010;    // set PB1 as output (for the speaker)\n  PCMSK = 0b00000001; // pin change mask: listen to portb bit 1\n  GIMSK |= 0b00100000;  // enable PCINT interrupt \n  sei();          // enable all interrupts\n}\n\n// Arduino stuff - loop\nvoid loop() { \n//  pinMode(2, INPUT_PULLUP);\n//  pinMode(1, OUTPUT);\n  \n  ssd1306_init();\n  ssd1306_fillscreen(0x00);\n\n  ssd1306_char_f6x8(0, 0, \"  M O R S E\");\n  ssd1306_char_f6x8(0, 1, \"      D E C O D E R\");\n  ssd1306_char_f6x8(27, 5, \"andy jackson\"); // see comments above !\n\n  ssd1306_setpos(16,2); \n  for (int incr = 16; incr < 112; incr++) {\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00001010);\n    ssd1306_send_data_stop();                    \n  }\n  ssd1306_setpos(27,4); \n  for (int incr = 0; incr < 72; incr++) {\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00100000);\n    ssd1306_send_data_stop();                    \n  }\n  ssd1306_setpos(27,6); \n  for (int incr = 0; incr < 72; incr++) {\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B00000100);\n    ssd1306_send_data_stop();                    \n  }\n\n  delay(1500);\n\n  long startT = millis();\n  long nowT =0;\n  boolean sChange = 0;\n\n  while(digitalRead(0) == HIGH) {\n    nowT = millis();\n    if (nowT - startT > 2000) {\n      sChange = 1;     \n      if (mute == 0) { mute = 1; ssd1306_char_f6x8(32, 7, \"-- MUTE --\"); } else { mute = 0; ssd1306_char_f6x8(31, 7, \"- SOUND ON -\");  }    \n      break;\n    }\n    if (sChange == 1) break;\n  }  \n  while(digitalRead(0) == HIGH);\n\n  if (sChange == 0) {\n    delay(1500);\n    \n    ssd1306_init();\n    ssd1306_fillscreen(0x00);\n  \n    stopRunning = 0;\n  \n    decodeMorse(); \n  \n    ssd1306_fillscreen(0x00);\n    ssd1306_char_f6x8(11, 1, \"----------------\");\n    ssd1306_char_f6x8(11, 2, \" S T O P P E D\");\n    ssd1306_char_f6x8(11, 3, \"----------------\");\n    ssd1306_char_f6x8(0, 6, \"          bye...\"); \n\n    delay(1200);    \n  }\n  system_sleep();\n}\n\nvoid doNumber (int x, int y, int value) {\n    char temp[10] = {0,0,0,0,0,0,0,0,0,0};\n    itoa(value,temp,10);\n    ssd1306_char_f6x8(x, y, temp);\n}\n\nvoid ssd1306_init(void){\n  DDRB |= (1 << SSD1306_SDA); // Set port as output\n  DDRB |= (1 << SSD1306_SCL); // Set port as output\n\n  ssd1306_send_command(0xAE); // display off\n  ssd1306_send_command(0x00); // Set Memory Addressing Mode\n  ssd1306_send_command(0x10); // 00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid\n  ssd1306_send_command(0x40); // Set Page Start Address for Page Addressing Mode,0-7\n  ssd1306_send_command(0x81); // Set COM Output Scan Direction\n  ssd1306_send_command(0xCF); // ---set low rowumn address\n  ssd1306_send_command(0xA1); // ---set high rowumn address\n  ssd1306_send_command(0xC8); // --set start line address\n  ssd1306_send_command(0xA6); // --set contrast control register\n  ssd1306_send_command(0xA8);\n  ssd1306_send_command(0x3F); // --set segment re-map 0 to 127\n  ssd1306_send_command(0xD3); // --set normal display\n  ssd1306_send_command(0x00); // --set multiplex ratio(1 to 64)\n  ssd1306_send_command(0xD5); // \n  ssd1306_send_command(0x80); // 0xa4,Output follows RAM content;0xa5,Output ignores RAM content\n  ssd1306_send_command(0xD9); // -set display offset\n  ssd1306_send_command(0xF1); // -not offset\n  ssd1306_send_command(0xDA); // --set display clock divide ratio/oscillator frequency\n  ssd1306_send_command(0x12); // --set divide ratio\n  ssd1306_send_command(0xDB); // --set pre-charge period\n  ssd1306_send_command(0x40); // \n  ssd1306_send_command(0x20); // --set com pins hardware configuration\n  ssd1306_send_command(0x02);\n  ssd1306_send_command(0x8D); // --set vcomh\n  ssd1306_send_command(0x14); // 0x20,0.77xVcc\n  ssd1306_send_command(0xA4); // --set DC-DC enable\n  ssd1306_send_command(0xA6); // \n  ssd1306_send_command(0xAF); // --turn on oled panel \n}\n\nvoid ssd1306_xfer_start(void){\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n}\n\nvoid ssd1306_xfer_stop(void){\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n}\n\nvoid ssd1306_send_byte(uint8_t byte){\n  uint8_t i;\n  for(i=0; i<8; i++)\n  {\n    if((byte << i) & 0x80)\n      DIGITAL_WRITE_HIGH(SSD1306_SDA);\n    else\n      DIGITAL_WRITE_LOW(SSD1306_SDA);\n    \n    DIGITAL_WRITE_HIGH(SSD1306_SCL);\n    DIGITAL_WRITE_LOW(SSD1306_SCL);\n  }\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);\n  DIGITAL_WRITE_LOW(SSD1306_SCL);\n}\n\nvoid ssd1306_send_command(uint8_t command){\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  // Slave address, SA0=0\n  ssd1306_send_byte(0x00);  // write command\n  ssd1306_send_byte(command);\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_send_data_start(void){\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);\n  ssd1306_send_byte(0x40);  //write data\n}\n\nvoid ssd1306_send_data_stop(void){\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_setpos(uint8_t x, uint8_t y)\n{\n  if (y>7) return;\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  //Slave address,SA0=0\n  ssd1306_send_byte(0x00);  //write command\n\n  ssd1306_send_byte(0xb0+y);\n  ssd1306_send_byte(((x&0xf0)>>4)|0x10); // |0x10\n  ssd1306_send_byte((x&0x0f)|0x01); // |0x01\n\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_fillscreen(uint8_t fill_Data){\n  uint8_t m,n;\n  for(m=0;m<8;m++)\n  {\n    ssd1306_send_command(0xb0+m); //page0-page1\n    ssd1306_send_command(0x00);   //low rowumn start address\n    ssd1306_send_command(0x10);   //high rowumn start address\n    ssd1306_send_data_start();\n    for(n=0;n<128;n++)\n    {\n      ssd1306_send_byte(fill_Data);\n    }\n    ssd1306_send_data_stop();\n  }\n}\n\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, char ch[]){\n  uint8_t c,i,j=0;\n  while(ch[j] != '\\0')\n  {\n    c = ch[j] - 32;\n    if(x>126)\n    {\n      x=0;\n      y++;\n    }\n    ssd1306_setpos(x,y);\n    ssd1306_send_data_start();\n    for(i=0;i<6;i++)\n    {\n      ssd1306_send_byte(pgm_read_byte(&ssd1306xled_font6x8[c*6+i]));\n    }\n    ssd1306_send_data_stop();\n    x += 6;\n    j++;\n  }\n}\n\nvoid system_sleep(void) {\n  ssd1306_fillscreen(0x00);\n  ssd1306_send_command(0xAE);\n  cbi(ADCSRA,ADEN);                    // switch analog to digital converter off\n  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here\n  sleep_enable();\n  sleep_mode();                        // system actually sleeps here\n  sleep_disable();                     // system continues execution here when watchdog timed out \n  sbi(ADCSRA,ADEN);                    // switch analog to digital converter on\n  ssd1306_send_command(0xAF);\n}\n\nvoid beep(int bCount,int bDelay){\n  if (mute) return;\n  for (int i = 0; i<=bCount; i++){digitalWrite(1,HIGH);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}digitalWrite(1,LOW);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}}\n}\n\n\n/* ------------------------\n *  Main code\n */\nvoid decodeMorse(){\n  int wpm = 0;\n\n  averageDah = 240;             // Starting point for auto-adjusting speed\n  averageWordGap = averageDah;  // Will auto adjust\n  dit = averageDah / 3;         \n  lastWordLength = 0;\n  letterCount = 0;\n  LCDline = FIRSTLINE; \n  currentWordLength = 0;\n  currentWordPos = 0;\n\n  for (int i = 700; i>200; i = i - 50){\n   beep(30,i);\n  }\n\n  ssd1306_char_f6x8(0, 0, \"Listening.. WPM:\");\n  wpm = floor(1200 / (float(averageDah/3.0)) );\n  doNumber(96,0,wpm);\n\n  while(stopRunning == 0) {\n     audio = digitalRead(inputPin); // What is the tone decoder doing?\n  \n     if (audio) { \n        keyIsDown();\n        while(audio) {\n          beep(50,250);\n          audio = digitalRead(inputPin);\n        }\n        }      \n     if (!audio) { \n        keyIsUp(); \n      }        \n  }\n} \n\n\nvoid keyIsDown() {\n   // The decoder is detecting our tone\n   // The LEDs on the decoder and Arduino will blink on in unison\n   \n   \n   if (startUpTime>0){\n     // We only need to do once, when the key first goes down\n     startUpTime=0;    // clear the 'Key Up' timer\n     }\n   // If we haven't already started our timer, do it now\n   if (startDownTime == 0){\n       startDownTime = millis();  // get Arduino's current clock time\n      }\n\n     characterDone=false; // we're still building a character\n     ditOrDah=false;      // the key is still down we're not done with the tone\n     delay(myBounce);     // Take a short breath here\n     \n   if (myNum == 0) {      // myNum will equal zero at the beginning of a character\n      myNum = 1;          // This is our start bit  - it only does this once per letter\n      }\n }\n \n  void keyIsUp() {\n   // The decoder does not detect our tone\n   // The LEDs on the decoder and Arduino will blink off in unison \n   \n   // If we haven't already started our timer, do it now\n   if (startUpTime == 0){startUpTime = millis();}\n   \n   // Find out how long we've gone with no tone\n   // If it is twice as long as a dah print a space\n   upTime = millis() - startUpTime;\n   if (upTime<10)return;\n   if (upTime > (averageDah*2)) {    \n      printSpace();\n   }\n   \n   // Only do this once after the key goes up\n   if (startDownTime > 0){\n     downTime = millis() - startDownTime;  // how long was the tone on?\n     startDownTime=0;      // clear the 'Key Down' timer\n   }\n \n   if (!ditOrDah) {   \n     // We don't know if it was a dit or a dah yet\n      shiftBits();    // let's go find out! And do our Magic with the bits\n    }\n\n    // If we are still building a character ...\n    if (!characterDone) {\n       // Are we done yet?\n       if (upTime > dit) { \n         // BINGO! we're done with this one  \n         printCharacter();       // Go figure out what character it was and print it       \n         characterDone=true;     // We got him, we're done here\n         myNum=0;                // This sets us up for getting the next start bit\n         }\n         downTime=0;               // Reset our keyDown counter\n       }\n   }\n   \n   \nvoid shiftBits() {\n \n  // we know we've got a dit or a dah, let's find out which\n  // then we will shift the bits in myNum and then add 1 or not add 1\n  \n  if (downTime < dit / 3) return;  // ignore my keybounce\n  \n  myNum = myNum << 1;   // shift bits left\n  ditOrDah = true;        // we will know which one in two lines \n  \n  \n  // If it is a dit we add 1. If it is a dah we do nothing!\n  if (downTime < dit) {\n     myNum++;           // add one because it is a dit\n     } else {\n  \n    // The next three lines handle the automatic speed adjustment:\n    averageDah = (downTime+averageDah) / 2;  // running average of dahs\n\n    if (averageDah > 1000) averageDah = 1000; // limiting slowest speed to about 3wpm !\n   \n    dit = averageDah / 3;                    // normal dit would be this\n    dit = dit * 2;    // double it to get the threshold between dits and dahs\n     }\n  }\n\n\nvoid printCharacter() {           \n  justDid = false;         // OK to print a space again after this\n\n  if (myNum == 511) {\n    deleteLastWord();\n    return;\n  }\n  \n  // Punctuation marks will make a BIG myNum\n  if (myNum > 63) {  \n    printPunctuation();  // The value we parsed is bigger than our character array\n                         // It is probably a punctuation mark so go figure it out.\n    return;              \n  }\n  decodedCharacter = mySet[myNum]; \n  \n  if (currentWordLength < MAXWORD) {\n    currentWord[currentWordPos] = decodedCharacter;\n    currentWordLength++;\n    currentWordPos++;\n    lastWordLength = currentWordLength; // this will ensure that lastWordLength is always the length of the most recent word\n  } else printSpace();\n  sendToLCD();      \n}\n\nvoid printSpace() {\n  int wpm;\n\n  if (justDid) return;  // only one space, no matter how long the gap\n  justDid = true;       // so we don't do this twice\n\n  currentWordLength = 0;\n  currentWordPos = 0;\n\n  wpm = floor(1200 / (float(averageDah/3.0)) );\n  ssd1306_char_f6x8(96, 0, \"   \");\n  doNumber(96,0,wpm);\n  \n  // We keep track of the average gap between words and bump it up 20 milliseconds\n  // do avoid false spaces within the word\n  averageWordGap = ((averageWordGap + upTime) / 2) + 20;\n\n  decodedCharacter=' ';            // this is going to go to the LCD \n  \n  sendToLCD();         // go figure out where to put it on the display\n}\n\nvoid printPunctuation() {\n  // Punctuation marks are made up of more dits and dahs than\n  // letters and numbers. Rather than extend the character array\n  // out to reach these higher numbers we will simply check for\n  // them here. This funtion only gets called when myNum is greater than 63\n  \n  // Thanks to Jack Purdum for the changes in this function\n  // The original uses if then statements and only had 3 punctuation\n  // marks. Then as I was copying code off of web sites I added\n  // characters we don't normally see on the air and the list got\n  // a little long. Using 'switch' to handle them is much better.\n\n  lastWordLength = currentWordLength; // this will ensure that lastWordLength is always the length of the most recent word\n  \n  switch (myNum) {\n    case 71:\n      decodedCharacter = ':';\n      break;\n    case 76:\n      decodedCharacter = ',';\n      break;\n    case 84:\n      decodedCharacter = '!';\n      break;\n    case 94:\n      decodedCharacter = '-';\n      break;\n    case 97:\n      decodedCharacter = 39;    // Apostrophe\n      break;\n    case 101:\n      decodedCharacter = '@';\n      break;\n    case 106:\n      decodedCharacter = '.';\n      break;\n    case 115:\n      decodedCharacter = '?';\n      break;\n    case 246:\n      decodedCharacter = '$';\n      break;\n    case 122:\n      decodedCharacter = 's';\n      sendToLCD();\n      decodedCharacter = 'k';\n      break;\n    default:\n      decodedCharacter = '#';    // Should not get here\n      break;\n  }\n  sendToLCD();    // go figure out where to put it on the display\n}\n\nvoid sendToLCD(){\n  uint8_t c,i;\n\n  screenText[LCDline-FIRSTLINE][letterCount] = decodedCharacter;\n  \n  c = decodedCharacter - 32;\n  ssd1306_setpos(letterCount*6,LCDline);\n  ssd1306_send_data_start();\n  for(i=0;i<6;i++)\n  {\n    ssd1306_send_byte(pgm_read_byte(&ssd1306xled_font6x8[c*6+i]));\n  }\n  ssd1306_send_data_stop();\n\n  letterCount++; \n\n  if (letterCount > LINELENGTH) {\n    newLine(); \n  }\n}\n\nvoid newLine() {\n    int scrollNow = 0;\n    int oldLine = LCDline;\n    int scrolled = 0;\n    \n    if (LCDline == LASTLINE) {scrollNow = 1; oldLine = LASTLINE-1; scrolled = 1;} else {LCDline++; scrollNow = 0;}\n    \n    if (scrollNow == 1) scrollUp();\n    blankLine(LCDline);\n    \n    letterCount = 0;\n\n\n    if (decodedCharacter > ' ') {   \n      for (int i = 0; i < currentWordLength; i++) {\n        decodedCharacter = currentWord[i];\n        sendToLCD();                        \n        screenText[oldLine-FIRSTLINE][LINELENGTH-i] = ' '; \n      }  \n      ssd1306_setpos(126-(currentWordLength*6),oldLine);\n      ssd1306_send_data_start();\n      for(int i=0;i<(currentWordLength*6);i++)\n      {\n        ssd1306_send_byte(0);\n      }\n      ssd1306_send_data_stop();\n    }\n}\n\nvoid blankLine(int line) {\n  uint8_t i;\n \n  ssd1306_setpos(0,LCDline);\n  ssd1306_send_data_start();\n  for(i=0;i<128;i++)\n  {\n    ssd1306_send_byte(0);\n  }\n  ssd1306_send_data_stop();\n}\n\nvoid scrollUp() {\n  int i,j,k,c;\n\n  for(i = 0; i < LASTLINE-FIRSTLINE; i++) {\n    for (j=0;j<LINELENGTH+1;j++) {\n      screenText[i][j] = screenText[i+1][j];\n      c = screenText[i][j] - 32;\n      ssd1306_setpos(j*6,i+FIRSTLINE);\n      ssd1306_send_data_start();\n      for(k=0;k<6;k++)\n      {\n        ssd1306_send_byte(pgm_read_byte(&ssd1306xled_font6x8[c*6+k]));\n      }\n      ssd1306_send_data_stop();      \n    }\n  }  \n}\n\nvoid deleteLastWord() {\n\n  if (lastWordLength < 1) return; \n\n  if (screenText[LCDline-FIRSTLINE][letterCount-1] == ' ') {\n    letterCount--;\n  }\n  letterCount--;\n\n  for(int i = 0; i < lastWordLength; i++) {\n    ssd1306_setpos(letterCount*6,LCDline);\n    ssd1306_send_data_start();\n    for(int k=0;k<6;k++)\n    {\n      ssd1306_send_byte(0);\n    }\n    ssd1306_send_data_stop();    \n    letterCount--;\n  }\n  letterCount++; // we will have gone one further back than the start of the deleted word\n  lastWordLength = 0;\n  if (letterCount < 0) letterCount = 0;\n  justDid = true; // we don't want to stick another space in after deleting\n}\n\n\r\n"
  },
  {
    "path": "MorseAttinyArcade/font6x8AJ.h",
    "content": "/*\n * SSD1306xLED - Drivers for SSD1306 controlled dot matrix OLED/PLED 128x64 displays\n *\n * @file: font6x8.h\n * @created: 2014-08-12\n * @author: Neven Boyanov\n * \n * Hacked by andy jackson to allow two games (originally by webboggles.com) to \n * fit onto an ATTiny85 at the same time - hence several characters are missing\n * and a couple have been moved to limit the amount of software remapping required\n * to map ASCII values onto locations in this array.\n *\n * Source code available at: https://bitbucket.org/tinusaur/ssd1306xled\n *\n */\n\n// ----------------------------------------------------------------------------\n\n#include <avr/pgmspace.h>\n\n// ----------------------------------------------------------------------------\n\n/* Standard ASCII 6x8 font */\nstatic const uint8_t ssd1306xled_font6x8 [] PROGMEM = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sp\n  0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // !\n  0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // \"\n  0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // #\n  0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $\n  0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // %\n  0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // &\n  0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // '\n  0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // (\n  0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // )\n  0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // *\n  0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // +\n  0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // ,\n  0x00, 0x08, 0x08, 0x08, 0x08, 0x08, // -\n  0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // .\n  0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // /\n  0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0\n  0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, // 1\n  0x00, 0x42, 0x61, 0x51, 0x49, 0x46, // 2\n  0x00, 0x21, 0x41, 0x45, 0x4B, 0x31, // 3\n  0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, // 4\n  0x00, 0x27, 0x45, 0x45, 0x45, 0x39, // 5\n  0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6\n  0x00, 0x01, 0x71, 0x09, 0x05, 0x03, // 7\n  0x00, 0x36, 0x49, 0x49, 0x49, 0x36, // 8\n  0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, // 9\n  0x00, 0x00, 0x36, 0x36, 0x00, 0x00, // :\n  0x00, 0x00, 0x56, 0x36, 0x00, 0x00, // ;\n  0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // <\n  0x00, 0x14, 0x14, 0x14, 0x14, 0x14, // =\n  0x00, 0x00, 0x41, 0x22, 0x14, 0x08, // >\n  0x00, 0x02, 0x01, 0x51, 0x09, 0x06, // ?\n  0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, // @\n  0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, // B\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, // C\n  0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, // D\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, // E\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, // F\n  0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, // G\n  0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, // H\n  0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, // I\n  0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, // J\n  0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, // K\n  0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, // L\n  0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M\n  0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, // N\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, // O\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, // P\n  0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q\n  0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, // R\n  0x00, 0x46, 0x49, 0x49, 0x49, 0x31, // S\n  0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, // T\n  0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, // U\n  0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, // V\n  0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, // W\n  0x00, 0x63, 0x14, 0x08, 0x14, 0x63, // X\n  0x00, 0x07, 0x08, 0x70, 0x08, 0x07, // Y\n  0x00, 0x61, 0x51, 0x49, 0x45, 0x43, // Z\n  0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, // [\n  0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55, // 55\n  0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, // ]\n  0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^\n  0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _\n  0x00, 0x00, 0x01, 0x02, 0x04, 0x00, // '\n  0x00, 0x20, 0x54, 0x54, 0x54, 0x78, // a\n  0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, // b\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x20, // c\n  0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, // d\n  0x00, 0x38, 0x54, 0x54, 0x54, 0x18, // e\n  0x00, 0x08, 0x7E, 0x09, 0x01, 0x02, // f\n  0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g\n  0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h\n  0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, // i\n  0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, // j\n  0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, // k\n  0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, // l\n  0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, // m\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, // n\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x38, // o\n  0x00, 0xFC, 0x24, 0x24, 0x24, 0x18, // p\n  0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, // q\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, // r\n  0x00, 0x48, 0x54, 0x54, 0x54, 0x20, // s\n  0x00, 0x04, 0x3F, 0x44, 0x40, 0x20, // t\n  0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, // u\n  0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, // v\n  0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w\n  0x00, 0x44, 0x28, 0x10, 0x28, 0x44, // x\n  0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C, // y\n  0x00, 0x44, 0x64, 0x54, 0x4C, 0x44, // z\n  0x14, 0x14, 0x14, 0x14, 0x14, 0x14, // horiz lines\n};\n\n// ----------------------------------------------------------------------------\n\r\n"
  },
  {
    "path": "PAK-MAN_MAKERbuino/HEX and INF/PAKMAN.HEX",
    "content": ":100000000C947F050C94A7050C94A7050C94A705E8\r\n:100010000C94A7050C94A7050C94A7050C94A705B0\r\n:100020000C94A7050C94A7050C94A7050C9436090D\r\n:100030000C94A7050C94A7050C94A7050C94A70590\r\n:100040000C94E1080C94A7050C94A7050C94A70543\r\n:100050000C94A7050C94A7050C94A7050C94A70570\r\n:100060000C94A7050C94A7050101FF030101F703F8\r\n:100070006C00680000000000240027002A00000037\r\n:100080000000250028002B000500893008023802F6\r\n:100090004978681400000500380168010000175312\r\n:1000A00044001613780016131400151020001520B4\r\n:1000B0001000540A03E181867F3E186D830F0F0EF6\r\n:1000C0000183866033186DC3198F1803C38E6033A4\r\n:1000D000186DE330CF1803C39E603630CDE360CF98\r\n:1000E0003006C79E7E3E30CDB360CF300CC6F66082\r\n:1000F0003330D9B660CF33CFCCF66061B0DB1E6051\r\n:10010000CF30D86CE6C061B0DB1E618F19986CC629\r\n:10011000C063B19B0E330F0FB078C6FF7E1F1B0666\r\n:100120001E0F401900000000000000000000000049\r\n:1001300000000000000000000000000000F80000C7\r\n:10014000007C000003FF000001FF000007FF8000AB\r\n:10015000037980000FFF8000062080000FFFC000A1\r\n:100160000C00C0001FFFC000080040001FFF00007F\r\n:1001700008E340003FF8000018E360003FE1999970\r\n:1001800098E360003FE19999980060003FF8000013\r\n:10019000180060003FFC0000180060001FFF000016\r\n:1001A000180060000FFFC00019CCE0000FFFC00076\r\n:1001B0001FFE600003FF00001DFFE00003FE0000C3\r\n:1001C00018CC600000F8000018CC600000000000AF\r\n:1001D000000000000000000000000000000000001F\r\n:1001E00000000000000000000000000050414B2D06\r\n:1001F0004D414E0000C0E0F0F8FCFCFEFEFEFFFFAB\r\n:10020000FFFFFEFEFEFCFCF8706000FEFFFFFFFF3C\r\n:10021000FFFFFFFFFFFFEFEFC787838301000010A1\r\n:10022000387C38100000000010387C381000070FB0\r\n:100230001F3F7F7F7F7FFFFFFFFFFFFF7F7F3F3FEE\r\n:100240003E1E1E000000000000000008080800001C\r\n:100250000060600000002010080402003E51494583\r\n:100260003E0000427F40000042615149460021416A\r\n:10027000454B31001814127F1000274545453900C1\r\n:100280003C4A494930000171090503003649494992\r\n:100290003600064949291E000036360000007C124F\r\n:1002A00011127C007F49494936003E4141412200FC\r\n:1002B0007F4141221C007F49494941007F090909CA\r\n:1002C00001003E4149497A007F0808087F0000414B\r\n:1002D0007F4100002040413F01007F08142241007F\r\n:1002E0007F40404040007F020C027F007F040810E6\r\n:1002F0007F003E4141413E007F09090906003E4121\r\n:1003000051215E007F0919294600464949493100BB\r\n:1003100001017F0101003F4040403F001F2040207D\r\n:100320001F003F4038403F002054545478007F481D\r\n:1003300044443800384444442000384444487F0052\r\n:10034000385454541800087E0901020018A4A4A4CB\r\n:100350007C007F080404780000447D400000408059\r\n:10036000847D00007F102844000000417F40000091\r\n:100370007C04180478007C08040478003844444461\r\n:100380003800FC242424180018242418FC007C08BD\r\n:1003900004040800485454542000043F4440200002\r\n:1003A0003C4040207C001C2040201C003C40304051\r\n:1003B0003C004428102844001CA0A0A07C3C7EFFE8\r\n:1003C000FFFFFF7E3C3C7EFFFFE7E7C3427CFE3F32\r\n:1003D0000F0F3FFE7C42C3E7E7FFFF7E3C3E7FFC02\r\n:1003E000F0F0FC7F3E7CFE22EBFF62EA7C7CC20ADE\r\n:1003F00083830A827C0E08180824082E0837083FD9\r\n:10040000084B0854085D0868086F0877080E141830\r\n:100410001424142E1437143F144B1454145D146810\r\n:100420001177110E1F181F241F2E1F5D1F68196FD3\r\n:1004300019771968256F2577250E2B182B242B2E5D\r\n:100440002B372B3F2B4B2B542B5D2B682E772E0EEF\r\n:1004500037183724372E3737373F374B3754375D08\r\n:100460003768376F37000C0C17171F1F22222D2DEE\r\n:10047000380E771C3C7E666662400000000000007B\r\n:1004800000F804F4141414141414141413100F00AA\r\n:10049000000000000000000F1013141414141414B2\r\n:1004A0001414E404E414141414141414141414147C\r\n:1004B0001414141414141414141414141414E4043C\r\n:1004C000E41414141414141414141414141414141C\r\n:1004D0001414141414141414141414E404E414144C\r\n:1004E00014141414141414141414141414141414CC\r\n:1004F000141414141414E404F800000000000000A4\r\n:1005000000FF00FF000000000000000040A0A0A0CD\r\n:10051000A0A0A0A0A0A0A0A0A040000000000000FB\r\n:100520000000FF00FF000000000000000040A0A04D\r\n:10053000A0A0A0A0A04000000000000000007F805C\r\n:100540007F000000000000000040A0A0A0A0A0A02C\r\n:10055000A0A04000000000000000007F807F00009D\r\n:10056000000000000000C020A0A0A0A020C000004B\r\n:10057000000000000000FF00FF000000000000007D\r\n:1005800000FF00FF0000000000000000000000006D\r\n:10059000000000000000000000000000000000005B\r\n:1005A0000000FF00FF00000000000000000000004D\r\n:1005B000000000000000000000000000000000003B\r\n:1005C000000000000000000000000000000000002B\r\n:1005D000000000000000000000000000000000001B\r\n:1005E0000000000000001F202F2F2F2F201F0000D1\r\n:1005F000000000000000FF00FF00000000000000FD\r\n:1006000000FF00FF0000000000000000FE01FE00EF\r\n:1006100000000000000000FE01FE000000000000DD\r\n:1006200000000708070000000000000000FE01FDB8\r\n:10063000050505050505050505050502000202027B\r\n:10064000020202000205050505050505050505056B\r\n:10065000FD01FE0000000000000000FE013E4040E1\r\n:1006600040404040404040404040404040800000CA\r\n:10067000000000000000FF00FF000000000000007C\r\n:1006800000FF00FF00000000000000007F807F00EE\r\n:10069000000000000000007F807F000000000000DC\r\n:1006A0000000C020C000000000000000007F809F0C\r\n:1006B000A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A03A\r\n:1006C000A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A02A\r\n:1006D0009F807F00000000000000007F807E0101FD\r\n:1006E00001010101010101010101010101000000FD\r\n:1006F000000000000000FF00FF00000000000000FC\r\n:1007000000FF00FF000000000000000000000000EB\r\n:1007100000000000000000000000000000000000D9\r\n:100720000000FF00FF0000000000000000000000CB\r\n:1007300000000000000000000000000000000000B9\r\n:1007400000000000000000000000000000000000A9\r\n:100750000000000000000000000000000000000099\r\n:10076000000000000000F804F4F4F4F404F80000C1\r\n:10077000000000000000FF00FF000000000000007B\r\n:1007800000FF00FF0000000000000000020505055A\r\n:10079000050505050505050505020000000000002A\r\n:1007A0000000FF00FF00000000000000000205053F\r\n:1007B0000505050505020000000000000000FE011F\r\n:1007C000FE0000000000000000020505050505050B\r\n:1007D0000505020000000000000000FE01FE000010\r\n:1007E00000000000000003040505050504030000E7\r\n:1007F000000000000000FF00FF00000000000000FB\r\n:10080000001F2027282828282828282828282828A2\r\n:100810002828282828282828282828282828282858\r\n:100820002828272027282828282828282828282852\r\n:100830002828282828282828282828282828272041\r\n:100840002728282828282828282828282828282829\r\n:100850002828282828282828282828C700FF00001A\r\n:10086000000000000000F008C828282828282828B0\r\n:1008700028282828282827201F0045006801000074\r\n:10088000F6E8DBCFC3B8AEA49B928A827B746E6815\r\n:10089000625C57524E4945413E3A3734312E2C293D\r\n:1008A000272523210A0A153A49676E6F7265006D84\r\n:1008B000560A0A504C45415345205455524E204F3C\r\n:1008C000464620004C4F572042415454455259212E\r\n:1008D000200003053F213F1208120A100A0E1C0EC9\r\n:1008E0000C1E0C141A14161F161E131E1E1B1E1E81\r\n:1008F0001F1E3F213F3A2F3A173D173F213F181F38\r\n:1009000002040A041F0E04040E1F0A1F0A0E0E1F03\r\n:1009100004110E2E252E2F2A2E262929021F020809\r\n:100920001F08150E04040E150E15151B151B0406C5\r\n:1009300004040C040000000017000300031F0A1F3A\r\n:1009400016371A1904130A153A000300000E111184\r\n:100950000E000A040A040E0400300004040400100F\r\n:10096000001804031F111F121F101D151711151F4A\r\n:1009700007041F17151D1F151D01011F1F151F1728\r\n:10098000151F000A00003200040A110A0A0A110A9F\r\n:10099000040115020E11171E051E1F150A0E110A5D\r\n:1009A0001F110E1F15111F05010E111D1F041F1110\r\n:1009B0001F1108100F1F041B1F10101F061F1E04FD\r\n:1009C0000F0E110E1F09060E112E1F051A12150902\r\n:1009D000011F011F101F0F180F1F0C1F1B041B03EB\r\n:1009E0001C03191513001F11030418111F00020125\r\n:1009F000022020200001020C121E1F120C0C1212E9\r\n:100A00000C121F0C1A14041E05242A1E1F021C148B\r\n:100A10001D1020201D1F0814111F101E041E1E0271\r\n:100A20001C0C120C3E0A040C123E1E040214160A80\r\n:100A3000020F120E101E0E100E1E081E120C122691\r\n:100A4000281E322A26041E21001F00211E04010236\r\n:100A5000013F213F172B152010204C4F4144455298\r\n:100A600000172B16201314000A4E6F2053442063E6\r\n:100A7000617264206F720A6E6F204C4F4144455280\r\n:100A80002E4845580A0A153A45786974001D2046D3\r\n:100A90006C617368696E670A20206C6F61646572AF\r\n:100AA0002E2E2E0A0A444F4E2754205455524E20C3\r\n:100AB0004F464621000000000023002600290004C4\r\n:100AC00004040404040404020202020202030303F5\r\n:100AD00003030301020408102040800102040810EF\r\n:100AE000200102040810200000000800020100009C\r\n:100AF000030407000000000000000000EC1F1124A8\r\n:100B00001FBECFEFD8E0DEBFCDBF11E0A0E0B1E067\r\n:100B1000E8EFF4E402C005900D92AE39B107D9F7C1\r\n:100B200024E0AEE9B1E001C01D92A73AB207E1F7B7\r\n:100B300015E0CFE7D5E004C02197FE010E946F22A7\r\n:100B4000CE37D107C9F70E942B170C947A220C9448\r\n:100B50000000CF92DF92EF92FF920F931F93CF93FB\r\n:100B6000DF936C017A018B01C0E0D0E0CE15DF0588\r\n:100B700089F0D8016D918D01D601ED91FC91019024\r\n:100B8000F081E02DC6010995892B11F47E0102C088\r\n:100B90002196ECCFC701DF91CF911F910F91FF906C\r\n:100BA000EF90DF90CF9008952F923F925F926F92D7\r\n:100BB0007F928F929F92AF92BF92CF92DF92EF92ED\r\n:100BC000FF920F931F93CF93DF93262F30E0C82F10\r\n:100BD000D0E0F90140E8849FE00DF11D1124E658B2\r\n:100BE000FB4F94915090BE01651508F460C0A52D8F\r\n:100BF000B0E0AD01495F5F4F421753070CF457C097\r\n:100C00004091BF01E42FE695E695E6958E1322C04C\r\n:100C10000091AE011091AF01F901EA1BFB0BA42F6B\r\n:100C2000A7700130110571F44091B6015091B701E0\r\n:100C3000B3E0440F551FBA95E1F7E40FF51FEB53EE\r\n:100C4000FC4F02C0E354FC4F449101C0440FAA95ED\r\n:100C5000EAF72EC0F0E03196CE17DF0741F500919C\r\n:100C6000AE011091AF01F901EA1BFB0BA42FA77095\r\n:100C70000130110571F44091B6015091B70173E054\r\n:100C8000440F551F7A95E1F7E40FF51FEB53FC4F26\r\n:100C900002C0E354FC4F449150E0E8E0F0E0EA1B6E\r\n:100CA000F10902C055954795EA95E2F701C040E089\r\n:100CB000942B6730B0F40091C5011091C60143E058\r\n:100CC000A6E0B0E0AC1BBD0BF901ED58FB4F84135F\r\n:100CD00005C0A017B10714F45491952B4F5F47300E\r\n:100CE000B1F70091AC01A0E0B0E058E0059F8001B1\r\n:100CF000112448E0E42EF12CFD01E854FE4F408120\r\n:100D00006417B8F150E06A0177E0C70ED11CC21633\r\n:100D1000D3067CF1D180ED2DE695E695E6958E1310\r\n:100D20000FC0F901E41BF50BE00FF11FEB51FC4F75\r\n:100D3000E4914D2D477001C0EE0F4A95EAF71AC0B5\r\n:100D4000F0E03196CE17DF07A1F4F901E41BF50BB3\r\n:100D5000E00FF11FEB51FC4FE491F0E04D2D477097\r\n:100D60006701C41AD10802C0F595E795CA94E2F765\r\n:100D700001C0E0E09E2B1296A630B10509F0BCCF71\r\n:100D80004FEF480F463008F070C0DE011197AA0FF0\r\n:100D9000BB1FFD01EB59FB4F94907090BF01A72C36\r\n:100DA000B12C47E0A40EB11C812CFD01EA59FB4F88\r\n:100DB0001F01EE24E394F12C052D10E0095F1F4F75\r\n:100DC000F1014491941608F051C0E92DF0E0AF0113\r\n:100DD00047525E4F6A01DA014C91442309F443C043\r\n:100DE000AF01440F551FFA01EB50FC4F64906611A0\r\n:100DF0003AC06490561430F5E491F0E00E171F07E6\r\n:100E00000CF1FA01EA50FC4F64907614D8F4E491A6\r\n:100E1000F0E0AE16BF06B4F0D6011C924091C001BE\r\n:100E20004F5F4093C001E091C701F091C80140912C\r\n:100E3000C3015091C4014E0F5F1F5093C8014093EE\r\n:100E4000C70114C0FA01EA50FC4F449146954695FB\r\n:100E50004695841339C0E491E770A70101C0440F9F\r\n:100E6000EA95EAF7842A9394ABCF812C9829E1E79D\r\n:100E7000F4E0CEE9D1E040E05C2F5E5F7991713023\r\n:100E800061F4863051F47491671731F0A491B0E0A9\r\n:100E900011962A173B0709F440EE31965C13EECF0A\r\n:100EA000892F842BDF91CF911F910F91FF90EF90AD\r\n:100EB000DF90CF90BF90AF909F908F907F906F907A\r\n:100EC0005F903F902F9008954491469546954695A2\r\n:100ED00050E04F5F5F4FC417D50709F0C4CFE491CE\r\n:100EE000C2CF089580E090E008950E94752283307B\r\n:100EF00081F028F4813099F08230A1F00895873094\r\n:100F0000A9F08830B9F08430D1F4809180008F7DD1\r\n:100F100003C0809180008F7780938000089584B50E\r\n:100F20008F7702C084B58F7D84BD08958091B00015\r\n:100F30008F7703C08091B0008F7D8093B0000895BB\r\n:100F40001F93CF93DF93282F30E0F901E951F54F3C\r\n:100F50008491F901ED52F54FD491F901E154F54F27\r\n:100F6000C491CC23C9F0162F81110E947707EC2F72\r\n:100F7000F0E0EE0FFF1FE258FF4FA591B4918FB73D\r\n:100F8000F894111105C09C91ED2FE095E92302C062\r\n:100F9000EC91ED2BEC938FBFDF91CF911F910895D2\r\n:100FA000CF93DF9390E0FC01ED52F54F2491FC01CB\r\n:100FB000E154F54F8491882361F190E0880F991FE7\r\n:100FC000FC01EC58FF4FC591D491FC01E258FF4F52\r\n:100FD000A591B491611109C09FB7F89488812095BB\r\n:100FE00082238883EC912E230BC0623061F49FB77B\r\n:100FF000F8943881822F809583238883EC912E2B5F\r\n:101000002C939FBF06C08FB7F894E8812E2B2883BE\r\n:101010008FBFDF91CF9108951F93CF93DF93182F48\r\n:10102000EB0161E00E94D007209711F460E004C05A\r\n:10103000CF3FD10539F461E0812FDF91CF911F912E\r\n:101040000C94A007E12FF0E0E951F54FE491E33073\r\n:10105000F9F048F4E130B9F0E230A1F584B58062EE\r\n:1010600084BDC8BD34C0E730E9F0E83019F1E430A0\r\n:1010700049F580918000806280938000D0938B003E\r\n:10108000C0938A0024C084B5806884BDC7BD1FC0DA\r\n:1010900080918000806880938000D0938900C09305\r\n:1010A000880015C08091B00080688093B000C09324\r\n:1010B000B3000DC08091B00080628093B000C093F7\r\n:1010C000B40005C0C038D1050CF0B5CFAFCFDF916B\r\n:1010D000CF911F9108958E3008F08E5087708064F4\r\n:1010E00080937C0080917A00806480937A00809164\r\n:1010F0007A0086FDFCCF809178002091790090E005\r\n:10110000922B08953FB7F8948091130290911402A6\r\n:10111000A0911502B091160226B5A89B05C02F3FDD\r\n:1011200019F00196A11DB11D3FBFBA2FA92F982F0D\r\n:101130008827820F911DA11DB11DBC01CD0142E088\r\n:10114000660F771F881F991F4A95D1F708958F92D0\r\n:101150009F92AF92BF92CF92DF92EF92FF926B017C\r\n:101160007C010E9482084B015C01C114D104E1049E\r\n:10117000F104F1F00E948208DC01CB018819990981\r\n:10118000AA09BB09883E9340A105B10570F321E08F\r\n:10119000C21AD108E108F10888EE880E83E0981E93\r\n:1011A000A11CB11CC114D104E104F10419F7DDCF75\r\n:1011B000FF90EF90DF90CF90BF90AF909F908F9077\r\n:1011C00008951F920F920FB60F9211242F933F9301\r\n:1011D0008F939F93AF93BF938091190290911A02BE\r\n:1011E000A0911B02B0911C023091120223E0230F48\r\n:1011F0002D3720F40196A11DB11D05C026E8230F4F\r\n:101200000296A11DB11D20931202809319029093A2\r\n:101210001A02A0931B02B0931C02809113029091BA\r\n:101220001402A0911502B09116020196A11DB11DE4\r\n:101230008093130290931402A0931502B0931602A8\r\n:10124000BF91AF919F918F913F912F910F900FBEC2\r\n:101250000F901F90189580911D04882319F080919C\r\n:101260001F0401C080E08093B40008951F920F9284\r\n:101270000FB60F9211242F933F934F935F936F9369\r\n:101280007F938F939F93AF93BF93EF93FF9360915F\r\n:101290001E04662321F1809111028F5F8093110259\r\n:1012A000909117028917D8F090911D0481E0892749\r\n:1012B00080931D041092110280911802882369F016\r\n:1012C0008091000193E4899F802D1124895B809394\r\n:1012D00000010E943B2290931F040E942B09FF9162\r\n:1012E000EF91BF91AF919F918F917F916F915F919E\r\n:1012F0004F913F912F910F900FBE0F901F90189517\r\n:101300001F93CF93DF93EC01162FF89460E08F8545\r\n:101310000E94A007888918161CF460E00E94A007AC\r\n:101320001EBD00000DB407FEFDCF8EB588891816CE\r\n:101330001CF461E00E94A0077894DF91CF911F9187\r\n:101340000895EF92FF921F93CF93DF93EC018C856A\r\n:101350008F5F8C878DE1E82E82E0F82E10E0612F00\r\n:101360006064CE010E94800960E8CE010E9480097D\r\n:1013700061E08F850E94A007888918161CF460E040\r\n:101380000E94A00780E090E0F701E80FF91F20819C\r\n:101390002EBD00000DB407FEFDCF2EB5019684359D\r\n:1013A000910591F7888918161CF461E00E94A00746\r\n:1013B0001F5F84E5E80EF11C163089F660E4CE016B\r\n:1013C000DF91CF911F91FF90EF900C9480091092C4\r\n:1013D000AC011092A3011092A201E6EAF1E01182A1\r\n:1013E000108213821282158214821092A50110922B\r\n:1013F000A401E8EBF1E082E480832CE12183A0EBFF\r\n:10140000B1E083E090E011969C938E9337E33283B2\r\n:10141000238313969C938E9312974DE444832583E4\r\n:1014200015969C938E931497368388E2878317963C\r\n:101430001C921E9216971092C2011092C10108953B\r\n:101440001092C0011092AD01E9EDF1E021E098E3C6\r\n:101450009E0F81E021939E13FCCF80939E01809389\r\n:101460009F0108950F931F93CF93DF93462F4695C7\r\n:1014700046954695962F97706FEF70E0EB01092E19\r\n:1014800002C0CC0FDD1F0A94E2F728E030E0291BF0\r\n:10149000310902C0759567952A95E2F7282F30E04B\r\n:1014A00080E8489F200D311D1124A0E0B0E010E03D\r\n:1014B00080E090E0FD01E20FF31FE658FB4F08E0EB\r\n:1014C000111105C0449150E04C235D2304C04491A8\r\n:1014D00050E046235723452B11F081E090E0015066\r\n:1014E00031960111EDCFA058BF4F113011F011E02E\r\n:1014F000E1CFDF91CF911F910F9108956F927F926D\r\n:101500008F929F92AF92BF92CF92DF92EF92FF9213\r\n:101510000F931F93CF93DF93CDB7DEB7C455D10997\r\n:101520000FB6F894DEBF0FBECDBF8091A0019091A1\r\n:10153000A10197FD0796A3E095958795AA95E1F7F8\r\n:1015400016E0180F0091C9012091C9013091CA011C\r\n:10155000802F90E0A9014D5A5F4F4817590784F03A\r\n:101560007C01E21AF30A602F812F0E94D405E1E08A\r\n:10157000F0E0EC0FFD1FEE0DFF1D80830F5FE4CF49\r\n:101580000091A0011091A10117FF02C0095F1F4F38\r\n:1015900073E0159507957A95E1F70B5FE8E0AE2EBD\r\n:1015A000B12CF4E56F2EC02ED12C8091A00190912A\r\n:1015B000A10197FD079643E0959587954A95E1F738\r\n:1015C0001091C9018C159D050CF059C0E12EF12C2C\r\n:1015D0008091C9019091CA018D5A9F4F8E159F0528\r\n:1015E0000CF44BC0612F802F0E94D405882E909060\r\n:1015F000A0017090A101892D972DB5010E9447226D\r\n:101600004091C9015091CA01F701E41BF50B282D47\r\n:1016100030E0B901082E02C0759567950A94E2F78B\r\n:1016200021E030E02C0F3D1FE20FF31F2081022E3E\r\n:10163000000C330BD501A81BB90B01C0220FAA95D2\r\n:10164000EAF7262B8082892D972D97FD079663E078\r\n:10165000959587956A95E1F7B601681B790B669EAB\r\n:10166000F001679EF00D1124E41BF50BEE0DFF1D3C\r\n:10167000E35EFD4F20831F5FA9CF015094CF082F59\r\n:1016800028E0A22EB12C7C01FF2434E5932EC12E3C\r\n:10169000D12C8091C9019091CA018D5A9F4F8C1510\r\n:1016A0009D050CF44BC0612F802F0E94D405882E1D\r\n:1016B000F091A001E091A1018F2F9E2FB5010E9412\r\n:1016C0004722AC016091C9017091CA012F2F3E2FB2\r\n:1016D00037FF02C0295F3F4F83E0359527958A95F4\r\n:1016E000E1F7C701821B930B989EF001999EF00DC4\r\n:1016F0001124E61BF70BEC0DFD1DE35EFD4F882D5D\r\n:1017000090E0042E02C0959587950A94E2F7C61AD8\r\n:10171000D70AA1E0B0E0AC0FBD1FAC0DBD1D2C91F0\r\n:10172000022E000C330BD501A41BB50B01C0220FF8\r\n:10173000AA95EAF7282B20831F5FA9CFCC5ADF4F49\r\n:101740000FB6F894DEBF0FBECDBFDF91CF911F91D2\r\n:101750000F91FF90EF90DF90CF90BF90AF909F9050\r\n:101760008F907F906F900895EF92FF920F931F9349\r\n:10177000CF93DF937C018B01C0E0D0E0EC16FD0637\r\n:10178000E4F061E083E00E94A00720E030E0201751\r\n:10179000310724F400002F5F3F4FF9CF60E083E072\r\n:1017A0000E94A00720E030E02017310724F4000059\r\n:1017B0002F5F3F4FF9CF2196E1CFDF91CF911F915E\r\n:1017C0000F91FF90EF900895FC01643508F053C02D\r\n:1017D000403308F050C090A1742F7595759575959C\r\n:1017E000262F062E000C330B542F57709230A1F485\r\n:1017F000F901E35EFD4F84E57802E00DF11D11244F\r\n:10180000808190E0052E02C0959587950A94E2F7B5\r\n:101810008095982F91700AC0933041F4848581702F\r\n:10182000462740954170841303C014C0911112C023\r\n:1018300084E57802200D311D1124F901E35EFD4F8E\r\n:1018400081E090E001C0880F5A95EAF78095908179\r\n:10185000892310C084E57802200D311D1124F9017F\r\n:10186000E35EFD4F81E090E001C0880F5A95EAF7F2\r\n:101870009081892B80830895BF92CF92DF92EF925F\r\n:10188000FF920F931F93CF93DF931F92CDB7DEB7D5\r\n:101890007C01D62EC42E002E000C110B040F111D3E\r\n:1018A00047FD1A954C2D0C2C000C550B4017510779\r\n:1018B0007CF4B12CB21654F46B2D6D0D4C2DC70178\r\n:1018C00029830E94E40BB3942981F4CFC394EACF17\r\n:1018D0000F90DF91CF911F910F91FF90EF90DF90CC\r\n:1018E000CF90BF9008956F927F928F929F92AF9208\r\n:1018F000BF92CF92DF92EF92FF920F931F93CF93FD\r\n:10190000DF93EC016A3019F42D819885A1C06D3008\r\n:1019100009F4A4C01885BA84D98488A083E58D15FC\r\n:101920000CF47FC08FE28B150CF47BC08C8190E0AF\r\n:101930000197189F9001199F300D1124C9018D0D39\r\n:10194000911DD7FC9A95181619060CF06AC08D8166\r\n:10195000819FC00111248B0D911DB7FC9A9518161B\r\n:1019600019060CF05EC09D2CCD2CE62EF12CEC2D32\r\n:10197000ED190E2E000CFF0B8C8190E0E817F90793\r\n:101980000CF04EC00197E817F90779F0E89E900136\r\n:10199000E99E300DF89E300D1124E20FF31F8E8D5D\r\n:1019A0009F8DE80FF91F749001C0712C6B2CAB2C2C\r\n:1019B0002A2D2B19022E000C330B8D8190E0281755\r\n:1019C00039075CF570FE10C0113031F44A2D6C2DD2\r\n:1019D000CE010E94E40B1DC0012F212F462D692D41\r\n:1019E000CE010E943C0C15C089A198A1891789F0ED\r\n:1019F00088A3113031F44A2D6C2DCE010E94E40BE6\r\n:101A000007C0012F212F462D692DCE010E943C0CCD\r\n:101A100088A27694A394610ECBCFC394910EA7CFE6\r\n:101A200088A228853C818985329F800D1124898771\r\n:101A30009F81992399F0082E000C990B44E550E002\r\n:101A4000239F401951091124481759073CF49D81DF\r\n:101A50008A85299F800D11248A87198681E090E06C\r\n:101A6000DF91CF911F910F91FF90EF90DF90CF907A\r\n:101A7000BF90AF909F908F907F906F900895CF937D\r\n:101A8000DF9310928E0481E080938F04D0E0C0E059\r\n:101A90004D2F6C2F8EE694E00E94E40BCF5FC03890\r\n:101AA000B9F7DF5FD03499F7DF91CF910895FF92B6\r\n:101AB0000F931F93CF93DF93C0E0D0E0082F10E087\r\n:101AC000FF24F3946091D8012091C9013091CA019B\r\n:101AD000C8010C2E02C0959587950A94E2F780FD07\r\n:101AE00010C0862F90E08217930734F1A9014C5A59\r\n:101AF0005F4F4817590704F110928E04F0928F043B\r\n:101B00000FC0862F90E082179307B4F0A9014C5ABA\r\n:101B10005F4F4817590784F0F0928E0410928F049B\r\n:101B20008091D7014C2F98E0899F400D1124621BB2\r\n:101B30008EE694E00E94E40B2196C830D10511F6A0\r\n:101B40008091D8018F5F8093D801DF91CF911F9151\r\n:101B50000F91FF900895AF92BF92CF92DF92EF92D4\r\n:101B6000FF920F931F93CF93DF931F92CDB7DEB7F2\r\n:101B7000182F7A0100E0F701E00FF11D8081882322\r\n:101B800081F1803261F194ED980F903130F09EEC4C\r\n:101B9000980F993210F095EC980F1F3710F06F5F87\r\n:101BA00010E01093D8016093D70186E0989F500110\r\n:101BB0001124C12CD12CF601EA0DFB1DED5BFD4F6C\r\n:101BC000849169830E94570D8FEFC81AD80A6981E2\r\n:101BD00086E0C816D10479F71A5F0F5FCCCF90E08A\r\n:101BE000DCCF0F90DF91CF911F910F91FF90EF907D\r\n:101BF000DF90CF90BF90AF900895EF92FF920F9338\r\n:101C00001F93CF93DF93CDB7DEB72A970FB6F89423\r\n:101C1000DEBF0FBECDBFF82EE62ECA018E010F5FCC\r\n:101C20001F4F2AE0F80111922A95E9F74AE0B8011E\r\n:101C30000E945320A8016E2D8F2D0E94AB0D2A9675\r\n:101C40000FB6F894DEBF0FBECDBFDF91CF911F91CD\r\n:101C50000F91FF90EF9008954FE451E062E080E033\r\n:101C60000E94AB0D4091C7015091C80162E070E045\r\n:101C70008CE290E00C94FD0DAF92BF92DF92EF9258\r\n:101C8000FF920F931F93CF93DF93EC0181E00E94AB\r\n:101C90003F0DC336D10524F4D093CA01C093C901C6\r\n:101CA0004FE651E061E080E00E94AB0D4BE751E070\r\n:101CB00063E080E00E94AB0D48E851E065E080E41D\r\n:101CC0000E94AB0D1092D8011092D701CCE4D0E065\r\n:101CD00088E30E94570D2197D9F71092D80182E02E\r\n:101CE0008093D701CCE4D0E08CE10E94570D21977E\r\n:101CF000D9F7E12CF12CC1E0D0E084E5D82ED092C8\r\n:101D0000D801C093D70100E010E05E01E894A1F88B\r\n:101D1000F701EC50FE4F84910E94570D8FEFE81AA7\r\n:101D2000F80A81E0A816B10429F40631110514F06F\r\n:101D300003E210E00F5F1F4F023211054CF32196B2\r\n:101D4000C430D105E1F6DF91CF911F910F91FF9043\r\n:101D5000EF90DF90BF90AF9008954F925F926F9297\r\n:101D60007F928F929F92AF92BF92CF92DF92EF922B\r\n:101D7000FF920F931F93CF93DF9300D000D01F9259\r\n:101D8000CDB7DEB74091A0045091A1046091A204A8\r\n:101D90007091A3042FB7F8948091190290911A02C0\r\n:101DA000A0911B02B0911C022FBF481B590B6A0B5C\r\n:101DB0007B0B80919F0490E0A0E0B0E000919B0439\r\n:101DC00010919C0420919D0430919E0484179507E6\r\n:101DD000A607B70730F4011511052105310509F0F3\r\n:101DE0003CC3012B022B032B09F035C38091370430\r\n:101DF00081508E3FC0F5809136048130C9F58091C5\r\n:101E00004A048F5F60914B0487FD09C0082E000CC7\r\n:101E1000990B70E06F5F7F4F0E944722682F60939D\r\n:101E20004A0481E69AE09093A5048093A40488E490\r\n:101E30008093A60480E00E943C138AE798E0909388\r\n:101E4000530480935204109258041092570481E076\r\n:101E50008093460489E080935B0410925E041092A4\r\n:101E60006004109262048091370481508E3F70F4B8\r\n:101E700080913504813009F09CC384E59AE0909309\r\n:101E8000A5048093A40488E48093A60480E00E94C3\r\n:101E90000F1480914604882309F4ABC080915A0442\r\n:101EA0008111A7C08091520490915304E09157048E\r\n:101EB000F0915804EE0FFF1FE80FF91F4591549160\r\n:101EC00041155105F1F420915604222331F010926E\r\n:101ED000580410925704FC0112C0109246048091DD\r\n:101EE0004504882341F080E00E940F14E0915704DC\r\n:101EF000F09158042DC080E00E9427137AC04591CC\r\n:101F000054919A01369527953695279540FF51C0F3\r\n:101F1000CA0116E0969587951A95E1F78F71952F6E\r\n:101F200096959695969590512F70223071F1F8F410\r\n:101F3000211117C08B3008F08AE080935B04E09198\r\n:101F40005704F09158043196F0935804E0935704E5\r\n:101F5000EE0FFF1F8091520490915304E80FF91F78\r\n:101F6000CECF213061F760E00E947914E8CF2330B2\r\n:101F7000B1F0243021F720914904829F802D112453\r\n:101F80008093620490936304DACF20914904829F86\r\n:101F9000802D112480935E0490935F04D0CF209114\r\n:101FA0004904829F802D11248093600490936104E2\r\n:101FB000C6CF2F732093590480914904859F802DAB\r\n:101FC000112480935A0410926A04109269041092AA\r\n:101FD000680481E080935C0480931D0410925D048A\r\n:101FE00080915704909158040196909358048093DF\r\n:101FF000570480915C04882309F4EEC080915A0450\r\n:10200000811103C00E942713E7C0815080935A04B6\r\n:1020100080916A04811146C020916804309169045E\r\n:102020002F5F3F4FC901880F991FE0916404F09121\r\n:102030006504E80FF91F65917491862F877080936E\r\n:102040006B04AB01E3E056954795EA95E1F7CA01C9\r\n:1020500096958795972F9695969590936C048F7388\r\n:1020600090914904899F802D112480936A044170C6\r\n:1020700040931802309369042093680480916604A9\r\n:1020800090E02817390770F020916704222339F077\r\n:10209000821B9109909369048093680403C080E0D7\r\n:1020A0000E94271380916A04815080936A04809172\r\n:1020B0005D0421E0280F20935D0440915904309184\r\n:1020C0006C04340F80915104380F309347046091B1\r\n:1020D0006004662371F070E0822F022E000C990BD1\r\n:1020E0000E94472280916104869F300D1124309315\r\n:1020F00047048091470490E0849664E270E00E9477\r\n:1021000047228093470430915B04309348046091E8\r\n:102110005E04662381F0062E000C770B822F022EC0\r\n:10212000000C990B0E94472280915F04869F300D1E\r\n:10213000112430934804609162046623A1F0822F39\r\n:10214000220F990B70E00E944722CB0162E070E001\r\n:102150000E9447222091630490914804289F900D8B\r\n:10216000112490934804809148044F3341F08A3001\r\n:102170000CF089E087FD80E08093480402C0109253\r\n:102180004804F894E0914704F0E0E058F74FE491F8\r\n:10219000E09317023091480420916D0432039001BE\r\n:1021A000112440916B044203C001439F900D112400\r\n:1021B00000904A0402C0880F991F0A94E2F797FF23\r\n:1021C00002C081589F4F880F892F881F990B8093D9\r\n:1021D0001E0480931F0478948091A604882309F438\r\n:1021E0008DC08C3020F49CE0E92EE81A01C0E12C6F\r\n:1021F000FF24F394F092760410928E0410928F04D0\r\n:10220000309173044DE2D42E1D2D131B1E0D03E0DF\r\n:10221000030F2EE4412F63E08EE694E03D830E949D\r\n:102220003C0C3D810CEF030F1D5F202F41E0612F1F\r\n:1022300080E50E944A15202F42E0612F83E00E9432\r\n:102240004A15F0928E04F0928F040091730413E00B\r\n:10225000100FD01ADE0C23E04D2D622F8EE694E095\r\n:102260002D830E94E40B2D812F5F2135A9F71D0DD1\r\n:10227000FF24FA94F10E23E04F2D622F8EE694E0B6\r\n:102280002D830E94E40B2D812F5F2135A9F7035088\r\n:1022900033E0D30E402F6D2D80E00E943215402F89\r\n:1022A0006D2D83E50E94321541E06D2D83E00E9483\r\n:1022B000B41442E06D2D80E50E94B414145044E043\r\n:1022C000612F80E50E94B41448E0612F83E00E94F2\r\n:1022D000B41484E08093770480917304E81A8E2DFF\r\n:1022E000815D809378048091A4049091A5040E945C\r\n:1022F000A7138091A60481508093A60480913C048A\r\n:1023000090913D04892B09F47CC011E010938E0458\r\n:1023100010928F049091720485E5891B8093770455\r\n:102320001092780480913904813009F44DC030F066\r\n:1023300090913804853008F05FC05AC080E00E9458\r\n:102340003C1310937604E2EDF8E0E491EF5FE09344\r\n:102350007204E3EDF8E0E491EF5FE093730484ED41\r\n:1023600098E090938D0480938C0410923D04109219\r\n:102370003C041092740418EA0E94AD0E8823E1F325\r\n:1023800084EC98E00E94A71360913A0470913B049A\r\n:1023900080E090E04AE00E94A5158FEA98E00E9454\r\n:1023A000A713612F62956F7070E080E090E04AE0C3\r\n:1023B0000E94A51584EA98E00E94A7138091350435\r\n:1023C000813009F0FCC01DC080919104909192046D\r\n:1023D000A0919304B09194048F709927AA27BB27EA\r\n:1023E0000897A105B10510F487E009C088E707C088\r\n:1023F000992339F08B5F03C0992319F08FE20E9473\r\n:10240000E6158EE694E00E94A10980917404811182\r\n:102410000EC088EF91E0EDE1F2E0DF019C011D923A\r\n:1024200021503040E1F710927704109278040E9416\r\n:10243000820860939B0470939C0480939D04909306\r\n:102440009E042091970430919804621B730B709343\r\n:1024500096046093950480E0CCC02FB7F8948091E7\r\n:10246000190290911A02A0911B02B0911C022FBF79\r\n:1024700020919F04820F911DA11DB11D8093A00486\r\n:102480009093A104A093A204B093A304809191041B\r\n:1024900090919204A0919304B09194040196A11D8F\r\n:1024A000B11D8093910490939204A0939304B093F0\r\n:1024B000940410929B0410929C0410929D0410921C\r\n:1024C0009E040E94820860939704709398048093FE\r\n:1024D000990490939A0480912104909122042FE012\r\n:1024E000289F8001299F100D112485E10E946B080F\r\n:1024F000800F911F24E0969587952A95E1F7909398\r\n:1025000022048093210420912004222309F44BC04B\r\n:1025100060912404262F30E040E050E029833A8384\r\n:102520004B835C83C0902504D12CE12CF12C40918D\r\n:102530002804509129044A01A12CB12C2091260491\r\n:10254000309127042901612C712C8217930728F000\r\n:102550009C014817590708F49A01C901A0E0B0E0AE\r\n:102560009C01AD01241935094609570969817A8111\r\n:102570008B819C816C197D098E099F090E942B22F9\r\n:10258000A501940124193509460957090E949E2086\r\n:10259000C20ED31EE41EF51EC09223046C2D70E003\r\n:1025A00085E00E940C080E9453130E94F11581E0FF\r\n:1025B00020C0893209F06ACC0E94D61367CC115032\r\n:1025C00009F0DACE60E070E085E00E940C0883B785\r\n:1025D000817F846083BF83B7816083BF83B781605D\r\n:1025E00083BF889583B78E7F83BF83B78E7F83BF7A\r\n:1025F000C3CE0F900F900F900F900F90DF91CF915F\r\n:102600001F910F91FF90EF90DF90CF90BF90AF9010\r\n:102610009F908F907F906F905F904F900895BC0136\r\n:10262000009791F0FC0101900020E9F73197AF018C\r\n:10263000481B590BE0916E04F0916F040280F38106\r\n:10264000E02D8EE694E0099480E090E008958111F9\r\n:1026500012C010925C0410925A04109269041092F5\r\n:10266000680410925D0410921F0410921E041092D0\r\n:102670001D040C942B090895811114C010925C0460\r\n:1026800010925A04109269041092680410925D042A\r\n:1026900010921F0410921E0410921D040E942B0918\r\n:1026A000109246040895CF92DF92EF92FF920F931B\r\n:1026B0001F93CF93DF93CAE2D4E001E314E0FF2439\r\n:1026C000FA9497E0E92EE00E62E088810E94D0073C\r\n:1026D000288130E0F901E951F54F8491F901ED527B\r\n:1026E000F54FC490F901E154F54FD490DD2071F01D\r\n:1026F00081110E947707ED2DF0E0EE0FFF1FEB54E4\r\n:10270000F54FA591B491EC91EC21B1F4F8018081E1\r\n:102710008F5F808360E088810E94D00721960F5FE1\r\n:102720001F4FE012D1CFDF91CF911F910F91FF90FA\r\n:10273000EF90DF90CF900895F8018081882371F3A6\r\n:10274000F8018F3F11F41082E5CFF082E3CF0F93B1\r\n:102750001F93CF93DF938C01C0E0D0E0F801EC0F22\r\n:10276000FD1F6491662371F0E0916E04F0916F0497\r\n:102770000190F081E02D8EE694E00995892B11F00F\r\n:102780002196ECCFCE01DF91CF911F910F9108954B\r\n:10279000CF93DF930E94A713EC0183E991E00E949D\r\n:1027A0000F138C0F9D1FDF91CF91089588EF91E05B\r\n:1027B000EDE1F2E0DF019C011D9221503040E1F794\r\n:1027C00010927704109278048DE89AE00E94A71383\r\n:1027D0008EE694E00E94A1098CB583608CBD8DB516\r\n:1027E0008E7F8DBD86E991E0EEEFFFE309951092B3\r\n:1027F000740488E69AE00E94C8138EE694E00E9472\r\n:10280000A1090E94531380913504813039F062E3AD\r\n:1028100070E080E090E00E94A708F3CF0895AF92A7\r\n:10282000BF92CF92DF92EF92FF920F931F93CF93BD\r\n:10283000DF93C82ED12CE601C05EDB4F9DA199230A\r\n:1028400009F44CC07E019FEFE91AF90AF70195A13E\r\n:10285000911144C09EA58601000F111F005E1B4F01\r\n:10286000F80134A525A5E32FF22FE90FF11DE90F9B\r\n:10287000F11D259134912F3FFFEF3F0711F41DA269\r\n:102880002DC039ABF601EE0FFF1FE65DFB4F33277E\r\n:10289000220F331F05A0F6A1E02DE20FF31FA59034\r\n:1028A000B490811117C00E943C13F801B3AAA2AAE8\r\n:1028B000F601EE0FFF1FEE5CFB4F16A215A281E0A2\r\n:1028C000F70185A389E08BAF1EAEFE017B9615A2B2\r\n:1028D000329615A229968DA18F5F8DA3DF91CF919E\r\n:1028E0001F910F91FF90EF90DF90CF90BF90AF902E\r\n:1028F000089570E0DB01AA0FBB1FA05EBB4FD4960A\r\n:102900002C91D497D5969C91D597E22FF92FE80F6B\r\n:10291000F11DE80FF11D259134915F9696963C9339\r\n:102920002E939597F9018591949190914904989FE0\r\n:10293000802D1124605E7B4FFB01B19685A3F901C8\r\n:10294000A591B4914B2F50E0E82FF0E04E175F07B0\r\n:1029500020F4F90125913491832FFB01B296899FD0\r\n:10296000802D112485A30895AF92BF92CF92DF925C\r\n:10297000EF92FF920F931F93CF93DF93182F062FA1\r\n:10298000C1E0D3E08AEFD82E9EEFE92E842F847029\r\n:10299000C82E842F8270B82E842F8870A82E417084\r\n:1029A000F42E8C2F880F8F5FE80ECC2081F04D2FF6\r\n:1029B000400F6C2F610F8EE694E00E94E40B4C2FC9\r\n:1029C000400F6D2F610F8EE694E00E94E40BBB2058\r\n:1029D00081F0402F4D1B6C2F610F8EE694E00E941A\r\n:1029E000E40B402F4C1B6D2F610F8EE694E00E948C\r\n:1029F000E40BAA2081F04C2F400F612F6D1B8EE657\r\n:102A000094E00E94E40B4D2F400F612F6C1B8EE66B\r\n:102A100094E00E94E40BFF2081F0402F4C1B612FBB\r\n:102A20006D1B8EE694E00E94E40B402F4D1B612F3E\r\n:102A30006C1B8EE694E00E94E40BCD1744F4E7FC97\r\n:102A400004C0D150D394D394ED0CCF5FAACFDF91C3\r\n:102A5000CF911F910F91FF90EF90DF90CF90BF909B\r\n:102A6000AF9008950F931F93CF93DF93182F062FE6\r\n:102A7000D42FC0E0CD174CF44C2F400F612F8EE6C1\r\n:102A800094E00E94E40BCF5FF5CFDF91CF911F91CF\r\n:102A90000F9108959F92AF92BF92CF92DF92EF92E3\r\n:102AA000FF920F931F93CF93DF93F82EE62EB22E53\r\n:102AB00003E0020FD0E0C3E08AEFC82E1EEF842FA0\r\n:102AC0008170982EAA24A394A20E4270D42EDF5FA8\r\n:102AD000802F8B19180F992081F04C2F440F4A0D2D\r\n:102AE0006E2D6C1B8D2F8F0D0E943215402F6E2D79\r\n:102AF0006D1B8C2F8F0D0E943215DD2081F04C2F25\r\n:102B0000440F4A0D6E2D6C1B8F2D8D1B0E943215AC\r\n:102B1000402F6E2D6D1B8F2D8C1B0E943215DC17E4\r\n:102B200044F417FD04C0C150C394C3941C0D0E5F40\r\n:102B3000CECFDF91CF911F910F91FF90EF90DF905B\r\n:102B4000CF90BF90AF909F9008958F929F92AF9239\r\n:102B5000BF920F931F93CF93DF93CDB7DEB7A197AB\r\n:102B60000FB6F894DEBF0FBECDBF19A2423008F4F5\r\n:102B70004AE08E010F5D1F4F842E912CA12CB12CA9\r\n:102B8000A50194010E94D020E62FB901CA0101508D\r\n:102B90001109EA3014F4E05D01C0E95CD801EC935E\r\n:102BA000232B242B252B61F7C8010E940F13A1961C\r\n:102BB0000FB6F894DEBF0FBECDBFDF91CF911F914E\r\n:102BC0000F91BF90AF909F908F900895E0916E0409\r\n:102BD000F0916F040190F081E02D682F8EE694E073\r\n:102BE000099480913C0490913D04892BB1F180912E\r\n:102BF00044048F7169F584E10E946B08BC01990F50\r\n:102C0000880B990B0E94322126EE3FE34EEC50E4F4\r\n:102C10000E9496210E9401219B0170933B046093C6\r\n:102C20003A04672B91F084E080933904ECE3F4E0FC\r\n:102C300080E0419151912417350718F480933904AD\r\n:102C400008958F5F8430A9F703C08FEF8093390414\r\n:102C5000809144048F5F8093440408958F929F92E3\r\n:102C6000AF92BF92CF92DF92EF92FF920F931F939A\r\n:102C7000CF93DF93FB0124913196C490F0908E04A2\r\n:102C8000022E000C330B121613060CF0D7C0803343\r\n:102C90000CF0D4C0482F082E000C550BFA01EC0D97\r\n:102CA000F11DC7FCFA951E161F060CF0C7C06E5F1B\r\n:102CB0007F4FD901179693E0B595A7959A95E1F7BF\r\n:102CC00087FF0BC0C80EA49FC001A59F900DB49FA5\r\n:102CD000900D1124681B790B80E04C2D0C2C000CFE\r\n:102CE000550B480F511D87FD5A95413351051CF076\r\n:102CF00090E3C92EC81A2535310514F024E530E0DB\r\n:102D000010917A041827982F977031E001C0330F83\r\n:102D10009A95EAF7859585958595F4E58F02C0012A\r\n:102D20001124835E9D4F00E00C2C000CDD08BB24B9\r\n:102D3000B394402F50E04C155D050CF07FC0FB01B3\r\n:102D4000E490F1E0FF1218C0FB01EC0140E8542FC1\r\n:102D50005E2119F05881532B588350E055954795C3\r\n:102D60004115510519F43196E49040E821965C2F05\r\n:102D7000581B521760F359C0F1101AC0A32EA0942B\r\n:102D8000FB01EC0140E8542F5E2119F058815A21D3\r\n:102D9000588350E0559547954115510519F43196E2\r\n:102DA000E49040E821965C2F581B521760F33DC019\r\n:102DB00043E0F41223C0932E9094FB01EC0140E811\r\n:102DC000A82E8C2E881A542F5E2141F0812658811E\r\n:102DD00080FE02C0532B01C05921588350E0559505\r\n:102DE00047954115510519F43196E49040E8219634\r\n:102DF0005C2F5A19521728F31B2517C0FB01EC0151\r\n:102E000040E8542F5E2119F058815327588350E031\r\n:102E1000559547954115510519F43196E49040E8D0\r\n:102E200021965C2F581B521760F3330F19F48C5AFC\r\n:102E30009F4F31E00F5F6A0F7B1F7BCFDF91CF91F8\r\n:102E40001F910F91FF90EF90DF90CF90BF90AF90C8\r\n:102E50009F908F900895CF93DF93CDB7DEB72B97D8\r\n:102E60000FB6F894DEBF0FBECDBF789484B58260F4\r\n:102E700084BD84B5816084BD85B5826085BD85B51E\r\n:102E8000816085BD80916E00816080936E0010929C\r\n:102E90008100809181008260809381008091810017\r\n:102EA00081608093810080918000816080938000A8\r\n:102EB0008091B10084608093B1008091B000816006\r\n:102EC0008093B00080917A00846080937A00809132\r\n:102ED0007A00826080937A0080917A00816080938A\r\n:102EE0007A0080917A00806880937A001092C10005\r\n:102EF00082E380939F0481E090E0A0E0B0E08093C3\r\n:102F00009B0490939C04A0939D04B0939E048FEF28\r\n:102F100080939004E0E8F7E7259134912130304C1C\r\n:102F200009F049C0E6E9F7E7E491E0937904E7E9BD\r\n:102F3000F7E7E491E0932404E8E9F7E7E491E0930C\r\n:102F40002504E9E9F7E7859194919093270480930C\r\n:102F50002604EBE9F7E785919491909329048093F7\r\n:102F6000280487E080934B04EEE9F7E7E491E093CF\r\n:102F70004A04EFE9F7E7E491E0939004E0EAF7E729\r\n:102F80008591949190933D0480933C04E2EAF7E7A5\r\n:102F90008591949190933F0480933E04E4EAF7E78F\r\n:102FA000859194919093410480934004E6EAF7E779\r\n:102FB000859194912CC09CE3909379041092240401\r\n:102FC0008093250480E293E0909327048093260465\r\n:102FD00084ED93E0909329048093280487E0809304\r\n:102FE0004B0480934A048CEA9DE090933D048093C7\r\n:102FF0003C048EED9DE090933F0480933E0484E773\r\n:103000009EE090934104809340048CE39FE0909372\r\n:1030100043048093420411E0109320046FEF70E0AA\r\n:1030200085E00E940C0888E080932A0489E0809360\r\n:103030002B0487E080932C0486E080932D0404E029\r\n:1030400000932E0482E080932F0481E1809330046A\r\n:103050000E9453138CE39FE090933B0480933A04C7\r\n:1030600000933904109344048BE080937C048DE03A\r\n:1030700080937B0480E180937D048EE080937F04C5\r\n:103080008FE080937E041093760410938E04109248\r\n:103090008F0410937504E2EDF8E0E491EF5FE093A4\r\n:1030A0007204E3EDF8E0E491EF5FE093730484EDE4\r\n:1030B00098E090938D0480938C041FB7F8948091CE\r\n:1030C000CB01811127C0E9ECFAE08491EDEDFAE043\r\n:1030D0009491E82FF0E0EE0FFF1FEC58FF4FA59101\r\n:1030E000B491EC91E92321F461E08AE00E94A00709\r\n:1030F00061E08AE00E94D0078CB580618CBD8CB500\r\n:1031000080648CBD61E08DE00E94D00761E08BE0BF\r\n:103110000E94D0078091CB018F5F8093CB011FBFAE\r\n:103120008CB58F7D8CBD8CB58C7F81608CBD8DB551\r\n:1031300081608DBD8CB58C608CBD61E080917C041C\r\n:103140000E94D00761E080917B040E94D00761E07B\r\n:1031500080917D040E94D00780917F0418161CF492\r\n:1031600061E00E94D00780917E0418161CF461E093\r\n:103170000E94D00780917F04181674F460E00E94CA\r\n:10318000A0076AE070E080E090E00E94A70861E09C\r\n:1031900080917F040E94A00780917B04082E000C80\r\n:1031A000990BFC01E154F54FE491F0E0EE0FFF1FA5\r\n:1031B000E258FF4F25913491309383042093820489\r\n:1031C000FC01ED52F54FE491E093890480917C0479\r\n:1031D000082E000C990BFC01E154F54FE491F0E04E\r\n:1031E000EE0FFF1FE258FF4F259134913093810479\r\n:1031F00020938004FC01ED52F54FE491E0938804A4\r\n:1032000080917E04082E000C990BFC01E154F54FCF\r\n:10321000E491F0E0EE0FFF1FE258FF4F259134914B\r\n:103220003093850420938404FC01ED52F54FE49122\r\n:10323000E0938A0480917D04082E000C990BFC0118\r\n:10324000E154F54FE491F0E0EE0FFF1FE258FF4F1D\r\n:10325000259134913093870420938604FC01ED522C\r\n:10326000F54FE491E0938B0461E28EE694E00E94D6\r\n:10327000800964E18EE694E00E94800980917904DF\r\n:1032800087FF03C08FE780937904609179046068B9\r\n:103290008EE694E00E94800960E28EE694E00E944F\r\n:1032A00080096CE08EE694E00E9480098EE694E04E\r\n:1032B0000E94A10911E01093490484E080936D04F9\r\n:1032C00080E790E0909355048093540460E080E0A0\r\n:1032D0000E94791461E070E083E00E940C08809104\r\n:1032E000B100887F81608093B100F89410928000D3\r\n:1032F00010928100109285001092840088E191E084\r\n:1033000090938900809388008091810088608093E9\r\n:1033100081008091810081608093810080916F00A5\r\n:10332000826080936F0078940E94F115809136043A\r\n:10333000813019F410924A041CC08091390488230A\r\n:10334000C9F380E00E943C1388E890E09093530416\r\n:10335000809352041092580410925704109346041C\r\n:1033600089E080935B0410925E04109260041092D6\r\n:10337000620480919004882309F4E7C081E080937F\r\n:10338000760410927504109274041092380480939D\r\n:103390008E0480938F04FCEE6F2EF1E07F2EACE064\r\n:1033A000FA2E0AE718E0EE24E394B9E0DB2E0E943F\r\n:1033B000AD0E8823E1F3F3018491882319F0C090C6\r\n:1033C000730401C0C12C62EB70E080E00E942E16F5\r\n:1033D00062E271E08CE08C0D0E942E161092770450\r\n:1033E000F09278048CEE91E00E94A7138091720411\r\n:1033F000982F990F890F81958D5A8093770480912A\r\n:103400007304982F990F890F8195835D80937804B9\r\n:103410008091910484FF03C08EEA90E002C08AEAA2\r\n:1034200090E00E94C81380917204982F990F890F21\r\n:1034300081958D5A80937704809178048F5F809373\r\n:10344000780480914A04882319F086EA90E002C04B\r\n:1034500082EA90E00E94C81380917204982F990F1D\r\n:10346000890F81958D5A80937704809178048F5FBE\r\n:10347000809378048EE990E00E94C813809136040E\r\n:10348000813039F580914A048F5F60914B0487FD4C\r\n:1034900009C0082E000C990B70E06F5F7F4F0E94EF\r\n:1034A0004722682F60934A0480E00E943C131093E7\r\n:1034B0005304009352041092580410925704E0925F\r\n:1034C0004604D0925B0410925E0410926004109245\r\n:1034D0006204809135048130B9F080919004482FC6\r\n:1034E00050E060E070E08090910490909204A09091\r\n:1034F0009304B090940484169506A606B70608F4C3\r\n:10350000D3C48F3F09F4D0C48FEF8093900480E040\r\n:103510000E943C1380E00E943C1386E990E0909367\r\n:10352000530480935204109258041092570481E07F\r\n:103530008093460499E090935B0410925E0410928D\r\n:1035400060041092620480933804E2E04E2E512C05\r\n:1035500081E00E943F0D1092CA011092C901809132\r\n:103560003604813009F4A8C481E00E943F0D109216\r\n:10357000C8011092C7015092C6014092C50181E076\r\n:1035800090E09093C4018093C30186E990E090930A\r\n:10359000D3018093D2015092D1014092D0010E9478\r\n:1035A000200A0E94E7098091C5019091C60197FD0C\r\n:1035B000CFC30E94AD0E8823E1F3809131048130A6\r\n:1035C00009F49FC480913304813009F49FC4809131\r\n:1035D0003204813009F49FC480913404813009F4AD\r\n:1035E000A1C48091C001883308F45AC00E94E70941\r\n:1035F0000E94200A0091C3011091C4010F5F1F4F68\r\n:103600001093C4010093C3010330110519F0053074\r\n:10361000110549F48091C5019091C60101969093DE\r\n:10362000C6018093C5018091D0019091D101833072\r\n:1036300091052CF401969093D1018093D001809153\r\n:10364000D2019091D301833391052CF04997909347\r\n:10365000D3018093D20180E00E943F0D1092CA01F5\r\n:103660001092C90148E251E063E080E00E94AB0D96\r\n:10367000A80163E070E08CE290E00E94FD0D0E94E2\r\n:103680002C0E8EE694E00E94A10964EC79E080E0C3\r\n:1036900090E00E94A70880E00E943F0D0E947E0AF1\r\n:1036A0008091A4019091A50101969093A50180932A\r\n:1036B000A4012091D2013091D301821793072CF1FC\r\n:1036C0001092A5011092A4012091D0013091D10156\r\n:1036D00060E001C06F5F862F90E082179307ACF423\r\n:1036E000880F991FFC01EA55FE4F40815181452BFF\r\n:1036F00089F7DC01A854BE4F80E48C9380E11196D9\r\n:103700008C9381E090E09183808346EA51E05F836F\r\n:103710004E8330EBE32E31E0F32E49EBC42E41E033\r\n:10372000D42E58EB252E51E0352E3A8229825601AF\r\n:103730001B861A865FC0F701208131812150310933\r\n:103740002330310508F05FC0F901EF5EFE4F808144\r\n:10375000082E000C990BF901E25FFE4F4081F90140\r\n:10376000E55FFE4F5081652F550F770B7C836B8390\r\n:10377000F901E85FFE4F7080F901EB5FFE4F708149\r\n:103780007D838A849B84880C991C8401040F111DFD\r\n:1037900008541E4FF8016080860D8083D5016C911E\r\n:1037A000E981FA8180810E94320A0197C1F5D8012E\r\n:1037B0006C920E94452024E030E040E050E00E94FE\r\n:1037C0009E20F701718360834A855B854F5F5F4F61\r\n:1037D0005B874A8752E0E50EF11C62E0A60EB11C41\r\n:1037E00089819A8102969A838983AA85BB851397DA\r\n:1037F00009F453C0AE81BF818D919D91BF83AE838B\r\n:10380000019711F798CF83E08D8377247394AFEFFE\r\n:10381000BFEFBC83AB8340E081E090E0B2CF23E018\r\n:1038200030E0072D10E0C401800F911FAC01485417\r\n:103830005E4F3A01D3018C91BB818B0FF3018083E2\r\n:10384000D5016C91E981FA818081298738870E94AE\r\n:10385000320A29853885019709F431E0215051F762\r\n:1038600031110EC00E94452024E630E040E050E0D7\r\n:103870000E949E2063337105810591050CF059C3A8\r\n:10388000080D191DF801E854FE4F9B81990F2B81FB\r\n:10389000920F8081891B808397CF8091CE01909178\r\n:1038A000CF0101969093CF018093CE01029709F04A\r\n:1038B0004EC08091AE019091AF01892B41F581E01E\r\n:1038C00090E09093AF018093AE018091AC0198E3BA\r\n:1038D000899F8001181B1124B8016E5A7C4F84E027\r\n:1038E00090E00E94B40BB80160537D4F85E090E0FA\r\n:1038F0000E94B40BB80164597D4F84E090E00E94AF\r\n:10390000B40BB801665C7D4F85E090E01AC0109260\r\n:10391000AF011092AE016AE372E085E090E00E9490\r\n:10392000B40B6CE672E084E090E00E94B40B60EDB2\r\n:1039300072E085E090E00E94B40B62E573E084E001\r\n:1039400090E00E94B40B1092CF011092CE018091B2\r\n:10395000AC01882391F08091A2019091A30101967E\r\n:103960009093A3018093A201883C910534F01092BA\r\n:10397000AC011092A3011092A2010091B601109126\r\n:10398000B7011093CD010093CC012091C10130917A\r\n:10399000C2013093B7012093B601F090BE01EF2D24\r\n:1039A000F0E07E97F093CA01E093C901E090BF0177\r\n:1039B0004E2D50E0445151095093A1014093A00174\r\n:1039C000F7FF0BC01092CA011092C90157FF13C034\r\n:1039D0001092A1011092A00102C057FDF9CF809171\r\n:1039E000C9019091CA018C9734F08BE290E09093DA\r\n:1039F000CA018093C9018091A0019091A1014197D2\r\n:103A000034F080E190E09093A1018093A0012130F7\r\n:103A1000310509F458C01CF4232B41F06EC022304C\r\n:103A20003105E1F023303105A9F167C0F090BE0106\r\n:103A3000F394F092BE016E2D8F2D0E94320A0197F1\r\n:103A400021F41093B7010093B601EA85FB85319705\r\n:103A5000FB87EA87EF2B51F78DEF18C0F090BE017E\r\n:103A6000FA94F092BE016E2D8F2D0E94320A0197BA\r\n:103A700021F41093B7010093B6014A855B8541504C\r\n:103A800051095B874A87452B49F783E08F0D809367\r\n:103A9000BE0133C0E090BF01EA94E092BF016E2DF9\r\n:103AA0008F2D0E94320A019721F41093B7010093E1\r\n:103AB000B6016A857B85615071097B876A87672BB0\r\n:103AC00049F783E017C0E090BF01E394E092BF01A3\r\n:103AD0006E2D8F2D0E94320A019721F41093B701A9\r\n:103AE0000093B6018A859B8501979B878A87892BDE\r\n:103AF00051F78DEF8E0D8093BF018091B6019091AB\r\n:103B0000B70181309105F9F034F4892B51F510910A\r\n:103B1000BE0181E00CC08230910531F0039709F5B8\r\n:103B20001091BF016FEF12C01091BE018FEF810F96\r\n:103B30008093BE016091BF010E94320A019789F40F\r\n:103B40001093BE010EC01091BF0161E0610F609340\r\n:103B5000BF018091BE010E94320A019711F41093B7\r\n:103B6000BF018091BF018333D1F48091BE018E30BB\r\n:103B700038F480919E01813091F410929E0108C02A\r\n:103B8000803768F080919F01813049F410929F0145\r\n:103B900091E09093AC011092A3011092A201E8EB86\r\n:103BA000F1E095E128E334E6D6018C91811103C060\r\n:103BB0002C93308305C0883318F0D6011C92908373\r\n:103BC000B2E0CB0ED11C329641E0E03CF40761F745\r\n:103BD000A12CB12CD12C00E010E08091BE0190E02E\r\n:103BE000D1012C9130E0AC01475051092417350721\r\n:103BF0000CF44BC00796821793070CF446C08091D3\r\n:103C0000BF0190E0F501E854FE4F218130E0AC01A6\r\n:103C10004750510924173507C4F1079682179307B7\r\n:103C2000A4F18091AC01882371F1D801A85EBE4F48\r\n:103C30008C91D1018C93D801AC5EBE4F8C91818365\r\n:103C4000F501EA55FE4F118210829CEBE92E92E0BD\r\n:103C5000F92EB7018EE190E00E94B40BB2E3EB1AAB\r\n:103C6000F108E8ECEE16F104A1F78091C7019091FC\r\n:103C7000C8010A969093C8018093C7011092A501CC\r\n:103C80001092A40102C0DD24D3940F5F1F4FF2E015\r\n:103C90002F0E311C22E0A20EB11C46E0A416B10486\r\n:103CA00009F09BCFDD2009F450C063E070E0709311\r\n:103CB000B7016093B60181E090E09093AF018093EB\r\n:103CC000AE010E947E0A00E010E0B80182E390E0BD\r\n:103CD0000E94B40B0E5C1F4F043F71E01707A9F759\r\n:103CE0000E94AD0E8823E1F30E947E0A0E94AD0E71\r\n:103CF0008823E1F31092AF011092AE010E947E0A78\r\n:103D0000B80182E390E00E94B40B0E5C1F4F083EA6\r\n:103D100083E01807A9F70E94AD0E8823E1F30E9403\r\n:103D20007E0A64EF71E080E090E00E94A70891E0D5\r\n:103D30009093AD018091C5019091C6010197909338\r\n:103D4000C6018093C5010E94E7090E947E0A2BCC20\r\n:103D50000E94E70980E090E00E948820082F10E090\r\n:103D6000102F00271093D6010093D50181E090E039\r\n:103D70000E948820082B1093D6010093D501109241\r\n:103D8000D4016091C7017091C801061717078CF420\r\n:103D90007093D6016093D50181E090E00E9490205D\r\n:103DA0006091C80180E090E00E94902081E08093C3\r\n:103DB000D4011092CA011092C90180E00E943F0D07\r\n:103DC0004DE351E060E080E00E94AB0D4FE251E036\r\n:103DD00061E080E00E94AB0D4DE351E063E080E0E4\r\n:103DE0000E94AB0D0E942C0E0E94AD0E8823E1F3C1\r\n:103DF00064EC79E080E090E00E94A70880E00E94F7\r\n:103E00003F0D4AE351E060E080E00E94AB0D4AE3E1\r\n:103E100051E063E080E00E94AB0D4091D5015091EC\r\n:103E2000D60162E070E088E190E00E94FD0D809193\r\n:103E3000D401811106C04AE451E061E00E94AB0D5B\r\n:103E400012C046E551E061E080E00E94AB0D0CEB52\r\n:103E500012E0B8018EE190E00E94B40B0253110908\r\n:103E6000083C1105B1F70E94AD0E8823E1F364EC24\r\n:103E700079E080E090E00E94A70881E00E943F0D79\r\n:103E80008EE694E00E94A10980913504813009F00A\r\n:103E900057C00E94AD0E8823E1F365E070E080E03A\r\n:103EA00090E00E94A708F0CF80913704813009F09C\r\n:103EB0007ECA0E94D6137BCA60E080E090E00E9438\r\n:103EC000902060E081E090E00E9490204BE351E080\r\n:103ED00060E080E00E94AB0D40E651E061E080E0F0\r\n:103EE0000E94AB0D4BE351E063E080E00E94AB0D1C\r\n:103EF0000E94AD0E8823E1F360ED77E080E090E072\r\n:103F0000BACF5092C2014092C1015CCB1092C20163\r\n:103F10001092C1015CCBA3E0B0E0B093C201A093CA\r\n:103F2000C1015ACB81E090E09093C2018093C1011E\r\n:103F300058CBBD818B2F90E0F70191838083A0CC7B\r\n:103F40008FE3809359048091490480935A0410921E\r\n:103F50006A04109269041092680481E080935C0402\r\n:103F600080931D0410925D040E94AD0E8823E1F33E\r\n:103F70001092CA011092C90100E010E0C8010E942D\r\n:103F80003C0E8EE694E00E94A1090115110531F462\r\n:103F900064EA76E080E090E00E94A7080D5F1F4F82\r\n:103FA0000A32110559F780913504813041F480E0DF\r\n:103FB00090E0892B09F4CCCA0E940000C9CA809104\r\n:103FC00036048130A1F384E690E00E943C0E0E940A\r\n:103FD000AD0E8823E1F3E7CF1092710410927004C4\r\n:103FE00080E291E090936F0480936E0408958F9225\r\n:103FF0009F92AF92BF92CF92DF92EF92FF92CF93B8\r\n:10400000DF93EC01688179818A819B81611571055B\r\n:104010008105910521F464E279ED8BE597E02DE1CE\r\n:1040200033EF41E050E00E949E2049015A019B017C\r\n:10403000AC01A7EAB1E40E94BD206B017C01ACEEAB\r\n:10404000B4EFA50194010E94CB20DC01CB018C0DC3\r\n:104050009D1DAE1DBF1DB7FF03C00197A109B0484C\r\n:1040600088839983AA83BB83BC01CD019F77DF91AD\r\n:10407000CF91FF90EF90DF90CF90BF90AF909F9047\r\n:104080008F9008950E94F71F089581E091E00E94AB\r\n:10409000F71F08956093010170930201809303015B\r\n:1040A000909304010895BB274A3031F4992322F4F8\r\n:1040B000BDE2909581959F4F0C945F20BB27FB013B\r\n:1040C0005527AA27880F991FAA1FA41710F0A41B11\r\n:1040D00083955051B9F7A05DAA3308F0A95DA1936B\r\n:1040E000009779F7B111B1931192CB010C9478201C\r\n:1040F000DC01FC01672F71917723E1F7329704C04F\r\n:104100007C916D9370836291AE17BF07C8F30895D9\r\n:10411000F999FECF92BD81BDF89A992780B508958F\r\n:10412000262FF999FECF1FBA92BD81BD20BD0FB6D3\r\n:10413000F894FA9AF99A0FBE01960895052E97FB06\r\n:104140001EF400940E94B52057FD07D00E94D02095\r\n:1041500007FC03D04EF40C94B52050954095309553\r\n:1041600021953F4F4F4F5F4F0895909580957095E3\r\n:1041700061957F4F8F4F9F4F08950E94F220A59F1A\r\n:10418000900DB49F900DA49F800D911D1124089552\r\n:10419000B7FF0C94BD200E94BD20821B930B089595\r\n:1041A000A1E21A2EAA1BBB1BFD010DC0AA1FBB1F3B\r\n:1041B000EE1FFF1FA217B307E407F50720F0A21BAD\r\n:1041C000B30BE40BF50B661F771F881F991F1A941A\r\n:1041D00069F760957095809590959B01AC01BD0144\r\n:1041E000CF010895A29FB001B39FC001A39F700D9E\r\n:1041F000811D1124911DB29F700D811D1124911DEF\r\n:1042000008950E94752188F09F5798F0B92F99273B\r\n:10421000B751B0F0E1F0660F771F881F991F1AF0B1\r\n:10422000BA95C9F714C0B13091F00E948F21B1E066\r\n:1042300008950C948F21672F782F8827B85F39F065\r\n:10424000B93FCCF3869577956795B395D9F73EF44A\r\n:1042500090958095709561957F4F8F4F9F4F0895F2\r\n:10426000E89409C097FB3EF4909580957095619510\r\n:104270007F4F8F4F9F4F9923A9F0F92F96E9BB27C6\r\n:104280009395F695879577956795B795F111F8CF42\r\n:10429000FAF4BB0F11F460FF1BC06F5F7F4F8F4FAD\r\n:1042A0009F4F16C0882311F096E911C0772321F0A3\r\n:1042B0009EE8872F762F05C0662371F096E8862F3B\r\n:1042C00070E060E02AF09A95660F771F881FDAF792\r\n:1042D000880F9695879597F9089557FD9058440F44\r\n:1042E000551F59F05F3F71F04795880F97FB991F55\r\n:1042F00061F09F3F79F08795089512161306140612\r\n:10430000551FF2CF4695F1DF08C01616170618069E\r\n:10431000991FF1CF86957105610508940895E89479\r\n:10432000BB2766277727CB0197F908950E94A9211B\r\n:104330000C941A220E940C2238F00E94132220F0C2\r\n:10434000952311F00C9403220C94092211240C944F\r\n:1043500090210E946D2170F3959FC1F3950F50E05D\r\n:10436000551F629FF001729FBB27F00DB11D639F27\r\n:10437000AA27F00DB11DAA1F649F6627B00DA11DCD\r\n:10438000661F829F2227B00DA11D621F739FB00D73\r\n:10439000A11D621F839FA00D611D221F749F3327E3\r\n:1043A000A00D611D231F849F600D211D822F762F7C\r\n:1043B0006A2F11249F5750409AF0F1F088234AF059\r\n:1043C000EE0FFF1FBB1F661F771F881F91505040C5\r\n:1043D000A9F79E3F510580F00C9403220C94902184\r\n:1043E0005F3FE4F3983ED4F3869577956795B7954C\r\n:1043F000F795E7959F5FC1F7FE2B880F911D969566\r\n:10440000879597F9089597F99F6780E870E060E0D5\r\n:1044100008959FEF80EC089500240A94161617065D\r\n:1044200018060906089500240A94121613061406A5\r\n:1044300005060895092E0394000C11F4882352F008\r\n:10444000BB0F40F4BF2B11F460FF04C06F5F7F4FC0\r\n:104450008F4F9F4F0895DB018F939F930E94BD2044\r\n:10446000BF91AF91A29F800D911DA39F900DB29F10\r\n:10447000900D11240895991B79E004C0991F961797\r\n:1044800008F0961B881F7A95C9F78095089597FBC9\r\n:10449000072E16F4009407D077FD09D00E945B2206\r\n:1044A00007FC05D03EF4909581959F4F0895709537\r\n:1044B00061957F4F0895AA1BBB1B51E107C0AA1F3E\r\n:1044C000BB1FA617B70710F0A61BB70B881F991FB5\r\n:1044D0005A95A9F780959095BC01CD010895EE0FEE\r\n:1044E000FF1F0590F491E02D099481E090E0F8948D\r\n:0844F0000C947A22F894FFCF2E\r\n:1044F80001010000000001020001000101FF0100AC\r\n:104508000101FFFF1C1C1C2842374D37000000002A\r\n:10451800730CA905720771074C4556454C3A00477C\r\n:10452800414D4520204F564552002D2D2D2D2D2D26\r\n:104538002D2D2D2D2D2D2D2D2D004849474820534B\r\n:10454800434F52453A004E455720484947483A009C\r\n:1045580048492053434F5245205245534554005033\r\n:104568002041204B2D4D2041204E00616E64792062\r\n:104578006A61636B736F6E00507265737320412EAE\r\n:0E4588002E2E000D0A004C4F414445520000FB\r\n:00000001FF\r\n"
  },
  {
    "path": "PAK-MAN_MAKERbuino/PAK-MAN_MAKERbuino.ino",
    "content": "/*  2018\n *   \n *  PAK-MAN for MakerBuino and GameBuino by Andy Jackson - Twitter @andyhighnumber\n *  \n *  You need to install the 'Classic' GameBuino libraries in your Arduino IDE, like this:\n *  http://legacy.gamebuino.com/wiki/index.php?title=Getting_started#Install_the_Gamebuino_Library_.28Automatic.29\n *  \n *  Everything you need to build and run this game is contained in this file and the font \n *  header (font6x8AJ3.h) \n *  \n *  This is a port of a Pac-Man clone written for the AttinyArcade, which is why some of\n *  the display routines look a bit weird. More info here:\n *  https://github.com/andyhighnumber/Attiny-Arduino-Games\n *  \n *  Permission is hereby granted, free of charge, to any person obtaining a copy of \n *  this software and associated documentation files (the \"Software\"), to deal in the \n *  Software without restriction, including without limitation the rights to use, copy, \n *  modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, \n *  and to permit persons to whom the Software is furnished to do so, subject to the \n *  following conditions: \n *  \n *  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, \n *  INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR \n *  PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE \n *  FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR \n *  OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n *  DEALINGS IN THE SOFTWARE.\n * \n*/\n\n//imports the SPI library (needed to communicate with Gamebuino's screen)\n#include <SPI.h>\n//imports the Gamebuino library\n#include <Gamebuino.h>\n//creates a Gamebuino object named gb\nGamebuino gb;\n\n\n#include <EEPROM.h>\n#include \"font6x8AJ4.h\"\n\n#define DIR_RIGHT 0\n#define DIR_DOWN 1\n#define DIR_LEFT 2\n#define DIR_UP 3\n\n#define PACMAN 1\n#define GHOST1 2\n#define GHOST2 4\n#define GHOST3 8\n\n// Probability of a ghost taking a branch to the side if it can\n#define BRANCH_PROBABILITY 50\n// How many ghosts on level 1\n#define INITIAL_GHOSTS 2\n// Initial number of cycles before a ghost is released - reduces according to next two defines down to a min level\n#define INITIAL_GHOST_DELAY 150\n#define GHOST_DELAY_REDUCTION 25\n#define GHOST_DELAY_MINIMUM 50\n\n// How long does powerUp mode last?\n#define POWER_LENGTH 200\n\n/* ------ This section needs to be updated if you change the screen bitmap ------\n   ------------------------------------------------------------------------------*/\n\n// Where on the screen to the ghosts appear when they pop out onto the playing screen?\n#define GHOST_LAUNCH_X 64\n#define GHOST_LAUNCH_Y 16\n\n// How many pills are there on the screen?\n#define NO_PILLS 56\n\n// Where are the ghosts and pacman drawn initially?\n// In each of these, the order is - Ghost1, Ghost2, Ghost3, PAC-MAN\nstatic const byte startPosX[] = {66, 55, 77, 55};\nstatic const byte startPosY[] = {28, 28, 28, 40};\nstatic const byte startDirections[] = {DIR_UP, DIR_UP, DIR_UP, DIR_RIGHT};\n\n// Where are the big pills? (their row is fixed as the last one)\nstatic const byte bigPillLocations[2] PROGMEM = {14, 119};\n\n// How many pills on each row? for the six rows 1-7 that you are allowed pills\nstatic const byte readRow[6][2] PROGMEM = {\n  0, 12,\n  12, 23,\n  23, 31,\n  31, 34,\n  34, 45,\n  45, 56\n};\n\n// Where are the pills (x,y)\nstatic const byte pillLocations[NO_PILLS][2] PROGMEM = {\n  14, 8,\n  24, 8,\n  36, 8,\n  46, 8,\n  55, 8,\n  63, 8,\n  75, 8,\n  84, 8,\n  93, 8,\n  104, 8,\n  111, 8,\n  119, 8,\n  14, 20,\n  24, 20,\n  36, 20,\n  46, 20,\n  55, 20,\n  63, 20,\n  75, 20,\n  84, 20,\n  93, 20,\n  104, 17,\n  119, 17,\n  14, 31,\n  24, 31,\n  36, 31,\n  46, 31,\n  93, 31,\n  104, 25,\n  111, 25,\n  119, 25,\n  104, 37,\n  111, 37,\n  119, 37,\n  14, 43,\n  24, 43,\n  36, 43,\n  46, 43,\n  55, 43,\n  63, 43,\n  75, 43,\n  84, 43,\n  93, 43,\n  104, 46,\n  119, 46,\n  14, 55,\n  24, 55,\n  36, 55,\n  46, 55,\n  55, 55,\n  63, 55,\n  75, 55,\n  84, 55,\n  93, 55,\n  104, 55,\n  111, 55\n};\n\n\nconst byte PROGMEM openScreen[] = {\n    64,25,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0xf8,0x00,0x00,0x00,0x7c,0x00,0x00,\n    0x03,0xff,0x00,0x00,0x01,0xff,0x00,0x00,\n    0x07,0xff,0x80,0x00,0x03,0x79,0x80,0x00,\n    0x0f,0xff,0x80,0x00,0x06,0x20,0x80,0x00,\n    0x0f,0xff,0xc0,0x00,0x0c,0x00,0xc0,0x00,\n    0x1f,0xff,0xc0,0x00,0x08,0x00,0x40,0x00,\n    0x1f,0xff,0x00,0x00,0x08,0xe3,0x40,0x00,\n    0x3f,0xf8,0x00,0x00,0x18,0xe3,0x60,0x00,\n    0x3f,0xe1,0x99,0x99,0x98,0xe3,0x60,0x00,\n    0x3f,0xe1,0x99,0x99,0x98,0x00,0x60,0x00,\n    0x3f,0xf8,0x00,0x00,0x18,0x00,0x60,0x00,\n    0x3f,0xfc,0x00,0x00,0x18,0x00,0x60,0x00,\n    0x1f,0xff,0x00,0x00,0x18,0x00,0x60,0x00,\n    0x0f,0xff,0xc0,0x00,0x19,0xcc,0xe0,0x00,\n    0x0f,0xff,0xc0,0x00,0x1f,0xfe,0x60,0x00,\n    0x03,0xff,0x00,0x00,0x1d,0xff,0xe0,0x00,\n    0x03,0xfe,0x00,0x00,0x18,0xcc,0x60,0x00,\n    0x00,0xf8,0x00,0x00,0x18,0xcc,0x60,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\n  };\n\n// Display functions - a legacy from the AttinyArcade version - could be replaced with GameBuino function calls if you wish\nvoid lcdDisplay_send_byte(uint8_t byte);\nvoid lcdDisplay_setpos(uint8_t x, uint8_t y);\nvoid lcdDisplay_fillscreen(uint8_t fill_Data);\nvoid lcdDisplay_char_f6x8(uint8_t x, uint8_t y, const char ch[]);\n\n// Other generic functions for games (both originated in code from webboggles.com)\nvoid doNumber (int, int, int);\nvoid beep(int,int);\n\n// Game functions\nvoid playPacman(void);\nvoid levelUp(int);\nvoid showScore(void);\nvoid displayTitle(void);\nint checkCollision(byte xpos, byte ypos);\nvoid initScreen(void);\nvoid initLevel(void);\nvoid newDirection(byte ghostNo);\nbyte hitGhosts(void);\nvoid movePacman(void);\nvoid pacDie(void);\nvoid eatenGhost(void);\nvoid moveGhosts(void);\nbyte drawPacman(byte c, byte r);\n\n// Global variables - yes I know all these global vars is a lazy way to code but it makes it easier to prevent stack overflows when you're working with 512 bytes!\n// Most of these are initialised in the main game function (playPacman())\nboolean stopAnimate;      // this is set to 1 when a collision is detected\nint lives;                // Lives in the game - this can go negative to end the game, which is why it's a signed variable\nunsigned long clickBase;  // Timer for debounce\nboolean clickLock;        // For debounce routine\nint score;                // Obvious I hope\nint topScore;             // High score\nboolean newHigh;          // Is there a new high score?\nboolean mute = 0;         // Mute the speaker\nint mouth = 0;            // Is his mouth open?\nint directions[4];        // Directions of the four possible characters (pacman = 0, ghosts are 1-3)\nint commandDir;           // The desired direction set by input\nbyte pillsEaten = 0;      // How many pills have been eaten (there are 63 altogether)\nint ghostCounter = 0;     // How many ghosts\nint ghostsActive[3];      // How many ghosts are out?\nint count = 0;            // Counter\nint oldDir;               // Holds previous direction\nint level = 0;            // Obvious I hope\nint releaseDelay;         // The delay between ghosts being let out\nint maxGhosts;            // How many ghosts maximum on this level?\nbool powerUp;             // Is powerUp move active?\nint powerCounter;         // Counts the length of powerUp mode\nbyte locations[4][2];     // The x,y location of the sprites\nbyte pillsActive[NO_PILLS];    // Which of the pills is still on the screen?\nbyte bigPillsActive[2];   // Which of the two big pills is still active?\n\nbyte currentX, currentY, currentRow, currentCol;\n\nint screenTop, screenLeft;\n\n// Artwork\nstatic const byte pacOpen[4][8] PROGMEM = {\n  0x3C, 0x7E, 0xFF, 0xFF, 0xE7, 0xE7, 0xC3, 0x42,\n  0x7C, 0xFE, 0x3F, 0x0F, 0x0F, 0x3F, 0xFE, 0x7C,\n  0x42, 0xC3, 0xE7, 0xE7, 0xFF, 0xFF, 0x7E, 0x3C,\n  0x3E, 0x7F, 0xFC, 0xF0, 0xF0, 0xFC, 0x7F, 0x3E\n};\n\nstatic const byte pacClosed[] PROGMEM = {0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C};\n\nstatic const byte ghost[2][8] PROGMEM = {0x7C, 0xFE, 0x22, 0xEB, 0xFF, 0x62, 0xEA, 0x7C, 0x7C, 0xC2, 0x0A, 0x83, 0x83, 0x0A, 0x82, 0x7C};\n\nstatic const byte PAClives[] PROGMEM = {0x1C, 0x3C, 0x7E, 0x66, 0x66, 0x62, 0x40};\n\nstatic const byte openBmp[] PROGMEM = {\n  0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE,\n  0xFE, 0xFC, 0xFC, 0xF8, 0x70, 0x60, 0x00,\n  0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xEF, 0xC7, 0x87, 0x83,\n  0x83, 0x01, 0x00, 0x00, 0x10, 0x38, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7C,\n  0x38, 0x10,\n  0x00, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F,\n  0x7F, 0x3F, 0x3F, 0x3E, 0x1E, 0x1E\n};\n\nstatic const byte gameScreen[] PROGMEM = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x04, 0xF4, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,\n  0x14, 0x14, 0x13, 0x10, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x10, 0x13,\n  0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xE4, 0x04, 0xE4, 0x14, 0x14, 0x14, 0x14, 0x14,\n  0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,\n  0x14, 0x14, 0x14, 0x14, 0xE4, 0x04, 0xE4, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,\n  0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,\n  0x14, 0xE4, 0x04, 0xE4, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,\n  0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xE4, 0x04, 0xF8, 0x00,\n\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x40, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x40,\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x00, 0x40, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x40, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,\n  0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x7F, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x20, 0xA0, 0xA0,\n  0xA0, 0xA0, 0x20, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00,\n\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x2F, 0x2F,\n  0x2F, 0x2F, 0x20, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00,\n\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0xFE, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0xFE,\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x00, 0xFE, 0x01, 0xFD, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\n  0x05, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x05, 0x05, 0x05, 0x05, 0x05,\n  0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xFD, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0xFE, 0x01, 0x3E, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,\n  0x40, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00,\n\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x7F, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x7F,\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x20, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x00, 0x7F, 0x80, 0x9F, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,\n  0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,\n  0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x9F, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x7F, 0x80, 0x7E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n  0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00,\n\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x04, 0xF4, 0xF4,\n  0xF4, 0xF4, 0x04, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00,\n\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x02, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x02,\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x00, 0x02, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,\n  0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0x00, 0xFE, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x05, 0x05,\n  0x05, 0x05, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00,\n\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x27, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,\n  0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,\n  0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x27, 0x20, 0x27, 0x28, 0x28, 0x28, 0x28, 0x28,\n  0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,\n  0x28, 0x28, 0x28, 0x28, 0x27, 0x20, 0x27, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,\n  0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,\n  0x28, 0xC7, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x08, 0xC8, 0x28,\n  0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x27, 0x20, 0x1F, 0x00\n};\n\nvoid beep(int bCount,int bDelay){\n  if (mute) return;\n  for (int i = 0; i<=bCount; i++){\n    digitalWrite(3,HIGH);\n    for(int i2=0; i2<bDelay; i2++){\n      __asm__(\"nop\\n\\t\"); // 62.5ns delay @ 16MHz\n      }\n    digitalWrite(3,LOW);\n    for(int i2=0; i2<bDelay; i2++) {\n      __asm__(\"nop\\n\\t\"); // 62.5ns delay @ 16Mhz\n    }\n  }\n}\n\nvoid displayTitle(void) {\n  int incr = 0;\n  for (int lxn = 1; lxn < 4; lxn++) {\n    lcdDisplay_setpos(84, lxn);\n    for (int lxn2 = 0; lxn2 < 34; lxn2++) {\n      lcdDisplay_send_byte(pgm_read_byte(&openBmp[incr]));\n      incr++;\n      if ( (lxn == 1 || lxn == 3) && lxn2 > 21) lxn2 = 35;\n    }\n  }\n}\n\n// Arduino stuff - setup\nvoid setup() {\n  // initialize the Gamebuino object\n  gb.begin();\n  //display the main menu:\n  gb.titleScreen(F(\"PAK-MAN\"),openScreen);\n}\n\nvoid displayOpenScreen(int incr) {\n    lcdDisplay_fillscreen(1);\n    if (incr < 99) screenLeft = incr;\n    \n    lcdDisplay_char_f6x8(0, 1, \"P A K-M A N\");\n    lcdDisplay_char_f6x8(0, 3, \"andy jackson\");\n    lcdDisplay_char_f6x8(64, 5, \"Press A...\");\n\n    lcdDisplay_setpos(0, 0);\n    for (int incr2 = 0; incr2 < 76; incr2++) {\n      lcdDisplay_send_byte(B00111000);\n    }\n    \n    lcdDisplay_setpos(0, 2);\n    for (int incr2 = 0; incr2 < 76; incr2++) {\n      lcdDisplay_send_byte(B00011100);\n    }\n\n    displayTitle();\n}\n\n// Arduino stuff - loop\nvoid loop() {\n  lcdDisplay_fillscreen(1);\n  int sChange = 0;\n\n  screenLeft = 0;\n  \n  if (gb.buttons.pressed(BTN_B) == true) {\n      sChange = 1;     \n      EEPROM.write(0,0);\n      EEPROM.write(1,0);\n      lcdDisplay_char_f6x8(0, 0, \"--------------\");\n      lcdDisplay_char_f6x8(0, 1, \"HI SCORE RESET\");\n      lcdDisplay_char_f6x8(0, 3, \"--------------\");\n      while(!gb.update());\n      delay(2000);\n  }\n  \n  if (sChange == 0) {\n\n    lcdDisplay_fillscreen(1);\n\n    playPacman();\n\n    topScore = EEPROM.read(0);\n    topScore = topScore << 8;\n    topScore = topScore |  EEPROM.read(1);\n\n    newHigh = 0;\n    if (score > topScore) {\n      topScore = score;\n      EEPROM.write(1, score & 0xFF);\n      EEPROM.write(0, (score >> 8) & 0xFF);\n      newHigh = 1;\n    }\n\n    screenLeft = 0;\n\n    lcdDisplay_fillscreen(0x00);\n    lcdDisplay_char_f6x8(0, 0, \"------------\");\n    lcdDisplay_char_f6x8(0, 1, \"GAME  OVER\");\n    lcdDisplay_char_f6x8(0, 3, \"------------\");\n    showScore();\n    while(!gb.update());\n    delay(2500);\n    lcdDisplay_fillscreen(0x00);\n    lcdDisplay_char_f6x8(0, 0, \"---------------\");\n    lcdDisplay_char_f6x8(0, 3, \"---------------\");\n    doNumber(24, 2, topScore);\n    if (!newHigh) {\n      lcdDisplay_char_f6x8(0, 1, \"HIGH SCORE:\");\n    } else {\n      lcdDisplay_char_f6x8(0, 1, \"NEW HIGH:\");\n      for (int i = 700; i>200; i = i - 50){\n        beep(30,i);\n      }\n    }\n    while(!gb.update());\n    delay(2500);\n  }\n  \n  lcdDisplay_fillscreen(1);\n  gb.display.update();\n\n  while(gb.buttons.pressed(BTN_A) == true) { while(!gb.update()); delay(5);}\n\n  gb.sound.playNote(63,1,0);\n  while(!gb.update());\n  \n  screenLeft = 0;\n  for (int incr = 0; incr < 42 ; incr+=3) {\n    displayOpenScreen(incr);\n    gb.display.update();\n    if (incr == 0) delay(1700);\n  }\n\n  while(gb.buttons.pressed(BTN_A) == false && gb.buttons.pressed(BTN_B) == false ) {\n    displayOpenScreen(100);    \n    while(!gb.update());\n  } \n}\n\nvoid showScore(void) {\n  lcdDisplay_char_f6x8(0, 2, \"SCORE:\");\n  doNumber(44, 2, score);\n}\n\n// Handle what happens at the end of a level\nvoid levelUp() {\n  initScreen();\n  initLevel();\n  level++;\n  if ((level == 3) || (level == 5)) lives++;\n  if (maxGhosts < 3) maxGhosts++;\n  if (releaseDelay > GHOST_DELAY_MINIMUM) releaseDelay -= GHOST_DELAY_REDUCTION;\n  lcdDisplay_fillscreen(0x00);\n\n  screenLeft = 0;\n\n  lcdDisplay_char_f6x8(0, 3, \"LEVEL:\");\n  doNumber(44, 3, level);\n  showScore();\n  gb.display.update();\n\n  delay(2500);\n  lcdDisplay_fillscreen(0x00);\n  displayScreen();\n}\n\n\nvoid doNumber (int x, int y, int value) {\n  char temp[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\n  itoa(value, temp, 10);\n  lcdDisplay_char_f6x8(x, y, temp);\n}\n\n\nvoid lcdDisplay_send_byte(uint8_t input) {\n  for (int by = 0; by < 8; by++) {\n    if ((input >> by & B00000001) == 0) {\n      if ( (currentX >= screenLeft) && (currentX <= screenLeft + 84)) {\n        gb.display.setColor(WHITE, BLACK);\n        gb.display.drawPixel(currentX - screenLeft, (currentY) * 8 + by);\n      }\n    } else {\n      if ( (currentX >= screenLeft) && (currentX <= screenLeft + 84)) {\n        gb.display.setColor(BLACK, WHITE);\n        gb.display.drawPixel(currentX - screenLeft, (currentY) * 8 + by);\n      }\n    }\n  }\n  currentX++;\n}\n\nvoid lcdDisplay_setpos(uint8_t x, uint8_t y)\n{\n  currentX = x;\n  currentY = y;\n}\n\nvoid lcdDisplay_fillscreen(uint8_t fill_Data) {\n  gb.display.setColor(WHITE, BLACK);\n\n  for (int i = 0; i < 64; i++) {\n    for (int j = 0; j < 128; j++) {\n      gb.display.drawPixel(j, i);\n    }\n  }\n\n}\n\nvoid lcdDisplay_char_f6x8(uint8_t x, uint8_t y, const char ch[]) {\n  uint8_t c, i, j = 0;\n  while (ch[j] != '\\0')\n  {\n    c = ch[j] - 32;\n    if (c > 0) c = c - 12;\n    if (c > 15) c = c - 6;\n    if (c > 40) c = c - 9;\n    if (x > 126)\n    {\n      x = 0;\n      y++;\n    }\n    lcdDisplay_setpos(x, y);\n    for (i = 0; i < 6; i++)\n    {\n      lcdDisplay_send_byte(pgm_read_byte(&lcdDisplayxled_font6x8[c * 6 + i]));\n    }\n    x += 6;\n    j++;\n  }\n}\n\nbyte drawPacman(byte c, byte r) {\n  byte out = 0;\n  if ( (r >= locations[3][0]) && (r < locations[3][0] + 8) ) { // draw the pacMan if any of his body is on this column\n    if (c == locations[3][1] / 8) {\n      if (mouth == 1) {\n        out = (pgm_read_byte(&pacOpen[directions[3]][r - locations[3][0]]) << locations[3][1] % 8);\n      } else {\n        out = (pgm_read_byte(&pacClosed[r - locations[3][0]]) << locations[3][1] % 8);\n      }\n    } else if (c == locations[3][1] / 8 + 1) {\n      if (mouth == 1) {\n        out = (pgm_read_byte(&pacOpen[directions[3]][r - locations[3][0]]) >> (8 - locations[3][1] % 8) );\n      } else {\n        out = (pgm_read_byte(&pacClosed[r - locations[3][0]]) >> (8 - locations[3][1] % 8) );\n      }\n    }\n  }\n  return out;\n}\n\nbyte drawGhostSprite(byte c, byte r, byte lxn) {\n  byte out = 0;\n\n  if ( (r >= locations[lxn][0]) && (r < locations[lxn][0] + 8) ) {\n      if (c == locations[lxn][1] / 8) {\n        out |= (pgm_read_byte(&ghost[powerUp][r - locations[lxn][0]]) << locations[lxn][1] % 8);\n      } else if (c == locations[lxn][1] / 8 + 1) {\n        out |= (pgm_read_byte(&ghost[powerUp][r - locations[lxn][0]]) >> (8 - locations[lxn][1] % 8) );\n      }\n    }\n\n  return out;\n}\n\nbyte drawPills(byte c, byte r) {\n  byte out = 0;\n      // draw the pills and also check whether pacman is eating an active pill\n      if (c > 0 && c < 7) {\n        for (byte lxn = pgm_read_byte(&readRow[c - 1][0]); lxn < pgm_read_byte(&readRow[c - 1][1]); lxn++) {\n          if (pillsActive[lxn]) { // this pill is active\n            if (r == pgm_read_byte(&pillLocations[lxn][0])) { // draw the pills if they appear here\n              // check if pac-man has eaten a pill\n              if (pgm_read_byte(&pillLocations[lxn][0]) > locations[3][0] && pgm_read_byte(&pillLocations[lxn][0]) < locations[3][0] + 8 && pgm_read_byte(&pillLocations[lxn][1]) > locations[3][1] && pgm_read_byte(&pillLocations[lxn][1]) < locations[3][1] + 8) {\n                pillsActive[lxn] = 0;\n                pillsEaten++;\n                score += level;\n                break;\n              }\n              if (c == pgm_read_byte(&pillLocations[lxn][1]) / 8) {\n                out |= ((B00000001) << pgm_read_byte(&pillLocations[lxn][1]) % 8);\n              } else if (c == pgm_read_byte(&pillLocations[lxn][1]) / 8 + 1) {\n                out |= ((B00000001) >> (8 - pgm_read_byte(&pillLocations[lxn][1]) % 8) );\n              }\n            }\n          }\n        }\n      }\n  return out;  \n}\n\nbyte drawBigPills(byte c, byte r) {\n  byte out = 0;\n  \n  for (byte lxn = 0; lxn < 2; lxn++) {\n    if (bigPillsActive[lxn] == 1 && c == 6 && (r == pgm_read_byte(&bigPillLocations[lxn]) || r == (pgm_read_byte(&bigPillLocations[lxn]) + 1) )) {\n      out |= B11100000;\n    }\n  }\n  return out;\n}\n\nbyte createScreenOut(byte c, byte r) {\n  byte out;\n      // 'out' is the byte we're going to write, starts with the background image\n      out = (pgm_read_byte(&gameScreen[c*128+r]));\n\n      // add pacman, if part of his sprite is on this space\n      out |= drawPacman(c, r);\n\n      // Draw the lives in the far left column\n      if (r < 7) {\n        for (byte lxn = 3; lxn < 7; lxn++) {\n          if (c == lxn && lives > 6 - lxn) out |= (pgm_read_byte(&PAClives[r]));\n        }\n      }\n\n      // draw a ghost if any of their sprites are on this column and row\n      for (byte lxn = 0; lxn < 3; lxn++) {\n        out |= drawGhostSprite(c, r, lxn);\n      }\n\n      out |= drawPills(c, r);\n\n      // Draw the big pills\n      out |= drawBigPills(c, r);\n\n  return out;\n}\n\nvoid displayScreen(void) {\n  int pacDir = directions[3];\n  byte out;\n  uint8_t *disp;\n  char nextRow[84];\n\n  // For each row on the screen (there's 8 - I think of them as columns, hence 'c', I don't know why!)\n\n  disp = gb.display.getBuffer();\n\n\n  byte c = screenTop /8 + 6;\n  for (byte r= screenLeft; r < screenLeft+84; r++) {\n    nextRow[r-screenLeft] = createScreenOut(c, r);\n  }\n\n  for (byte c = screenTop /8 + 5; c > screenTop /8; c--) {\n    for (byte r = screenLeft; r < screenLeft+84; r++) {\n\n    byte thisRow = createScreenOut(c, r);\n    \n    out = ( (thisRow >> screenTop % 8) | (nextRow[r-screenLeft] << 8- screenTop % 8));\n\n    nextRow[r-screenLeft] = thisRow;\n    \n    *(disp + r - screenLeft + ((c - screenTop/8) * 84)) = out;\n\n    }\n  }\n\n  c = screenTop /8;\n  for (byte r= screenLeft; r < screenLeft+84; r++) {\n    byte thisRow = createScreenOut(c, r);\n    out = ( (thisRow >> screenTop % 8) | (nextRow[r-screenLeft] << 8- screenTop % 8));\n    *(disp + r - screenLeft + ((c - screenTop/8) * 84)) = out;\n  }\n  \n  //gb.display.update();\n}\n\nint checkCollision(byte xpos, byte ypos) {\n  int incr = 0;\n  int returnValue = 0;\n\n  for (byte c = 0; c < 2; c++) { // for each of the two lines that the item might be on\n    incr = (128 * (ypos / 8 + c)) + xpos;\n    for (byte r = 0; r < 8; r++) { // for each of the eight bytes in the sprite\n      if (c == 0) {\n        if ((pgm_read_byte(&gameScreen[incr]) & (0xFF << ypos % 8) ) != 0) returnValue = 1;\n      } else {\n        if ((pgm_read_byte(&gameScreen[incr]) & (0xFF >> (8 - ypos % 8) ) ) != 0) returnValue = 1;\n      }\n      incr++;\n    }\n  }\n  return returnValue;\n}\n\nvoid moveGhosts(void) {\n  int travelDirection;  // which way's the ghost going?\n  byte travelParam;     // zero for travelling in x, one for y\n  int searchDirection;  // +1 to search up, -1 to search down for side exits\n  byte paramSelection;  // zero for xPosition, one for yPosition\n  byte switchDirection; // which direction to switch to if there's a switch\n\n  ghostCounter++;\n\n  // Pop the next ghost out, if it's time\n  if (ghostCounter >= releaseDelay) {\n    ghostCounter = 0;\n    for (byte lxn = 0; lxn < maxGhosts; lxn++) {\n      if (ghostsActive[lxn] == 0) {\n        locations[lxn][0] = GHOST_LAUNCH_X;\n        locations[lxn][1] = GHOST_LAUNCH_Y;\n        ghostsActive[lxn] = 1;\n        break;\n      }\n    }\n  }\n\n  for (byte lxn = 0; lxn < 3; lxn++) {\n    if (ghostsActive[lxn] == 1) {\n      char clash = 0;\n\n      // Start with a default set (which is DIR_RIGHT) then only change the things that differ from this in the switch statements below\n      // (saves two bytes of code, but every bit helps!)\n      travelDirection = 1;\n      travelParam = 0;\n      searchDirection = -1;\n      paramSelection = 1;\n      switchDirection = DIR_UP;\n\n      switch (directions[lxn]) {\n        case (DIR_LEFT):\n          travelDirection = -1;\n          searchDirection = 1;\n          switchDirection = DIR_DOWN;\n          break;\n\n        case (DIR_UP):\n          travelDirection = -1;\n          travelParam = 1;\n          paramSelection = 0;\n          switchDirection = DIR_LEFT;\n          break;\n\n        case (DIR_DOWN):\n          travelParam = 1;\n          searchDirection = 1;\n          paramSelection = 0;\n          switchDirection = DIR_RIGHT;\n          break;\n      }\n\n      locations[lxn][travelParam] += travelDirection;\n      // Move the ghosts along according to which way they are heading - if there's a clash, then backtrack\n      if (checkCollision(locations[lxn][0], locations[lxn][1]) == 1) {\n        locations[lxn][travelParam] -= travelDirection;\n        newDirection(lxn);\n      } else {\n        clash = 0;\n        for (byte lxn2 = 0; lxn2 < 3; lxn2++) {\n          locations[lxn][paramSelection] += searchDirection;\n          if (checkCollision(locations[lxn][0], locations[lxn][1]) == 1) clash = 1;\n        }\n        if (clash == 0 && random(100) > BRANCH_PROBABILITY) directions[lxn] = switchDirection;\n        locations[lxn][paramSelection] -= (searchDirection * 3);\n      }\n    }\n  }\n}\n\nvoid newDirection(byte ghostNo) {\n  directions[ghostNo] = random(4);\n}\n\nvoid eatenGhost(void) {\n  for (int i = 700; i>200; i = i - 50){\n    beep(30,i);\n  }\n}\n\nbyte hitGhosts(void) {\n  byte returnCode = 0;\n\n  for (int lxn = 0; lxn < 3 ; lxn++) {\n    if ((locations[lxn][0] > locations[3][0] - 8) && (locations[lxn][0] < locations[3][0] + 8) && (locations[lxn][1] > locations[3][1] - 8) && (locations[lxn][1] < locations[3][1] + 8)) {\n      if (powerUp == 1) {\n        locations[lxn][0] = startPosX[lxn];\n        locations[lxn][1] = startPosY[lxn];\n        ghostsActive[lxn] = 0;\n        eatenGhost();\n        score += 10;\n        ghostCounter = 0;\n      } else returnCode = 1;\n    }\n  }\n  return returnCode;\n}\n\nvoid pacDie(void) {\n  int i;\n  directions[3] = DIR_UP;\n  mouth = 1;\n  displayScreen();\n  for (i = 0; i<500; i = i+ 50){  \n    beep(50,i);\n  }\n  while(!gb.update());\n  displayScreen();\n  while(!gb.update());\n  mouth = 0;\n  displayScreen();\n  for (i = 500; i<1000; i = i+ 50){  \n    beep(50,i);\n  }\n  while(!gb.update());\n  displayScreen();\n  delay(500);\n  stopAnimate = 1;\n}\n\nvoid movePacman(void) {\n  count++;\n  if (count == 2) {\n    if (mouth == 0) {mouth = 1; beep(4,850-powerUp*200);beep(5,720-powerUp*200);beep(4,620-powerUp*200);beep(5,570-powerUp*200);} else {mouth = 0; beep(5,570);beep(4,620);beep(5,720);beep(4,850);}\n    count = 0;\n  }\n\n  if (powerUp == 1) {\n    powerCounter++;\n    if (powerCounter >= POWER_LENGTH) {\n      powerUp = 0;\n      powerCounter = 0;\n    }\n  }\n\n  oldDir = directions[3];\n  directions[3] = commandDir;\n\n  screenLeft = locations[3][0] - 30;\n  screenTop =  locations[3][1] - 20;\n\n  if (screenLeft < 0) screenLeft = 0;\n  if (screenTop < 0) screenTop = 0;\n  if (screenLeft > 43) screenLeft = 43;\n  if (screenTop > 16) screenTop = 16;\n\n  switch (directions[3]) {\n    case (DIR_RIGHT):\n      for (int lxn = 0; lxn < 3; lxn++) {\n        locations[3][0]++;\n        if (checkCollision(locations[3][0], locations[3][1]) == 1) {\n          directions[3] = oldDir;\n        }\n      }\n      locations[3][0] -= 3;\n      break;\n\n    case (DIR_LEFT):\n      for (int lxn = 0; lxn < 3; lxn++) {\n        locations[3][0]--;\n        if (checkCollision(locations[3][0], locations[3][1]) == 1) {\n          directions[3] = oldDir;\n        }\n      }\n      locations[3][0] += 3;\n      break;\n\n    case (DIR_UP):\n      for (int lxn = 0; lxn < 3; lxn++) {\n        locations[3][1]--;\n        if (checkCollision(locations[3][0], locations[3][1]) == 1) {\n          directions[3] = oldDir;\n        }\n      }\n      locations[3][1] += 3;\n      break;\n\n    case (DIR_DOWN):\n      for (int lxn = 0; lxn < 3; lxn++) {\n        locations[3][1]++;\n        if (checkCollision(locations[3][0], locations[3][1]) == 1) {\n          directions[3] = oldDir;\n        }\n      }\n      locations[3][1] -= 3;\n      break;\n  }\n\n  switch (directions[3]) {\n    case (DIR_RIGHT):\n      locations[3][0] += 1;\n      if (checkCollision(locations[3][0], locations[3][1]) == 1) locations[3][0] -= 1;\n      break;\n\n    case (DIR_LEFT):\n      locations[3][0] -= 1;\n      if (checkCollision(locations[3][0], locations[3][1]) == 1) locations[3][0] += 1;\n      break;\n\n    case (DIR_UP):\n      locations[3][1] -= 1;\n      if (checkCollision(locations[3][0], locations[3][1]) == 1) locations[3][1] += 1;\n      break;\n\n    case (DIR_DOWN):\n      locations[3][1] += 1;\n      if (checkCollision(locations[3][0], locations[3][1]) == 1) locations[3][1] -= 1;\n      break;\n  }\n\n  // If pacman is on the bottom row, check if he's eaten either of the big pills\n  if (locations[3][1] == 51) {\n    if ((locations[3][0] < 14 && bigPillsActive[0] == 1) || (locations[3][0] > 111 && bigPillsActive[1] == 1)) {\n      if (locations[3][0] < 14) bigPillsActive[0] = 0; else bigPillsActive[1] = 0;\n      powerUp = 1;\n      powerCounter = 0;\n    }\n  }\n}\n\nvoid initLevel(void) {\n  pillsEaten = 0;\n  stopAnimate = 0;\n\n  for (byte lxn = 0; lxn < NO_PILLS; lxn++) pillsActive[lxn] = 1;\n  bigPillsActive[0] = 1;\n  bigPillsActive[1] = 1;\n}\n\nvoid initScreen(void) {\n  powerUp = 0;\n  powerCounter = 0;\n  ghostsActive[0] = 0;\n  ghostsActive[1] = 0;\n  ghostsActive[2] = 0;\n  ghostCounter = 0;\n\n  // Set up the initial directions of the ghosts and pacman\n  for (byte lxn = 0; lxn < 4; lxn++) {\n    locations[lxn][0] = startPosX[lxn];\n    locations[lxn][1] = startPosY[lxn];\n    directions[lxn] = startDirections[lxn];\n  }\n\n  // Initially set pacman off in the direction he is facing\n  commandDir = startDirections[3];\n}\n\n/* ------------------------\n    Pacman main game code\n*/\nvoid playPacman() {\n  score = 0;\n  lives = 2;\n  level = 1;\n  releaseDelay = INITIAL_GHOST_DELAY;\n  maxGhosts = INITIAL_GHOSTS;\n\n  initLevel();\n  initScreen();\n\n  while (lives >= 0) {\n    while(!gb.update());\n\n    if (gb.buttons.pressed(BTN_LEFT) == true) commandDir = DIR_LEFT;\n    if (gb.buttons.pressed(BTN_RIGHT) == true) commandDir = DIR_RIGHT;\n    if (gb.buttons.pressed(BTN_UP) == true) commandDir = DIR_UP;\n    if (gb.buttons.pressed(BTN_DOWN) == true) commandDir = DIR_DOWN;\n\n    if (pillsEaten >= NO_PILLS) levelUp();\n\n    moveGhosts();\n    movePacman();\n\n    // Check for ghosrs or pacman going thru the tunnel teleport thing\n    for (byte lxn2 = 0; lxn2 < 4; lxn2 ++) {\n      if (locations[lxn2][1] <= 0) {\n        locations[lxn2][1] = 56;\n        locations[lxn2][0] = 100;\n      } else if (locations[lxn2][1] >= 56) {\n        locations[lxn2][1] = 0;\n        locations[lxn2][0] = 21;\n      }\n    }\n\n    if (hitGhosts() != 0) {\n      pacDie();\n      lives--;\n      initScreen();\n    }\n    \n    displayScreen();\n\n  }\n  initScreen();\n}\r\n"
  },
  {
    "path": "PAK-MAN_MAKERbuino/font6x8AJ4.h",
    "content": "/*\n * Font file - originally from SSD1306xLED - Drivers for SSD1306 controlled dot matrix OLED/PLED 128x64 displays\n *\n * @file: font6x8AJ4.h\n * @created: 2014-08-12, edited by andy jackson 2018 (see below)\n * @author: Neven Boyanov\n * \n * Hacked by andy jackson to optimise size for the AttinyArcade - hence several characters \n * are missing and a couple have been moved to limit the amount of software remapping required\n * to map ASCII values onto locations in this array.\n *\n * Source code available at: https://bitbucket.org/tinusaur/ssd1306xled\n *\n */\n\n// ----------------------------------------------------------------------------\n\n#include <avr/pgmspace.h>\n\n// ----------------------------------------------------------------------------\n\n/* Standard ASCII 6x8 font */\nstatic const uint8_t lcdDisplayxled_font6x8 [] PROGMEM = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sp\n/*\n  0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // !\n  0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // \"\n  0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // #\n  0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $\n  0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // %\n  0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // &\n  0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // '\n  0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // (\n  0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // )\n  0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // *\n  0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // +\n  0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // ,\n  */\n  0x00, 0x00, 0x08, 0x08, 0x08, 0x00, // -\n  0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // .\n  0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // /\n  0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0\n  0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, // 1\n  0x00, 0x42, 0x61, 0x51, 0x49, 0x46, // 2\n  0x00, 0x21, 0x41, 0x45, 0x4B, 0x31, // 3\n  0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, // 4\n  0x00, 0x27, 0x45, 0x45, 0x45, 0x39, // 5\n  0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6\n  0x00, 0x01, 0x71, 0x09, 0x05, 0x03, // 7\n  0x00, 0x36, 0x49, 0x49, 0x49, 0x36, // 8\n  0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, // 9\n  0x00, 0x00, 0x36, 0x36, 0x00, 0x00, // :\n/*\n  0x00, 0x00, 0x56, 0x36, 0x00, 0x00, // ;\n  0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // <\n  0x00, 0x14, 0x14, 0x14, 0x14, 0x14, // =\n  0x00, 0x00, 0x41, 0x22, 0x14, 0x08, // >\n  0x00, 0x02, 0x01, 0x51, 0x09, 0x06, // ?\n  0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, // @\n */\n  0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, // B\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, // C\n  0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, // D\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, // E\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, // F\n  0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, // G\n  0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, // H\n  0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, // I\n  0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, // J\n  0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, // K\n  0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, // L\n  0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M\n  0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, // N\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, // O\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, // P\n  0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q\n  0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, // R\n  0x00, 0x46, 0x49, 0x49, 0x49, 0x31, // S\n  0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, // T\n  0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, // U\n  0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, // V\n  0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, // W\n  /*\n  0x00, 0x63, 0x14, 0x08, 0x14, 0x63, // X\n  0x00, 0x07, 0x08, 0x70, 0x08, 0x07, // Y\n  0x00, 0x61, 0x51, 0x49, 0x45, 0x43, // Z\n  0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, // [\n  0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55, // 55\n  0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, // ]\n  0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^\n  0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _\n  0x00, 0x00, 0x01, 0x02, 0x04, 0x00, // '\n*/\n  0x00, 0x20, 0x54, 0x54, 0x54, 0x78, // a\n  0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, // b\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x20, // c\n  0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, // d\n  0x00, 0x38, 0x54, 0x54, 0x54, 0x18, // e\n  0x00, 0x08, 0x7E, 0x09, 0x01, 0x02, // f\n  0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g\n  0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h\n  0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, // i\n  0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, // j\n  0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, // k\n  0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, // l\n  0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, // m\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, // n\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x38, // o\n  0x00, 0xFC, 0x24, 0x24, 0x24, 0x18, // p\n  0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, // q\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, // r\n  0x00, 0x48, 0x54, 0x54, 0x54, 0x20, // s\n  0x00, 0x04, 0x3F, 0x44, 0x40, 0x20, // t\n  0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, // u\n  0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, // v\n  0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w\n  0x00, 0x44, 0x28, 0x10, 0x28, 0x44, // x\n  0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C  // y\n};\n\n// ----------------------------------------------------------------------------\n\r\n"
  },
  {
    "path": "Pacman_Attiny_Arcade/Pacman_Attiny_Arcade.ino",
    "content": "/*  2015 / 2016 / 2017\r\n    Pacman for Attiny Arcade by Andy Jackson - Twitter @andyhighnumber\r\n\r\n    Inspired by http://webboggles.com/ and includes some code from the #AttinyArcade games on that site\r\n    The code that does not fall under the licenses of sources listed below can be used non commercially with attribution.\r\n    This software is supplied without warranty of any kind.\r\n\r\n *  **** BEFORE USE, BURN THE BOOTLOADER ON THE ATTINY85 WITH 16Mhz Internal Clock and note the specific ATtiny libraries required for this sketch (see below) *\r\n\r\n    Controls:\r\n    On the standard AttinyArcade:\r\n\r\n    Tap left button to turn 90 degrees left (each tap cycles through directions, so if you are going left and\r\n    you tap once, you will go down, tap twice and you'll be going right)\r\n\r\n    Tap right button to turn 90 degrees right (each tap cycles through directions, so if you are going left and\r\n    you tap once, you will go up, tap twice and you'll be going right)\r\n\r\n    The arrow indicator on the far left of the screen indicates the currently-selected direction, which pac-man will take as soon as there's a gap big enough for him!\r\n\r\n    Also, from standby....\r\n    Press and hold left button to turn sound on and off\r\n    Press and hold left button with the right button held to reset high score\r\n\r\n    Everything you need to build and run this game is contained in this file and the font header (font6x8AJ3.h) - no additional libraries required\r\n\r\n    Instructions for programming the Attiny85 can be found here (but note the specific Attiny85 library required below): https://create.arduino.cc/projecthub/arjun/programming-attiny85-with-arduino-uno-afb829\r\n\r\n    **** NOTE ****\r\n    Unlike my other games, this one seems to only compile with one specific set of libraries - the ones here: http://drazzy.com/package_drazzy.com_index.json from Spence Konde - with the following options:\r\n    - Board: AttinyCore-> Attiny 25/45/85 (No Bootloader)\r\n    - Chip: Attiny85\r\n    - Clock: 16Mhz PLL\r\n    - B.O.D. Disabled\r\n\r\n    All other settings default.\r\n\r\n    Don't forget to burn the bootloader first!\r\n    ************ \r\n\r\n    This sketch is using the screen control and font functions written by Neven Boyanov for the http://tinusaur.wordpress.com/ project\r\n    Source code and font files available at: https://bitbucket.org/tinusaur/ssd1306xled\r\n *  **Note that this highly size-optimised version requires modified library functions (which are in this source code file)\r\n    and a modified font header\r\n\r\n    As well as the above sources of inspiration, the pac-man screen artwork was insipred by elements of another clone found here https://sites.google.com/view/arduino-collection\r\n\r\n    Sleep code is based on this blog post by Matthew Little:\r\n    http://www.re-innovation.co.uk/web12/index.php/en/blog-75/306-sleep-modes-on-attiny85\r\n*/\r\n#include <EEPROM.h>\r\n#include \"font6x8AJ3.h\"\r\n#include <avr/pgmspace.h>\r\n#include <avr/sleep.h>\r\n#include <avr/interrupt.h> // needed for the additional interrupt\r\n\r\n// Debounce factor - around 50 works ok with AttinyArcade, but you might need to increase this number if you are using differnt hardware\r\n// and are finding that you're getting multiple direction changes from a single click\r\n#define CLICKDELAY 52\r\n\r\n#define DIR_RIGHT 0\r\n#define DIR_DOWN 1\r\n#define DIR_LEFT 2\r\n#define DIR_UP 3\r\n\r\n#define PACMAN 1\r\n#define GHOST1 2\r\n#define GHOST2 4\r\n#define GHOST3 8\r\n\r\n// Probability of a ghost taking a branch to the side if it can\r\n#define BRANCH_PROBABILITY 50\r\n// How many ghosts on level 1\r\n#define INITIAL_GHOSTS 2\r\n// Initial number of cycles before a ghost is released - reduces according to next two defines down to a min level\r\n#define INITIAL_GHOST_DELAY 150\r\n#define GHOST_DELAY_REDUCTION 25\r\n#define GHOST_DELAY_MINIMUM 50\r\n\r\n// You start with two (spare) lives\r\n#define START_LIVES 2\r\n\r\n// How long does powerUp mode last?\r\n#define POWER_LENGTH 200\r\n\r\n#define DIGITAL_WRITE_HIGH(PORT) PORTB |= (1 << PORT)\r\n#define DIGITAL_WRITE_LOW(PORT) PORTB &= ~(1 << PORT)\r\n\r\n// Routines to set and clear bits (used in the sleep code)\r\n#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))\r\n#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))\r\n\r\n// Defines for OLED output\r\n#define SSD1306XLED_H\r\n#define SSD1306_SCL   PORTB4  // SCL, Pin 4 on SSD1306 Board - for webbogles board\r\n#define SSD1306_SDA   PORTB3  // SDA, Pin 3 on SSD1306 Board - for webbogles board\r\n#define SSD1306_SA    0x78  // Slave address\r\n\r\n/* ------ This section needs to be updated if you change the screen bitmap ------\r\n   ------------------------------------------------------------------------------*/\r\n\r\n// Where on the screen to the ghosts appear when they pop out onto the playing screen?\r\n#define GHOST_LAUNCH_X 64\r\n#define GHOST_LAUNCH_Y 16\r\n\r\n// How many pills are there on the screen?\r\n#define NO_PILLS 56\r\n\r\n// Where are the ghosts and pacman drawn initially?\r\n// In each of these, the order is - Ghost1, Ghost2, Ghost3, PAC-MAN\r\nstatic const byte startPosX[] = {66, 55, 77, 55};\r\nstatic const byte startPosY[] = {28, 28, 28, 40};\r\nstatic const byte startDirections[] = {DIR_UP, DIR_UP, DIR_UP, DIR_RIGHT};\r\n\r\n// Where are the big pills? (their row is fixed as the last one)\r\nstatic const byte bigPillLocations[2] PROGMEM = {14, 119};\r\n\r\n// How many pills on each row? for the six rows 1-7 that you are allowed pills\r\nstatic const byte readRow[6][2] PROGMEM = {\r\n  0, 12,\r\n  12, 23,\r\n  23, 31,\r\n  31, 34,\r\n  34, 45,\r\n  45, 56\r\n};\r\n\r\n// Where are the pills (x,y)\r\nstatic const byte pillLocations[NO_PILLS][2] PROGMEM = {\r\n  14, 8,\r\n  24, 8,\r\n  36, 8,\r\n  46, 8,\r\n  55, 8,\r\n  63, 8,\r\n  75, 8,\r\n  84, 8,\r\n  93, 8,\r\n  104, 8,\r\n  111, 8,\r\n  119, 8,\r\n\r\n  14, 20,\r\n  24, 20,\r\n  36, 20,\r\n  46, 20,\r\n  55, 20,\r\n  63, 20,\r\n  75, 20,\r\n  84, 20,\r\n  93, 20,\r\n  104, 17,\r\n  119, 17,\r\n\r\n  14, 31,\r\n  24, 31,\r\n  36, 31,\r\n  46, 31,\r\n  93, 31,\r\n  104, 25,\r\n  111, 25,\r\n  119, 25,\r\n\r\n  104, 37,\r\n  111, 37,\r\n  119, 37,\r\n\r\n  14, 43,\r\n  24, 43,\r\n  36, 43,\r\n  46, 43,\r\n  55, 43,\r\n  63, 43,\r\n  75, 43,\r\n  84, 43,\r\n  93, 43,\r\n  104, 46,\r\n  119, 46,\r\n\r\n  14, 55,\r\n  24, 55,\r\n  36, 55,\r\n  46, 55,\r\n  55, 55,\r\n  63, 55,\r\n  75, 55,\r\n  84, 55,\r\n  93, 55,\r\n  104, 55,\r\n  111, 55\r\n};\r\n\r\n// Drawing functions - adapted from those at https://bitbucket.org/tinusaur/ssd1306xled\r\nvoid ssd1306_init(void);\r\nvoid ssd1306_xfer_start(void);\r\nvoid ssd1306_xfer_stop(void);\r\nvoid ssd1306_send_byte(uint8_t byte);\r\nvoid ssd1306_send_command(uint8_t command);\r\nvoid ssd1306_send_data_start(void);\r\nvoid ssd1306_send_data_stop(void);\r\nvoid ssd1306_setpos(uint8_t x, uint8_t y);\r\nvoid ssd1306_fillscreen(uint8_t fill_Data);\r\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]);\r\nvoid ssd1306_draw_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t bitmap[]);\r\n\r\n// Other generic functions for games (both originated in code from webboggles.com and the sleep code is by Matthew Little - see above)\r\nvoid beep(int, int);\r\nvoid system_sleep(void);\r\nvoid doNumber (int, int, int);\r\n\r\n// Game functions\r\nvoid playPacman(void);\r\nvoid levelUp(int);\r\nvoid showScore(void);\r\nvoid displayTitle(void);\r\nint checkCollision(byte xpos, byte ypos);\r\nvoid initScreen(void);\r\nvoid initLevel(void);\r\nvoid newDirection(byte ghostNo);\r\nbyte hitGhosts(void);\r\nvoid movePacman(void);\r\nvoid pacDie(void);\r\nvoid eatenGhost(void);\r\nvoid moveGhosts(void);\r\nbyte drawPacman(byte c, byte r);\r\n\r\n\r\n// Global variables - yes I know all these global vars is a lazy way to code but it makes it easier to prevent stack overflows when you're working with 512 bytes!\r\n// Most of these are initialised in the main game function (playPacman())\r\nboolean stopAnimate;      // this is set to 1 when a collision is detected\r\nint lives;                // Lives in the game - this can go negative to end the game, which is why it's a signed variable\r\nunsigned long clickBase;  // Timer for debounce\r\nboolean clickLock;        // For debounce routine\r\nint score;                // Obvious I hope\r\nint topScore;             // High score\r\nboolean newHigh;          // Is there a new high score?\r\nboolean mute = 0;         // Mute the speaker\r\nint mouth = 0;            // Is his mouth open?\r\nint directions[4];        // Directions of the four possible characters (pacman = 0, ghosts are 1-3)\r\nint commandDir;           // The desired direction set by input\r\nbyte pillsEaten = 0;      // How many pills have been eaten (there are 63 altogether)\r\nint ghostCounter = 0;     // How many ghosts\r\nint ghostsActive[3];      // How many ghosts are out?\r\nint gCount = 0;            // Counter for ghost behaviour\r\nint pCount = 0;            // Counter pac-man behaviour\r\nint oldDir;               // Holds previous direction\r\nint level = 0;            // Obvious I hope\r\nint releaseDelay;         // The delay between ghosts being let out\r\nint maxGhosts;            // How many ghosts maximum on this level?\r\nbool powerUp;             // Is powerUp move active?\r\nint powerCounter;         // Counts the length of powerUp mode\r\nbyte locations[4][2];     // The x,y location of the sprites\r\nbyte pillsActive[NO_PILLS];    // Which of the pills is still on the screen?\r\nbyte bigPillsActive[2];   // Which of the two big pills is still active?\r\nbool flipFlop = 0;        // Used to make the ghosts flash\r\n\r\n// Artwork\r\nstatic const byte pacOpen[4][8] PROGMEM = {\r\n  0x3C, 0x7E, 0xFF, 0xFF, 0xE7, 0xE7, 0xC3, 0x42,\r\n  0x7C, 0xFE, 0x3F, 0x0F, 0x0F, 0x3F, 0xFE, 0x7C,\r\n  0x42, 0xC3, 0xE7, 0xE7, 0xFF, 0xFF, 0x7E, 0x3C,\r\n  0x3E, 0x7F, 0xFC, 0xF0, 0xF0, 0xFC, 0x7F, 0x3E\r\n};\r\n\r\nstatic const byte arrows[4][7] PROGMEM = {\r\n  0x10, 0x10, 0x10, 0x7C, 0x38, 0x10, 0x00,\r\n  0x00, 0x20, 0x60, 0xFF, 0x60, 0x20, 0x00,\r\n  0x10, 0x38, 0x7C, 0x10, 0x10, 0x10, 0x00,\r\n  0x00, 0x04, 0x06, 0xFF, 0x06, 0x04, 0x00\r\n};\r\n\r\nstatic const byte pacClosed[] PROGMEM = {0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C};\r\n\r\nstatic const byte ghost[2][8] PROGMEM = {0x7C, 0xFE, 0x22, 0xEB, 0xFF, 0x62, 0xEA, 0x7C, 0x7C, 0xC2, 0x0A, 0x83, 0x83, 0x0A, 0x82, 0x7C};\r\n\r\nstatic const byte PAClives[] PROGMEM = {0x1C, 0x3C, 0x7E, 0x66, 0x66, 0x62, 0x40};\r\n\r\nstatic const byte openBmp[] PROGMEM = {\r\n  0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE,\r\n  0xFE, 0xFC, 0xFC, 0xF8, 0x70, 0x60, 0x00,\r\n  0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xEF, 0xC7, 0x87, 0x83,\r\n  0x83, 0x01, 0x00, 0x00, 0x10, 0x38, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7C,\r\n  0x38, 0x10,\r\n  0x00, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F,\r\n  0x7F, 0x3F, 0x3F, 0x3E, 0x1E, 0x1E\r\n};\r\n\r\n\r\nstatic const byte gameScreen[] PROGMEM = {\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x04, 0xF4, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,\r\n  0x14, 0x14, 0x13, 0x10, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x10, 0x13,\r\n  0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xE4, 0x04, 0xE4, 0x14, 0x14, 0x14, 0x14, 0x14,\r\n  0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,\r\n  0x14, 0x14, 0x14, 0x14, 0xE4, 0x04, 0xE4, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,\r\n  0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,\r\n  0x14, 0xE4, 0x04, 0xE4, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,\r\n  0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xE4, 0x04, 0xF8, 0x00,\r\n\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x40, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x40,\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x00, 0x40, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x40, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,\r\n  0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x7F, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x20, 0xA0, 0xA0,\r\n  0xA0, 0xA0, 0x20, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00,\r\n\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x2F, 0x2F,\r\n  0x2F, 0x2F, 0x20, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00,\r\n\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0xFE, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0xFE,\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x00, 0xFE, 0x01, 0xFD, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\r\n  0x05, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x05, 0x05, 0x05, 0x05, 0x05,\r\n  0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xFD, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0xFE, 0x01, 0x3E, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,\r\n  0x40, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00,\r\n\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x7F, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x7F,\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x20, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x00, 0x7F, 0x80, 0x9F, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,\r\n  0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,\r\n  0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x9F, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x7F, 0x80, 0x7E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\r\n  0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00,\r\n\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x04, 0xF4, 0xF4,\r\n  0xF4, 0xF4, 0x04, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00,\r\n\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x02, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x02,\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x00, 0x02, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,\r\n  0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r\n  0x00, 0xFE, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x05, 0x05,\r\n  0x05, 0x05, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00,\r\n\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x27, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,\r\n  0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,\r\n  0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x27, 0x20, 0x27, 0x28, 0x28, 0x28, 0x28, 0x28,\r\n  0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,\r\n  0x28, 0x28, 0x28, 0x28, 0x27, 0x20, 0x27, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,\r\n  0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,\r\n  0x28, 0xC7, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x08, 0xC8, 0x28,\r\n  0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x27, 0x20, 0x1F, 0x00\r\n};\r\n\r\n// Interrupt handlers\r\nISR(PCINT0_vect) { // PB0 pin button interrupt\r\n  if (clickLock == 0) {\r\n    if (commandDir > 0) commandDir--; else commandDir = 3;\r\n    clickLock = 1;\r\n    clickBase = millis();\r\n  }\r\n}\r\n\r\nvoid playerIncPacman() { // PB2 pin button interrupt\r\n  if (clickLock == 0) {\r\n    if (commandDir < 3) commandDir++; else commandDir = 0;\r\n    clickLock = 1;\r\n    clickBase = millis();\r\n  }\r\n}\r\n\r\nvoid displayTitle(void) {\r\n  int incr = 0;\r\n  for (int lxn = 3; lxn < 6; lxn++) {\r\n    ssd1306_setpos(84, lxn);\r\n    ssd1306_send_data_start();\r\n    for (int lxn2 = 0; lxn2 < 34; lxn2++) {\r\n      ssd1306_send_byte(pgm_read_byte(&openBmp[incr]));\r\n      incr++;\r\n      if ( (lxn == 3 || lxn == 5) && lxn2 > 21) lxn2 = 35;\r\n    }\r\n    ssd1306_send_data_stop();\r\n  }\r\n}\r\n\r\n// Arduino stuff - setup\r\nvoid setup() {\r\n  DDRB = 0b00000010;    // set PB1 as output (for the speaker)\r\n  PCMSK = 0b00000001; // pin change mask: listen to portb bit 1\r\n  GIMSK |= 0b00100000;  // enable PCINT interrupt\r\n  sei();          // enable all interrupts\r\n}\r\n\r\nvoid drawBar(byte aColumn, byte aRow, byte aLen) {\r\n  ssd1306_setpos(aColumn, aRow);\r\n  for (int incr = 0; incr < aLen; incr++) {\r\n    ssd1306_send_data_start();\r\n    ssd1306_send_byte(B00111000);\r\n    ssd1306_send_data_stop();\r\n  }\r\n}\r\n\r\n// Arduino stuff - loop\r\nvoid loop() {\r\n  ssd1306_init();\r\n  ssd1306_fillscreen(0x00);\r\n\r\n  ssd1306_char_f6x8(4, 2, \"P A C-M A N\");\r\n  ssd1306_char_f6x8(0, 4, \"andy jackson\");\r\n\r\n  drawBar(0, 1, 76);\r\n  drawBar(0, 3, 76);\r\n\r\n  displayTitle();\r\n\r\n  ssd1306_char_f6x8(0, 6, \"inspired by\");\r\n  ssd1306_char_f6x8(0, 7, \"webboggles.com\");\r\n  delay(1200);\r\n\r\n  long startT = millis();\r\n  long nowT = 0;\r\n  boolean sChange = 0;\r\n\r\n  while (digitalRead(0) == HIGH) {\r\n    nowT = millis();\r\n    if (nowT - startT > 2000) {\r\n      sChange = 1;\r\n      if (digitalRead(2) == HIGH) {\r\n        EEPROM.write(0, 0);\r\n        EEPROM.write(1, 0);\r\n        ssd1306_char_f6x8(8, 0, \"-HIGH SCORE RESET-\");\r\n      } else if (mute == 0) {\r\n        mute = 1;\r\n        ssd1306_char_f6x8(32, 0, \"-- MUTE --\");\r\n      } else {\r\n        mute = 0;\r\n        ssd1306_char_f6x8(31, 0, \"- SOUND ON -\");\r\n      }\r\n      break;\r\n    }\r\n    if (sChange == 1) break;\r\n  }\r\n  while (digitalRead(0) == HIGH);\r\n\r\n  if (sChange == 0) {\r\n    delay(1000);\r\n\r\n    ssd1306_init();\r\n    ssd1306_fillscreen(0x00);\r\n    \r\n    playPacman();\r\n\r\n    topScore = EEPROM.read(0);\r\n    topScore = topScore << 8;\r\n    topScore = topScore |  EEPROM.read(1);\r\n\r\n    newHigh = 0;\r\n    if (score > topScore) {\r\n      topScore = score;\r\n      EEPROM.write(1, score & 0xFF);\r\n      EEPROM.write(0, (score >> 8) & 0xFF);\r\n      newHigh = 1;\r\n    }\r\n\r\n    ssd1306_fillscreen(0x00);\r\n    drawBar(11, 1, 96);\r\n    drawBar(11, 3, 96);\r\n    ssd1306_char_f6x8(11, 2, \"G A M E  O V E R\");\r\n    showScore();\r\n    if (!newHigh) {\r\n      ssd1306_char_f6x8(21, 7, \"HIGH SCORE:\");\r\n      doNumber(88, 7, topScore);\r\n    }\r\n    delay(1500);\r\n    if (newHigh) {\r\n      ssd1306_fillscreen(0x00);\r\n      drawBar(11, 1, 96);\r\n      drawBar(11, 3, 96);\r\n      ssd1306_char_f6x8(10, 2, \" NEW HIGH SCORE \");\r\n      doNumber(50, 5, topScore);\r\n      for (int i = 700; i > 200; i = i - 50) {\r\n        beep(30, i);\r\n      }\r\n      delay(1500);\r\n    }\r\n  }\r\n  system_sleep();\r\n}\r\n\r\nvoid showScore(void) {\r\n  ssd1306_char_f6x8(37, 5, \"SCORE:\");\r\n  doNumber(75, 5, score);\r\n}\r\n\r\n// Handle what happens at the end of a level\r\nvoid levelUp() {\r\n  initScreen();\r\n  initLevel();\r\n  level++;\r\n  if ((level == 3) || (level == 5)) lives++;\r\n  if (maxGhosts < 3) maxGhosts++;\r\n  if (releaseDelay > GHOST_DELAY_MINIMUM) releaseDelay -= GHOST_DELAY_REDUCTION;\r\n  ssd1306_fillscreen(0x00);\r\n\r\n  ssd1306_char_f6x8(37, 1, \"LEVEL:\");\r\n  doNumber(75, 1, level);\r\n  drawBar(35, 3, 65);\r\n  showScore();\r\n\r\n  delay(2500);\r\n  ssd1306_fillscreen(0x00);\r\n  displayScreen();\r\n}\r\n\r\n\r\nvoid doNumber (int x, int y, int value) {\r\n  char temp[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\r\n  itoa(value, temp, 10);\r\n  ssd1306_char_f6x8(x, y, temp);\r\n}\r\n\r\nvoid ssd1306_init(void) {\r\n  DDRB |= (1 << SSD1306_SDA); // Set port as output\r\n  DDRB |= (1 << SSD1306_SCL); // Set port as output\r\n\r\n  ssd1306_send_command(0xAE); // display off\r\n  ssd1306_send_command(0x00); // Set Memory Addressing Mode\r\n  ssd1306_send_command(0x10); // 00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid\r\n  ssd1306_send_command(0x40); // Set Page Start Address for Page Addressing Mode,0-7\r\n  ssd1306_send_command(0x81); // Set COM Output Scan Direction\r\n  ssd1306_send_command(0xCF); // ---set low rowumn address\r\n  ssd1306_send_command(0xA1); // ---set high rowumn address\r\n  ssd1306_send_command(0xC8); // --set start line address\r\n  ssd1306_send_command(0xA6); // --set contrast control register\r\n  ssd1306_send_command(0xA8);\r\n  ssd1306_send_command(0x3F); // --set segment re-map 0 to 127\r\n  ssd1306_send_command(0xD3); // --set normal display\r\n  ssd1306_send_command(0x00); // --set multiplex ratio(1 to 64)\r\n  ssd1306_send_command(0xD5); //\r\n  ssd1306_send_command(0x80); // 0xa4,Output follows RAM content;0xa5,Output ignores RAM content\r\n  ssd1306_send_command(0xD9); // -set display offset\r\n  ssd1306_send_command(0xF1); // -not offset\r\n  ssd1306_send_command(0xDA); // --set display clock divide ratio/oscillator frequency\r\n  ssd1306_send_command(0x12); // --set divide ratio\r\n  ssd1306_send_command(0xDB); // --set pre-charge period\r\n  ssd1306_send_command(0x40); //\r\n  ssd1306_send_command(0x20); // --set com pins hardware configuration\r\n  ssd1306_send_command(0x02);\r\n  ssd1306_send_command(0x8D); // --set vcomh\r\n  ssd1306_send_command(0x14); // 0x20,0.77xVcc\r\n  ssd1306_send_command(0xA4); // --set DC-DC enable\r\n  ssd1306_send_command(0xA6); //\r\n  ssd1306_send_command(0xAF); // --turn on oled panel\r\n}\r\n\r\nvoid ssd1306_xfer_start(void) {\r\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\r\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\r\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\r\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\r\n}\r\n\r\nvoid ssd1306_xfer_stop(void) {\r\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\r\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\r\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\r\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\r\n}\r\n\r\nvoid ssd1306_send_byte(uint8_t byte) {\r\n  uint8_t i;\r\n  for (i = 0; i < 8; i++)\r\n  {\r\n    if ((byte << i) & 0x80)\r\n      DIGITAL_WRITE_HIGH(SSD1306_SDA);\r\n    else\r\n      DIGITAL_WRITE_LOW(SSD1306_SDA);\r\n\r\n    DIGITAL_WRITE_HIGH(SSD1306_SCL);\r\n    DIGITAL_WRITE_LOW(SSD1306_SCL);\r\n  }\r\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);\r\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);\r\n  DIGITAL_WRITE_LOW(SSD1306_SCL);\r\n}\r\n\r\nvoid ssd1306_send_command(uint8_t command) {\r\n  ssd1306_xfer_start();\r\n  ssd1306_send_byte(SSD1306_SA);  // Slave address, SA0=0\r\n  ssd1306_send_byte(0x00);  // write command\r\n  ssd1306_send_byte(command);\r\n  ssd1306_xfer_stop();\r\n}\r\n\r\nvoid ssd1306_send_data_start(void) {\r\n  ssd1306_xfer_start();\r\n  ssd1306_send_byte(SSD1306_SA);\r\n  ssd1306_send_byte(0x40);  //write data\r\n}\r\n\r\nvoid ssd1306_send_data_stop(void) {\r\n  ssd1306_xfer_stop();\r\n}\r\n\r\nvoid ssd1306_setpos(uint8_t x, uint8_t y)\r\n{\r\n  if (y > 7) return;\r\n  ssd1306_xfer_start();\r\n  ssd1306_send_byte(SSD1306_SA);  //Slave address,SA0=0\r\n  ssd1306_send_byte(0x00);  //write command\r\n\r\n  ssd1306_send_byte(0xb0 + y);\r\n  ssd1306_send_byte(((x & 0xf0) >> 4) | 0x10); // |0x10\r\n  ssd1306_send_byte((x & 0x0f) | 0x01); // |0x01\r\n\r\n  ssd1306_xfer_stop();\r\n}\r\n\r\nvoid ssd1306_fillscreen(uint8_t fill_Data) {\r\n  uint8_t m, n;\r\n  for (m = 0; m < 8; m++)\r\n  {\r\n    ssd1306_send_command(0xb0 + m); //page0-page1\r\n    ssd1306_send_command(0x00);   //low rowumn start address\r\n    ssd1306_send_command(0x10);   //high rowumn start address\r\n    ssd1306_send_data_start();\r\n    for (n = 0; n < 128; n++)\r\n    {\r\n      ssd1306_send_byte(fill_Data);\r\n    }\r\n    ssd1306_send_data_stop();\r\n  }\r\n}\r\n\r\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]) {\r\n  uint8_t c, i, j = 0;\r\n  while (ch[j] != '\\0')\r\n  {\r\n    c = ch[j] - 32;\r\n    if (c > 0) c = c - 12;\r\n    if (c > 15) c = c - 6;\r\n    if (c > 40) c = c - 9;\r\n    if (x > 126)\r\n    {\r\n      x = 0;\r\n      y++;\r\n    }\r\n    ssd1306_setpos(x, y);\r\n    ssd1306_send_data_start();\r\n    for (i = 0; i < 6; i++)\r\n    {\r\n      ssd1306_send_byte(pgm_read_byte(&ssd1306xled_font6x8[c * 6 + i]));\r\n    }\r\n    ssd1306_send_data_stop();\r\n    x += 6;\r\n    j++;\r\n  }\r\n}\r\n\r\nvoid system_sleep(void) {\r\n  ssd1306_fillscreen(0x00);\r\n  ssd1306_send_command(0xAE);\r\n  cbi(ADCSRA, ADEN);                   // switch analog to digital converter off\r\n  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here\r\n  sleep_enable();\r\n  sleep_mode();                        // system actually sleeps here\r\n  sleep_disable();                     // system continues execution here when watchdog timed out\r\n  sbi(ADCSRA, ADEN);                   // switch analog to digital converter on\r\n  ssd1306_send_command(0xAF);\r\n}\r\n\r\nvoid beep(int bCount, int bDelay) {\r\n  if (mute) return;\r\n  for (int i = 0; i <= bCount; i++) {\r\n    digitalWrite(1, HIGH);\r\n    for (int i2 = 0; i2 < bDelay; i2++) {\r\n      __asm__(\"nop\\n\\t\"); // 62.5ns delay @ 16MHz\r\n    }\r\n    digitalWrite(1, LOW);\r\n    for (int i2 = 0; i2 < bDelay; i2++) {\r\n      __asm__(\"nop\\n\\t\"); // 62.5ns delay @ 16Mhz\r\n    }\r\n  }\r\n}\r\n\r\nbyte drawPacman(byte c, byte r) {\r\n  byte out = 0;\r\n  if ( (r >= locations[3][0]) && (r < locations[3][0] + 8) ) { // draw the pacMan if any of his body is on this column\r\n    if (c == locations[3][1] / 8) {\r\n      if (mouth == 1) {\r\n        out = (pgm_read_byte(&pacOpen[directions[3]][r - locations[3][0]]) << locations[3][1] % 8);\r\n      } else {\r\n        out = (pgm_read_byte(&pacClosed[r - locations[3][0]]) << locations[3][1] % 8);\r\n      }\r\n    } else if (c == locations[3][1] / 8 + 1) {\r\n      if (mouth == 1) {\r\n        out = (pgm_read_byte(&pacOpen[directions[3]][r - locations[3][0]]) >> (8 - locations[3][1] % 8) );\r\n      } else {\r\n        out = (pgm_read_byte(&pacClosed[r - locations[3][0]]) >> (8 - locations[3][1] % 8) );\r\n      }\r\n    }\r\n  }\r\n  return out;\r\n}\r\n\r\nvoid displayScreen(void) {\r\n  int incr = 0;\r\n  int pacDir = directions[3];\r\n  byte out;\r\n\r\n  for (byte c = 0; c < 8; c++) {\r\n    ssd1306_setpos(0, c);\r\n    ssd1306_send_data_start();\r\n    for (byte r = 0; r < 128; r++) {\r\n      out = (pgm_read_byte(&gameScreen[incr]));\r\n\r\n      out |= drawPacman(c, r);\r\n\r\n      // Draw the bits in the far left column - lives and the little direction arrow\r\n      if (r < 7) {\r\n        if (c == 1) out |= (pgm_read_byte(&arrows[commandDir][r]));\r\n        for (byte lxn = 3; lxn < 7; lxn++) {\r\n          if (c == lxn && lives > 6 - lxn) out |= (pgm_read_byte(&PAClives[r]));\r\n        }\r\n      }\r\n\r\n      for (byte lxn = 0; lxn < 3; lxn++) {\r\n        if ( (r >= locations[lxn][0]) && (r < locations[lxn][0] + 8) ) { // draw the ghost if any of his body is on this column\r\n          if (c == locations[lxn][1] / 8) {\r\n            out |= (pgm_read_byte(&ghost[flipFlop][r - locations[lxn][0]]) << locations[lxn][1] % 8);\r\n          } else if (c == locations[lxn][1] / 8 + 1) {\r\n            out |= (pgm_read_byte(&ghost[flipFlop][r - locations[lxn][0]]) >> (8 - locations[lxn][1] % 8) );\r\n          }\r\n        }\r\n      }\r\n\r\n      if (c > 0 && c < 7) {\r\n        for (byte lxn = pgm_read_byte(&readRow[c - 1][0]); lxn < pgm_read_byte(&readRow[c - 1][1]); lxn++) {\r\n          if (pillsActive[lxn]) { // this pill is active\r\n            if (r == pgm_read_byte(&pillLocations[lxn][0])) { // draw the pills if they appear here\r\n              // check if pac-man has eaten a pill\r\n              if (pgm_read_byte(&pillLocations[lxn][0]) > locations[3][0] && pgm_read_byte(&pillLocations[lxn][0]) < locations[3][0] + 8 && pgm_read_byte(&pillLocations[lxn][1]) > locations[3][1] && pgm_read_byte(&pillLocations[lxn][1]) < locations[3][1] + 8) {\r\n                pillsActive[lxn] = 0;\r\n                pillsEaten++;\r\n                score += level;\r\n                break;\r\n              }\r\n              if (c == pgm_read_byte(&pillLocations[lxn][1]) / 8) {\r\n                out |= ((B00000001) << pgm_read_byte(&pillLocations[lxn][1]) % 8);\r\n              } else if (c == pgm_read_byte(&pillLocations[lxn][1]) / 8 + 1) {\r\n                out |= ((B00000001) >> (8 - pgm_read_byte(&pillLocations[lxn][1]) % 8) );\r\n              }\r\n            }\r\n          }\r\n        }\r\n      }\r\n      for (byte lxn = 0; lxn < 2; lxn++) {\r\n        if (bigPillsActive[lxn] == 1 && c == 6 && (r == pgm_read_byte(&bigPillLocations[lxn]) || r == (pgm_read_byte(&bigPillLocations[lxn]) + 1) )) {\r\n          out |= B11100000;\r\n        }\r\n      }\r\n\r\n      if (locations[3][1] == 51) {\r\n        if ((locations[3][0] < 14 && bigPillsActive[0] == 1) || (locations[3][0] > 111 && bigPillsActive[1] == 1)) {\r\n          if (locations[3][0] < 14) bigPillsActive[0] = 0; else bigPillsActive[1] = 0;\r\n          powerUp = 1;\r\n          flipFlop = 1;\r\n          powerCounter = 0;\r\n        }\r\n      }\r\n\r\n      ssd1306_send_byte(out);\r\n      incr++;\r\n    } // end for 128\r\n\r\n    ssd1306_send_data_stop();\r\n  }\r\n}\r\n\r\nint checkCollision(byte xpos, byte ypos) {\r\n  int incr = 0;\r\n  int returnValue = 0;\r\n\r\n  for (byte c = 0; c < 2; c++) { // for each of the two lines that the item might be on\r\n    incr = (128 * (ypos / 8 + c)) + xpos;\r\n    for (byte r = 0; r < 8; r++) { // for each of the eight bytes in the sprite\r\n      if (c == 0) {\r\n        if ((pgm_read_byte(&gameScreen[incr]) & (0xFF << ypos % 8) ) != 0) returnValue = 1;\r\n      } else {\r\n        if ((pgm_read_byte(&gameScreen[incr]) & (0xFF >> (8 - ypos % 8) ) ) != 0) returnValue = 1;\r\n      }\r\n      incr++;\r\n    }\r\n  }\r\n  return returnValue;\r\n}\r\n\r\nvoid moveGhosts(void) {\r\n  int travelDirection;  // which way's the ghost going?\r\n  byte travelParam;     // zero for travelling in x, one for y\r\n  int searchDirection;  // +1 to search up, -1 to search down for side exits\r\n  byte paramSelection;  // zero for xPosition, one for yPosition\r\n  byte switchDirection; // which direction to switch to if there's a switch\r\n\r\n  ghostCounter++;\r\n\r\n  // Pop the next ghost out, if it's time\r\n  if (ghostCounter >= releaseDelay) {\r\n    ghostCounter = 0;\r\n    for (byte lxn = 0; lxn < maxGhosts; lxn++) {\r\n      if (ghostsActive[lxn] == 0) {\r\n        locations[lxn][0] = GHOST_LAUNCH_X;\r\n        locations[lxn][1] = GHOST_LAUNCH_Y;\r\n        ghostsActive[lxn] = 1;\r\n        break;\r\n      }\r\n    }\r\n  }\r\n\r\n  for (byte lxn = 0; lxn < 3; lxn++) {\r\n    if (ghostsActive[lxn] == 1) {\r\n      char clash = 0;\r\n      switch (directions[lxn]) {\r\n        case (DIR_RIGHT):\r\n          travelDirection = 1;\r\n          travelParam = 0;\r\n          searchDirection = -1;\r\n          paramSelection = 1;\r\n          switchDirection = DIR_UP;\r\n          break;\r\n\r\n        case (DIR_LEFT):\r\n          travelDirection = -1;\r\n          travelParam = 0;\r\n          searchDirection = 1;\r\n          paramSelection = 1;\r\n          switchDirection = DIR_DOWN;\r\n          break;\r\n\r\n        case (DIR_UP):\r\n          travelDirection = -1;\r\n          travelParam = 1;\r\n          searchDirection = -1;\r\n          paramSelection = 0;\r\n          switchDirection = DIR_LEFT;\r\n          break;\r\n\r\n        case (DIR_DOWN):\r\n          travelDirection = 1;\r\n          travelParam = 1;\r\n          searchDirection = 1;\r\n          paramSelection = 0;\r\n          switchDirection = DIR_RIGHT;\r\n          break;\r\n      }\r\n\r\n      // Slow the ghosts down if powerup mode is active\r\n      gCount++;\r\n      if (gCount >= 5) {\r\n        if(powerUp) travelDirection = 0; \r\n        if (powerCounter > POWER_LENGTH - 50) flipFlop = !flipFlop;\r\n        gCount = 0;\r\n      }\r\n    \r\n      locations[lxn][travelParam] += travelDirection;\r\n      // Move the ghosts along according to which way they are heading - if there's a clash, then backtrack\r\n      if (checkCollision(locations[lxn][0], locations[lxn][1]) == 1) {\r\n        locations[lxn][travelParam] -= travelDirection;\r\n        newDirection(lxn);\r\n      } else {\r\n        clash = 0;\r\n        for (byte lxn2 = 0; lxn2 < 3; lxn2++) {\r\n          locations[lxn][paramSelection] += searchDirection;\r\n          if (checkCollision(locations[lxn][0], locations[lxn][1]) == 1) clash = 1;\r\n        }\r\n        if (clash == 0 && random(100) > BRANCH_PROBABILITY) directions[lxn] = switchDirection;\r\n        locations[lxn][paramSelection] -= (searchDirection * 3);\r\n      }\r\n    }\r\n  }\r\n}\r\n\r\nvoid newDirection(byte ghostNo) {\r\n  directions[ghostNo] = random(4);\r\n}\r\n\r\nvoid eatenGhost(void) {\r\n  for (int i = 700; i > 200; i = i - 50) {\r\n    beep(30, i);\r\n  }\r\n}\r\n\r\nbyte hitGhosts(void) {\r\n  byte returnCode = 0;\r\n\r\n  for (int lxn = 0; lxn < 3 ; lxn++) {\r\n    if ((locations[lxn][0] > locations[3][0] - 8) && (locations[lxn][0] < locations[3][0] + 8) && (locations[lxn][1] > locations[3][1] - 8) && (locations[lxn][1] < locations[3][1] + 8)) {\r\n      if (powerUp == 1) {\r\n        locations[lxn][0] = startPosX[lxn];\r\n        locations[lxn][1] = startPosY[lxn];\r\n        ghostsActive[lxn] = 0;\r\n        eatenGhost();\r\n        score += 10;\r\n        ghostCounter = 0;\r\n      } else returnCode = 1;\r\n    }\r\n  }\r\n  return returnCode;\r\n}\r\n\r\nvoid pacDie(void) {\r\n  int i;\r\n  directions[3] = DIR_UP;\r\n  mouth = 1;\r\n  displayScreen();\r\n  for (i = 0; i < 500; i = i + 50) {\r\n    beep(50, i);\r\n  }\r\n  mouth = 0;\r\n  displayScreen();\r\n  for (i = 500; i < 1000; i = i + 50) {\r\n    beep(50, i);\r\n  }\r\n  delay(1200);\r\n  stopAnimate = 1;\r\n}\r\n\r\nvoid movePacman(void) {\r\n  pCount++;\r\n  if (pCount >= 3) {\r\n    if (mouth == 0) {\r\n      mouth = 1;\r\n      beep(20, 400 + (powerUp * 100));\r\n    } else {\r\n      mouth = 0;\r\n      beep(20, 420);\r\n    }\r\n    pCount = 0;\r\n  }\r\n\r\n  if (powerUp == 1) {\r\n    powerCounter++;\r\n    if (powerCounter >= POWER_LENGTH) {\r\n      powerUp = 0;\r\n      powerCounter = 0;\r\n      flipFlop = 0;\r\n      gCount = 0;\r\n      pCount = 0;\r\n    }\r\n  }\r\n\r\n  oldDir = directions[3];\r\n  directions[3] = commandDir;\r\n\r\n  switch (directions[3]) {\r\n    case (DIR_RIGHT):\r\n      for (int lxn = 0; lxn < 3; lxn++) {\r\n        locations[3][0]++;\r\n        if (checkCollision(locations[3][0], locations[3][1]) == 1) {\r\n          directions[3] = oldDir;\r\n        }\r\n      }\r\n      locations[3][0] -= 3;\r\n      break;\r\n\r\n    case (DIR_LEFT):\r\n      for (int lxn = 0; lxn < 3; lxn++) {\r\n        locations[3][0]--;\r\n        if (checkCollision(locations[3][0], locations[3][1]) == 1) {\r\n          directions[3] = oldDir;\r\n        }\r\n      }\r\n      locations[3][0] += 3;\r\n      break;\r\n\r\n    case (DIR_UP):\r\n      for (int lxn = 0; lxn < 3; lxn++) {\r\n        locations[3][1]--;\r\n        if (checkCollision(locations[3][0], locations[3][1]) == 1) {\r\n          directions[3] = oldDir;\r\n        }\r\n      }\r\n      locations[3][1] += 3;\r\n      break;\r\n\r\n    case (DIR_DOWN):\r\n      for (int lxn = 0; lxn < 3; lxn++) {\r\n        locations[3][1]++;\r\n        if (checkCollision(locations[3][0], locations[3][1]) == 1) {\r\n          directions[3] = oldDir;\r\n        }\r\n      }\r\n      locations[3][1] -= 3;\r\n      break;\r\n  }\r\n\r\n  switch (directions[3]) {\r\n    case (DIR_RIGHT):\r\n      locations[3][0] += 1;\r\n      if (checkCollision(locations[3][0], locations[3][1]) == 1) locations[3][0] -= 1;\r\n      break;\r\n\r\n    case (DIR_LEFT):\r\n      locations[3][0] -= 1;\r\n      if (checkCollision(locations[3][0], locations[3][1]) == 1) locations[3][0] += 1;\r\n      break;\r\n\r\n    case (DIR_UP):\r\n      locations[3][1] -= 1;\r\n      if (checkCollision(locations[3][0], locations[3][1]) == 1) locations[3][1] += 1;\r\n      break;\r\n\r\n    case (DIR_DOWN):\r\n      locations[3][1] += 1;\r\n      if (checkCollision(locations[3][0], locations[3][1]) == 1) locations[3][1] -= 1;\r\n      break;\r\n  }\r\n}\r\n\r\nvoid initLevel(void) {\r\n  clickLock = 0;\r\n  pillsEaten = 0;\r\n  stopAnimate = 0;\r\n\r\n  for (byte lxn = 0; lxn < NO_PILLS; lxn++) pillsActive[lxn] = 1;\r\n  bigPillsActive[0] = 1;\r\n  bigPillsActive[1] = 1;\r\n}\r\n\r\nvoid initScreen(void) {\r\n  powerUp = 0;\r\n  flipFlop = 0;\r\n  powerCounter = 0;\r\n  ghostsActive[0] = 0;\r\n  ghostsActive[1] = 0;\r\n  ghostsActive[2] = 0;\r\n  ghostCounter = 0;\r\n\r\n  // Set up the initial directions of the ghosts and pacman\r\n  for (byte lxn = 0; lxn < 4; lxn++) {\r\n    locations[lxn][0] = startPosX[lxn];\r\n    locations[lxn][1] = startPosY[lxn];\r\n    directions[lxn] = startDirections[lxn];\r\n  }\r\n\r\n  // Initially set pacman off in the direction he is facing\r\n  commandDir = startDirections[3];\r\n}\r\n\r\n/* ------------------------\r\n    Pacman main game code\r\n*/\r\nvoid playPacman() {\r\n  score = 0;\r\n  lives = START_LIVES;\r\n  level = 1;\r\n  gCount = 0;\r\n  pCount = 0;\r\n  releaseDelay = INITIAL_GHOST_DELAY;\r\n  maxGhosts = INITIAL_GHOSTS;\r\n\r\n  attachInterrupt(0, playerIncPacman, CHANGE);\r\n\r\n  initLevel();\r\n  initScreen();\r\n\r\n  while (lives >= 0) {\r\n\r\n    if (pillsEaten >= NO_PILLS) levelUp();\r\n\r\n    moveGhosts();\r\n    movePacman();\r\n\r\n    // Check for ghosrs or pacman going thru the tunnel teleport thing\r\n    for (byte lxn2 = 0; lxn2 < 4; lxn2 ++) {\r\n      if (locations[lxn2][1] <= 0) {\r\n        locations[lxn2][1] = 56;\r\n        locations[lxn2][0] = 100;\r\n      } else if (locations[lxn2][1] >= 56) {\r\n        locations[lxn2][1] = 0;\r\n        locations[lxn2][0] = 21;\r\n      }\r\n    }\r\n\r\n    if (hitGhosts() != 0) {\r\n      pacDie();\r\n      lives--;\r\n      initScreen();\r\n    }\r\n    if (clickLock == 1 && millis() > clickBase + CLICKDELAY && digitalRead(2) == 0 && digitalRead(0) == 0) clickLock = 0; // normal debounce\r\n\r\n    displayScreen();\r\n  }\r\n}\r\n"
  },
  {
    "path": "Pacman_Attiny_Arcade/font6x8AJ3.h",
    "content": "/*\r\n * SSD1306xLED - Drivers for SSD1306 controlled dot matrix OLED/PLED 128x64 displays\r\n *\r\n * @file: font6x8.h\r\n * @created: 2014-08-12\r\n * @author: Neven Boyanov\r\n * \r\n * Hacked by andy jackson to allow two games (originally by webboggles.com) to \r\n * fit onto an ATTiny85 at the same time - hence several characters are missing\r\n * and a couple have been moved to limit the amount of software remapping required\r\n * to map ASCII values onto locations in this array.\r\n *\r\n * Source code available at: https://bitbucket.org/tinusaur/ssd1306xled\r\n *\r\n */\r\n\r\n// ----------------------------------------------------------------------------\r\n\r\n#include <avr/pgmspace.h>\r\n\r\n// ----------------------------------------------------------------------------\r\n\r\n/* Standard ASCII 6x8 font */\r\nstatic const uint8_t ssd1306xled_font6x8 [] PROGMEM = {\r\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sp\r\n/*\r\n  0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // !\r\n  0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // \"\r\n  0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // #\r\n  0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $\r\n  0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // %\r\n  0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // &\r\n  0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // '\r\n  0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // (\r\n  0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // )\r\n  0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // *\r\n  0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // +\r\n  0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // ,\r\n  */\r\n  0x00, 0x00, 0x08, 0x08, 0x08, 0x00, // -\r\n  0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // .\r\n  0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // /\r\n  0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0\r\n  0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, // 1\r\n  0x00, 0x42, 0x61, 0x51, 0x49, 0x46, // 2\r\n  0x00, 0x21, 0x41, 0x45, 0x4B, 0x31, // 3\r\n  0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, // 4\r\n  0x00, 0x27, 0x45, 0x45, 0x45, 0x39, // 5\r\n  0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6\r\n  0x00, 0x01, 0x71, 0x09, 0x05, 0x03, // 7\r\n  0x00, 0x36, 0x49, 0x49, 0x49, 0x36, // 8\r\n  0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, // 9\r\n  0x00, 0x00, 0x36, 0x36, 0x00, 0x00, // :\r\n/*\r\n  0x00, 0x00, 0x56, 0x36, 0x00, 0x00, // ;\r\n  0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // <\r\n  0x00, 0x14, 0x14, 0x14, 0x14, 0x14, // =\r\n  0x00, 0x00, 0x41, 0x22, 0x14, 0x08, // >\r\n  0x00, 0x02, 0x01, 0x51, 0x09, 0x06, // ?\r\n  0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, // @\r\n */\r\n  0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A\r\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, // B\r\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, // C\r\n  0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, // D\r\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, // E\r\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, // F\r\n  0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, // G\r\n  0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, // H\r\n  0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, // I\r\n  0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, // J\r\n  0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, // K\r\n  0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, // L\r\n  0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M\r\n  0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, // N\r\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, // O\r\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, // P\r\n  0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q\r\n  0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, // R\r\n  0x00, 0x46, 0x49, 0x49, 0x49, 0x31, // S\r\n  0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, // T\r\n  0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, // U\r\n  0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, // V\r\n  0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, // W\r\n  /*\r\n  0x00, 0x63, 0x14, 0x08, 0x14, 0x63, // X\r\n  0x00, 0x07, 0x08, 0x70, 0x08, 0x07, // Y\r\n  0x00, 0x61, 0x51, 0x49, 0x45, 0x43, // Z\r\n  0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, // [\r\n  0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55, // 55\r\n  0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, // ]\r\n  0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^\r\n  0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _\r\n  0x00, 0x00, 0x01, 0x02, 0x04, 0x00, // '\r\n*/\r\n  0x00, 0x20, 0x54, 0x54, 0x54, 0x78, // a\r\n  0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, // b\r\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x20, // c\r\n  0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, // d\r\n  0x00, 0x38, 0x54, 0x54, 0x54, 0x18, // e\r\n  0x00, 0x08, 0x7E, 0x09, 0x01, 0x02, // f\r\n  0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g\r\n  0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h\r\n  0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, // i\r\n  0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, // j\r\n  0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, // k\r\n  0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, // l\r\n  0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, // m\r\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, // n\r\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x38, // o\r\n  0x00, 0xFC, 0x24, 0x24, 0x24, 0x18, // p\r\n  0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, // q\r\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, // r\r\n  0x00, 0x48, 0x54, 0x54, 0x54, 0x20, // s\r\n  0x00, 0x04, 0x3F, 0x44, 0x40, 0x20, // t\r\n  0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, // u\r\n  0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, // v\r\n  0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w\r\n  0x00, 0x44, 0x28, 0x10, 0x28, 0x44, // x\r\n  0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C  // y\r\n};\r\n\r\n// ----------------------------------------------------------------------------\r\n\r\n"
  },
  {
    "path": "README.md",
    "content": "Games for the AttinyArcade (or hardware inspired by this system)\n================================================================\n\nBy Andy Jackson - Twitter: @andyhighnumber\n------------------------------------------\n\nThe games in this folder can mostly be played either on the AttinyArcade, or similar hardware (if the hardware is different, there will be a circuit diagram in the same folder as the game).\n\nInfo on programming the Attiny85 chip can be found online, here's an example: https://create.arduino.cc/projecthub/arjun/programming-attiny85-with-arduino-uno-afb829 - don't forget to burn the bootloader (it's a menu option under 'Tools' on the Arduino IDE) the first time you flash the chip and if you need to change between 8Mhz and 16Mhz clocks (all my games are 8Mhz, except Pacman which is 16Mhz).\n\nSee www.webboggles.com for details of the AttinyArcade hardware.\n\nThese games are based on the Attiny85 device running at 8Mhz on its internal clock, or 16Mhz for pac-man (don't forget to burn the bootloader when you first flash a new chip- the option to do this is in the \"Tools\" menu on the Arduino IDE).\n\nIn this folder:\n\nFor the standard Attiny Arcade Hardware, or enhanced functionality on custom hardware\n=====================================================================================\n- Pacman_Attiny_Arcade: PacMan clone for the original Attiny. This is the best of the lot in my opinion. Unlike the other games here, this needs to be flashed with a 16Mhz internal clock bootloader (all the others are 8MHz). Send me a message via twitter if this presents any problems.\n- SpaceAttackAttiny: Space Invaders clone for the original Attiny (also allows for modified version of hardware with fire button - see circuit diagram in folder)\n- Frogger_Attiny_Arcade: Frogger clone for the original Attiny (also allows modified version of hardware with jump button - same hardware config as SpaceAttack above - see schematic in folder)\n- MorseAttinyArcade: A morse code decoder (for practicing morse, if you so wish), which displays inputted code via a 5-line scrolling display. When combined with a PLL (or similar) tone detection circuit, this could easily decode off-air morse.\n\nFor the standard Attiny Arcade Hardware\n=======================================\n- WrenRollercoasterAttinyArcade: Inspired by the TinyWings iOS game - fly a wren along a landscape as far as you can! \n- Attiny Tetris: A Tetris clone, evolved from a game for the Arduino by Anthony Russell (https://github.com/AJRussell/Tiny-Tetris)\n- UFO_Stacker_Attiny: Two games in one sketch - UFO (from www.webboggles.com) and Stacker (from me).\n- UFO_Breakout_Arduino: Again - two games in one sketch, both from www.webboggles.com, UFO and Breakout\n- BatBonanzaAttinyArcade: A version of Pong for the standard AttinyHardware - not as playable because you really need analog control for this type of game - see below\n\nFor the MAKERbuino (https://www.makerbuino.com/)\n=======================================\n- PAK-MAN_MAKERbuino: Port of the PAC-MAN AttinyArcade game to the MAKERBUINO / GAMEBUINO platform \n- FROGGER_MAKERbuino: Port of the Frogger AttinyArcade game to the MAKERBUINO / GAMEBUINO platform \n\nFor custom hardware - see circuit schematics in the folders with the sketches\n=============================================================================\n- BatBonanzaAnalog: Pong clone based on custom hardware with analog controls (will work on the same hardware as Space Attack Anlog Version).\n- Space_Attack_Analog: Space Invaders clone (sort of) based on custom hardware with analog control (will work on the same hardware as Bat Bonanza Anlog Version).\n- BatBonanzaAnalogSinglePot: Pong clone based on custom hardware with single-pot analog control (will work on the same hardware as Space Attack Anlog Version).\n- Tetris_Multi_Button: A Tetris cline, as above but designed for multi-button pad (see circuit schematic in folder for details of the hardware)\n"
  },
  {
    "path": "SpaceAttackAttiny/SpaceAttackAttiny.ino",
    "content": "/* 2015 / 2016\n * SpaceAttack game by Andy Jackson - Twitter @andyhighnumber\n * Inspired by http://webboggles.com/ and includes some code from the #AttinyArcade games on that site\n * The code that does not fall under the licenses of sources listed below can be used non commercially with attribution.\n * \n * Press both left and right buttons to fire (works on #AttinyArcade which only has two buttons), or...\n * This code allows for three button inputs - the usual two on pins 5 and 7 (for left and right) and an additional switch on the reset pin\n * One side of the fire button should be wired to the reset pin (pin 1 - the only unused pin on the chip!) and the other side to  a voltage divider, \n * consisting of a 6.8k resistor to ground and a 1k resistor to vcc (battery +ve) - this allows the code to read a voltage on the input that \n * drops enough to be noticible when the button is pressed, but not enough to reset the chip!\n * \n * Also, from standby....\n *  Press and hold left button to turn sound on and off\n *  Press and hold left button with the right button held to reset high score\n * \n * If you have problems uploading this sketch, this is probably due to sketch size - you need to update ld.exe in arduino\\hardware\\tools\\avr\\avr\\bin\n * https://github.com/TCWORLD/ATTinyCore/tree/master/PCREL%20Patch%20for%20GCC\n *\n * This sketch is using the screen control and font functions written by Neven Boyanov for the http://tinusaur.wordpress.com/ project\n * Source code and font files available at: https://bitbucket.org/tinusaur/ssd1306xled\n * **Note that this highly size-optimised version requires modified library functions (which are in this source code file) \n * and a modified font header\n * \n * Sleep code is based on this blog post by Matthew Little:\n * http://www.re-innovation.co.uk/web12/index.php/en/blog-75/306-sleep-modes-on-attiny85\n*/\n#include <EEPROM.h>\n#include \"font6x8AJ.h\"\n#include <avr/sleep.h>\n#include <avr/interrupt.h> // needed for the additional interrupt\n\n#define DIGITAL_WRITE_HIGH(PORT) PORTB |= (1 << PORT)\n#define DIGITAL_WRITE_LOW(PORT) PORTB &= ~(1 << PORT)\n\n// Routines to set and clear bits (used in the sleep code)\n#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))\n#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))\n\n// Defines for OLED output\n#define SSD1306XLED_H\n#define SSD1306_SCL   PORTB4  // SCL, Pin 4 on SSD1306 Board - for webbogles board\n#define SSD1306_SDA   PORTB3  // SDA, Pin 3 on SSD1306 Board - for webbogles board\n#define SSD1306_SA    0x78  // Slave address\n\n// Function prototypes\nvoid resetAliens(void);\nvoid drawPlatform(void);\nvoid sendBlock(int);\nvoid playSpaceAttack(void);\nvoid beep(int,int);\nvoid levelUp(int);\nvoid drawFire(int x, int y);\nvoid doDrawLS(long, byte);\nvoid doDrawRS(long, byte);\nvoid clearAlienArea(int row, int lastActive);\nvoid doNumber (int x, int y, int value);\nvoid ssd1306_init(void);\nvoid ssd1306_xfer_start(void);\nvoid ssd1306_xfer_stop(void);\nvoid ssd1306_send_byte(uint8_t byte);\nvoid ssd1306_send_command(uint8_t command);\nvoid ssd1306_send_data_start(void);\nvoid ssd1306_send_data_stop(void);\nvoid ssd1306_setpos(uint8_t x, uint8_t y);\nvoid ssd1306_fillscreen(uint8_t fill_Data);\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]);\nvoid ssd1306_draw_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t bitmap[]);\n\nlong firecounter = 0; // Timer for managing fire\nlong aliencounter = 0; // Timer for alien movement\nint mothercounter = 0; // Timer for movement of the mothership\nint level = 1; // Game level - incremented every time you clear the screen\nint mothershipX = 0; // position of mothership\nint mothership = 0; // is mothership active?\nint mothershipWidth = 8; // mothership width in pixels\nint fireXidx, fireYidx; // mapping of player fire locaiton onto array of aliens\nint leftLimit; // furtherst left in x-axis pixels that the aliens are currently\nint positionNow = 0; // current position of the alien array (as steps from the left)\nboolean alienDirection = 1; // current direction of travel for alien swarm - 1 is right 0 is left\nint alienRow = 0; // which alien row are we considering\nint alienFire[5][3]; // max 5 lots of alien fire  - indices are active, xpos, ypos\nint playerFire[3]; // one lot of player fire - indices are active, xpos, ypos\nboolean row[4][10]; // on-off array of aliens\nint firstAlien = 0; // index of first live alien in the array\nint lastAlien = 8; // index of last live alien in the array\nint newFirst = firstAlien; // as above when it changes\nint newLast = lastAlien; // ...\nint aliensDead = 0; // how many aliens have been killed in total on this level?\nint lastActiveRow = 2; // what's the lowest row in which we will find live aliens?\nint deadOn1 = 0; // how many aliens are dead on row one (middle row)\nint deadOn2 = 0; // how many aliens are dead on row two (bottom row)\n\nboolean fire = 0;\nint topScoreB = 0;\nint player; //0 to 128-platformWidth  - this is the position of the player\nint platformWidth = 16; \nboolean stopAnimate = 0; // this is set to 1 when a collision is detected\nboolean mute = 0;\nboolean newHigh = 0;\nint score = 0; // score - this affects the difficulty of the game\nint top = 0;\n\n// Interrupt handlers\nISR(PCINT0_vect){ // PB0 pin button interrupt           \n   if (digitalRead(2)==1) fire = 1;\n}\n\nvoid playerIncSpaceAttack(){ // PB2 pin button interrupt\n  if (digitalRead(0)==1) fire = 1;\n}\n\n// Arduino stuff - setup\nvoid setup() {\n  DDRB = 0b00000010;    // set PB1 as output (for the speaker)\n  PCMSK = 0b00000001; // pin change mask: listen to portb bit 1\n  GIMSK |= 0b00100000;  // enable PCINT interrupt \n  sei();          // enable all interrupts\n}\n\n// Arduino stuff - loop\nvoid loop() { \n  ssd1306_init();\n  ssd1306_fillscreen(0x00);\n  \n  // The lower case character set is seriously compromised because I've had to truncate the ASCII table\n  // to release space for executable code - hence lower case y and w are remapped to h and / respectively.\n  // There is no z in the table (or h!) as these aren't used anywhere in the text here and most of the \n  // symbols are also missing for the same reason (see my hacked version of font6x8.h - font6x8AJ.h for more detail)\n  ssd1306_char_f6x8(0, 1, \"S P A C E\");\n  ssd1306_char_f6x8(4, 2, \"A T T A C K\");\n  ssd1306_char_f6x8(0, 4, \"andh jackson\"); // see comments above !\n\n  ssd1306_setpos(85,1);\n  ssd1306_send_data_start();\n  sendBlock(1);\n  sendBlock(0);  \n  sendBlock(1);\n  ssd1306_send_data_stop();\n  ssd1306_setpos(85,2);\n  ssd1306_send_data_start();\n  sendBlock(0);\n  sendBlock(2);\n  sendBlock(0);\n  ssd1306_send_data_stop();\n  ssd1306_setpos(85,3);\n  ssd1306_send_data_start();\n  sendBlock(0);\n  sendBlock(0);  \n  sendBlock(1);\n  sendBlock(0);  \n  sendBlock(1);\n  ssd1306_send_data_stop();\n  player = 96;\n  drawPlatform();\n\n  long startT = millis();\n  long nowT =0;\n  boolean sChange = 0;\n  while(digitalRead(0) == HIGH) {\n    nowT = millis();\n    if (nowT - startT > 2000) {\n      sChange = 1;     \n      if (digitalRead(2) == HIGH) {\n        EEPROM.write(0,0);\n        EEPROM.write(1,0);\n        ssd1306_char_f6x8(8, 0, \"-HIGH SCORE RESET-\");  \n      } else if (mute == 0) { mute = 1; ssd1306_char_f6x8(32, 0, \"-- MUTE --\"); } else { mute = 0; ssd1306_char_f6x8(23, 0, \"-- SOUND ON --\");  }    \n      break;\n    }\n    if (sChange == 1) break;\n  }  \n  while(digitalRead(0) == HIGH);\n\n\n  if (sChange == 0) {\n    for (byte mm = 112;mm>=1;mm--) {\n      if ( (mm>=32) && (mm<56) ) drawFire(104,mm);\n      if (mm == 32) {\n        ssd1306_setpos(100,3);      \n        ssd1306_send_data_start();\n        sendBlock(0);\n        ssd1306_send_data_stop();\n        ssd1306_setpos(100,4);      \n        ssd1306_send_data_start();\n        sendBlock(0);\n        ssd1306_send_data_stop();\n        beep(30,100);\n      }\n      ssd1306_setpos(mm,0);      \n      ssd1306_send_data_start();\n      sendBlock(3);\n      sendBlock(0);\n      ssd1306_send_data_stop();\n      drawPlatform();\n      delay(20);\n    }\n    ssd1306_setpos(0,0);      \n    ssd1306_send_data_start();\n    sendBlock(0);\n    sendBlock(0);\n    ssd1306_send_data_stop();\n    ssd1306_char_f6x8(0, 6, \"inspired bh\");  // see comments above !\n    ssd1306_char_f6x8(0, 7, \"/ebboggles.com\");  // see comments above !\n    delay(1500);\n    ssd1306_init();\n    ssd1306_fillscreen(0x00);\n    stopAnimate = 0;\n    score = 0;\n\n    playSpaceAttack(); \n    top=topScoreB;\n    \n    ssd1306_fillscreen(0x00);\n    ssd1306_char_f6x8(11, 1, \"----------------\");\n    ssd1306_char_f6x8(11, 2, \"G A M E  O V E R\");\n    ssd1306_char_f6x8(11, 3, \"----------------\");\n    ssd1306_char_f6x8(37, 5, \"SCORE:\");\n    doNumber(75, 5, score);\n    if (!newHigh) {\n      ssd1306_char_f6x8(21, 7, \"HIGH SCORE:\");\n      doNumber(88, 7, top);\n    }\n    for (int i = 0; i<1000; i = i+ 50){\n      beep(50,i);\n    }\n    delay(2000);\n    if (newHigh) {\n      ssd1306_fillscreen(0x00);\n      ssd1306_char_f6x8(10, 1, \"----------------\");\n      ssd1306_char_f6x8(10, 3, \" NEW HIGH SCORE \");\n      ssd1306_char_f6x8(10, 7, \"----------------\");\n      doNumber(50,5,top);\n      for (int i = 700; i>200; i = i - 50){\n      beep(30,i);\n      }\n      newHigh = 0;\n      delay(2700);    \n    } \n  }\n  system_sleep();\n}\n\nvoid doNumber (int x, int y, int value) {\n    char temp[10] = {0,0,0,0,0,0,0,0,0,0};\n    itoa(value,temp,10);\n    ssd1306_char_f6x8(x, y, temp);\n}\n\nvoid ssd1306_init(void){\n  DDRB |= (1 << SSD1306_SDA); // Set port as output\n  DDRB |= (1 << SSD1306_SCL); // Set port as output\n\n  ssd1306_send_command(0xAE); // display off\n  ssd1306_send_command(0x00); // Set Memory Addressing Mode\n  ssd1306_send_command(0x10); // 00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid\n  ssd1306_send_command(0x40); // Set Page Start Address for Page Addressing Mode,0-7\n  ssd1306_send_command(0x81); // Set COM Output Scan Direction\n  ssd1306_send_command(0xCF); // ---set low column address\n  ssd1306_send_command(0xA1); // ---set high column address\n  ssd1306_send_command(0xC8); // --set start line address\n  ssd1306_send_command(0xA6); // --set contrast control register\n  ssd1306_send_command(0xA8);\n  ssd1306_send_command(0x3F); // --set segment re-map 0 to 127\n  ssd1306_send_command(0xD3); // --set normal display\n  ssd1306_send_command(0x00); // --set multiplex ratio(1 to 64)\n  ssd1306_send_command(0xD5); // \n  ssd1306_send_command(0x80); // 0xa4,Output follows RAM content;0xa5,Output ignores RAM content\n  ssd1306_send_command(0xD9); // -set display offset\n  ssd1306_send_command(0xF1); // -not offset\n  ssd1306_send_command(0xDA); // --set display clock divide ratio/oscillator frequency\n  ssd1306_send_command(0x12); // --set divide ratio\n  ssd1306_send_command(0xDB); // --set pre-charge period\n  ssd1306_send_command(0x40); // \n  ssd1306_send_command(0x20); // --set com pins hardware configuration\n  ssd1306_send_command(0x02);\n  ssd1306_send_command(0x8D); // --set vcomh\n  ssd1306_send_command(0x14); // 0x20,0.77xVcc\n  ssd1306_send_command(0xA4); // --set DC-DC enable\n  ssd1306_send_command(0xA6); // \n  ssd1306_send_command(0xAF); // --turn on oled panel \n}\n\nvoid ssd1306_xfer_start(void){\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n}\n\nvoid ssd1306_xfer_stop(void){\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n}\n\nvoid ssd1306_send_byte(uint8_t byte){\n  uint8_t i;\n  for(i=0; i<8; i++)\n  {\n    if((byte << i) & 0x80)\n      DIGITAL_WRITE_HIGH(SSD1306_SDA);\n    else\n      DIGITAL_WRITE_LOW(SSD1306_SDA);\n    \n    DIGITAL_WRITE_HIGH(SSD1306_SCL);\n    DIGITAL_WRITE_LOW(SSD1306_SCL);\n  }\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);\n  DIGITAL_WRITE_LOW(SSD1306_SCL);\n}\n\nvoid ssd1306_send_command(uint8_t command){\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  // Slave address, SA0=0\n  ssd1306_send_byte(0x00);  // write command\n  ssd1306_send_byte(command);\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_send_data_start(void){\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);\n  ssd1306_send_byte(0x40);  //write data\n}\n\nvoid ssd1306_send_data_stop(void){\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_setpos(uint8_t x, uint8_t y)\n{\n  if (y>7) return;\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  //Slave address,SA0=0\n  ssd1306_send_byte(0x00);  //write command\n\n  ssd1306_send_byte(0xb0+y);\n  ssd1306_send_byte(((x&0xf0)>>4)|0x10); // |0x10\n  ssd1306_send_byte((x&0x0f)|0x01); // |0x01\n\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_fillscreen(uint8_t fill_Data){\n  uint8_t m,n;\n  for(m=0;m<8;m++)\n  {\n    ssd1306_send_command(0xb0+m); //page0-page1\n    ssd1306_send_command(0x00);   //low column start address\n    ssd1306_send_command(0x10);   //high column start address\n    ssd1306_send_data_start();\n    for(n=0;n<128;n++)\n    {\n      ssd1306_send_byte(fill_Data);\n    }\n    ssd1306_send_data_stop();\n  }\n}\n\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]){\n  uint8_t c,i,j=0;\n  while(ch[j] != '\\0')\n  {\n    c = ch[j] - 32;\n    if (c >0) c = c - 12;\n    if (c >15) c = c - 6;\n    if (c>40) c=c-9;\n    if(x>126)\n    {\n      x=0;\n      y++;\n    }\n    ssd1306_setpos(x,y);\n    ssd1306_send_data_start();\n    for(i=0;i<6;i++)\n    {\n      ssd1306_send_byte(pgm_read_byte(&ssd1306xled_font6x8[c*6+i]));\n    }\n    ssd1306_send_data_stop();\n    x += 6;\n    j++;\n  }\n}\n\nvoid system_sleep() {\n  ssd1306_fillscreen(0x00);\n  ssd1306_send_command(0xAE);\n  cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF\n  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here\n  sleep_enable();\n  sleep_mode();                        // System actually sleeps here\n  sleep_disable();                     // System continues execution here when watchdog timed out \n  sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON  \n  ssd1306_send_command(0xAF);\n}\n\nvoid beep(int bCount,int bDelay){\n  if (mute) return;\n  for (int i = 0; i<=bCount; i++){digitalWrite(1,HIGH);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}digitalWrite(1,LOW);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}}\n}\n\n\n\n/* ------------------------\n *  SpaceAttack Code\n */\nvoid playSpaceAttack() {\n\n  firecounter = 0; // Timer for managing fire\n  level = 1; // Game level - incremented every time you clear the screen\n  topScoreB = 0; // highscore\n  score = 0; // obvious\n  \n  // Initialisations\n  for (byte i = 0; i<5;i++) {\n    alienFire[i][0] = 0;\n  }\n  resetAliens();\n\n  levelUp(1); // This also does various essential initialisations\n  \n  attachInterrupt(0,playerIncSpaceAttack,CHANGE);\n\n  while (stopAnimate == 0) {\n    while(1) {\n    aliencounter++;\n    firecounter++;\n    mothercounter++;\n    \n    // deal with inputs\n    if(analogRead(0) < 940) fire =1; // this reads the reset pin (pin 1) of the Attiny85 - to use it, see comments section above\n\n    if(digitalRead(2)==1) {\n      if (digitalRead(0)==1) fire = 1;\n      if(player < 127-platformWidth) {\n        player++;\n        } \n    }\n    if (digitalRead(0)==1){\n      if (digitalRead(2)==1) fire = 1;\n      if (player >1){\n        player--;\n        } \n     }\n\n    if ( (mothership == 0) && (random(0,1000) > 998) && (alienRow>0) ) {\n      mothership = 1;\n      mothershipX= 127-16;\n    }\n\n    // draw aliens\n    for (int inc = 0; inc <= lastActiveRow; inc ++) {\n      ssd1306_setpos((positionNow*8),inc+alienRow);\n      ssd1306_send_data_start();\n      for (int bl = firstAlien; bl <=lastAlien; bl++){\n        if(row[inc][bl]==1){\n          if (inc == lastActiveRow) {\n            if(random(0,1000) > (999-level)) { // this alien is going to fire!\n              byte afIndex = 0;\n              while (alienFire[afIndex][0] == 1) {\n                afIndex++; // search for empty alien fire option\n                if (afIndex == 5) break;\n              } \n              if (afIndex < 5) { // we've found a slot\n                alienFire[afIndex][0] = 1; // activate fire on this slot\n                alienFire[afIndex][1] = ( (positionNow*8) + ((bl-firstAlien) * 8) + 4); // x position\n                alienFire[afIndex][2] = (inc+alienRow+1)*8; // Where the fire starts\n              }\n            } // end of this alien firing\n          } // only if we are on the lowest row of live aliens\n          if ( (inc == 0) || (inc == 2) ) {\n            sendBlock(1);\n          } else {\n            sendBlock(2);\n          }\n        }else {\n          sendBlock(0);\n        }\n       }   \n      ssd1306_send_data_stop();\n    }\n\n\n    // Display the score\n    doNumber(0,6,score);\n    \n    // Burn clock cycles to keep game at constant (ish) speed when there are low numbers of live aliens \n    int burnLimit = (8-(lastAlien-firstAlien));\n    for (int burn = 0; burn < burnLimit; burn+=2) {                  \n        drawPlatform();    \n        }\n\n    // Display the mothership\n    if (mothercounter >= 3) {\n      mothercounter = 0;    \n      // draw mothership\n      if (mothership) {\n        ssd1306_setpos(mothershipX,0);\n        ssd1306_send_data_start();\n        sendBlock(3);\n        sendBlock(0);\n        ssd1306_send_data_stop();\n        mothershipX --;\n        if (mothershipX == 0) {\n          mothership = 0;                      \n          ssd1306_setpos(mothershipX,0);\n          ssd1306_send_data_start();\n          sendBlock(0);\n          sendBlock(0);\n          ssd1306_send_data_stop();\n        }\n      }\n    }\n\n    // Move the aliens\n    if (aliencounter >= (92-((level-1)*5)) ) {\n        aliencounter = 0;\n      if(alienDirection) { // Moving right\n        // move down a row\n        if (positionNow >= 6+(8-(lastAlien-firstAlien))) {\n          alienDirection = 0;\n          clearAlienArea(alienRow,lastActiveRow);                                   \n          alienRow++;\n        } else {\n          positionNow++;\n        }\n      } else { // Moving left\n        // move down a row\n        if (positionNow <= 0) {\n          alienDirection = 1;\n          clearAlienArea(alienRow,lastActiveRow);                                   \n          alienRow++;\n        } else {\n          positionNow --;\n        }\n      } \n      clearAlienArea(alienRow,lastActiveRow);                                   \n    }\n\n    // Fire !\n    if ((fire == 1) && (playerFire[0] == 0)) { // fire has been pressed and we're not currently firing - initiate fire!!\n      playerFire[0] = 1;\n      playerFire[1] = player+platformWidth/2; // xposition of new fire!\n      playerFire[2] = 56;\n    }\n\n    // Handle all firing-related stuff (in both directions!)\n    if (firecounter >= 2) {                  \n      firecounter = 0;\n      // --- Deal with player Firing --- \n      if (playerFire[0] == 1) {                      \n          drawFire(playerFire[1], playerFire[2]);\n          if (playerFire[2] == 0) {\n            ssd1306_setpos(playerFire[1],0);\n            uint8_t temp = B00000000;\n            ssd1306_send_data_start();\n            ssd1306_send_byte(temp);  \n            ssd1306_send_data_stop();                                                          \n            playerFire[0] = 0;\n            fire = 0;\n          } else {\n            playerFire[2] = playerFire[2] - 1;                          \n          }\n      }\n      \n      // aliens are at positionNow * 8 + 8* their index\n      \n      leftLimit = positionNow*8;\n      if ((fire == 1)) {\n        fireXidx = firstAlien + floor((playerFire[1]-positionNow*8)/8);                    \n        fireYidx=  floor(floor(playerFire[2]/8) - alienRow);\n        \n        if((mothership == 1) && (playerFire[1] >= mothershipX) && (playerFire[1] <= mothershipX +8) && playerFire[2] <=8) {\n          long scm = random(1,100);\n          if (scm<30) {\n            score +=50;\n          } else if (scm<60) {\n            score += 100;\n          } else if (scm<90) {\n            score += 150;\n          } else {\n            score += 300;\n          }\n            \n          beep(30,400);\n          beep(30,300);          \n          beep(30,200);\n          beep(30,100);\n          mothership = 0;\n          ssd1306_setpos(mothershipX,0);\n          ssd1306_send_data_start();\n          sendBlock(0);\n          sendBlock(0);\n          ssd1306_send_data_stop();\n        }\n\n        // Alien has been hit\n        if ((playerFire[1] >= leftLimit) && (fireYidx>=0) && (fireYidx<=lastActiveRow) && (fireXidx>=0) && (fireXidx<9)) {                    \n          if (row[fireYidx][fireXidx] == 1) { \n\n            int lastActiveToClear = lastActiveRow; // if we kill the last alien on a row - we still need to clear that row (end of this fn)\n            \n            if (fireYidx == 2) deadOn2++;\n            if (fireYidx == 1) deadOn1++;\n            \n            if (deadOn2 == 5) {lastActiveRow = 1;}\n            if ((deadOn1 == 4) && (deadOn2 == 5)) {lastActiveRow = 0;}\n\n            score = score + (int)((3-fireYidx) * 10);\n                        \n            aliensDead++;                      \n            ssd1306_setpos(playerFire[1],alienRow+fireYidx+1);\n            uint8_t temp = B00000000;\n            ssd1306_send_data_start();\n            ssd1306_send_byte(temp);  \n            ssd1306_send_data_stop();                                                          \n            beep(30,100);\n            \n            fire = 0;\n            playerFire[0] = 0;\n            playerFire[1] = 0;\n            playerFire[2] = 7;\n            row[fireYidx][fireXidx] = 0;\n            \n            if (fireXidx == firstAlien) { // this is the first Alien - sweep back and reset to new first alien\n              for (int xi = lastAlien; xi>=firstAlien;xi--) {\n                if ( (row[0][xi] == 1) || (row[1][xi] == 1) || (row[2][xi] == 1) ) newFirst = xi;\n              }\n              positionNow += newFirst - firstAlien;\n              firstAlien = newFirst;\n            }\n            \n            if (fireXidx == lastAlien) { // this is the last Alien - sweep thru and reset to new last alien\n              for (int xi = firstAlien; xi<=lastAlien;xi++) {\n                if ( (row[0][xi] == 1) || (row[1][xi] == 1) || (row[2][xi] == 1) ) newLast = xi;\n              }\n              lastAlien = newLast;\n            }\n            clearAlienArea(alienRow,lastActiveToClear);\n                                               \n          }         \n        }\n      }\n\n\n      // --- Deal with Alien Firing --- \n      for (byte afIndex = 0; afIndex<5; afIndex++) {\n        if(alienFire[afIndex][0] == 1) {\n          drawFire(alienFire[afIndex][1],alienFire[afIndex][2]);\n          alienFire[afIndex][2] = alienFire[afIndex][2] + 1;\n\n          if (alienFire[afIndex][2] >= 56) {\n            ssd1306_setpos(alienFire[afIndex][1],7);\n            uint8_t temp = B00000000;\n            ssd1306_send_data_start();\n            ssd1306_send_byte(temp);  \n            ssd1306_send_data_stop();                                                          \n            alienFire[afIndex][0] = 0; // the fire's got to the end\n            if( ((alienFire[afIndex][1]) > player) && ( (alienFire[afIndex][1]) < player+platformWidth) ) { // you've been hit!!\n              stopAnimate = 1;\n              goto die;\n              }\n          }\n        }                  \n      } // end of aliens firing                  \n    }\n\n    if (aliensDead == 14) {\n      for (int ai = 0; ai <= 5; ai++) alienFire[ai][0] = 0;\n\n      level++;\n      if (level>15) level = 15;\n      levelUp(level);\n\n      resetAliens();\n    }\n    \n    if( ((alienRow == 5) && (lastActiveRow == 2))||  ( (alienRow == 6) && (lastActiveRow == 1)) || ((alienRow == 7) && (lastActiveRow == 0)) || stopAnimate) {\n      stopAnimate = 1;\n      break;\n    }\n    // draw the player\n    drawPlatform();\n    }\n }\ndie:\n  topScoreB = EEPROM.read(0);\n  topScoreB = topScoreB << 8;\n  topScoreB = topScoreB |  EEPROM.read(1);\n\n  if (score > topScoreB) { \n    topScoreB = score;\n    EEPROM.write(1,score & 0xFF); \n    EEPROM.write(0,(score>>8) & 0xFF); \n    newHigh = 1;\n    }\n  }\n\nvoid drawPlatform(){\n ssd1306_setpos(player,7);\n ssd1306_send_data_start();\n ssd1306_send_byte(B00000000);   \n ssd1306_send_byte(B00000000);   \n for (byte pw = 0; pw <5; pw++){ssd1306_send_byte(B11000000);}                \n for (byte pw = 0; pw <4; pw++){ssd1306_send_byte(B11110000);}                \n for (byte pw = 0; pw <5; pw++){ssd1306_send_byte(B11000000);}                \n ssd1306_send_byte(B00000000);   \n ssd1306_send_byte(B00000000);   \n ssd1306_send_data_stop();  \n}\n\nvoid sendBlock(int fill){\n  if (fill == 1) {\n   ssd1306_send_byte(B10011000);\n   ssd1306_send_byte(B01011100);\n   ssd1306_send_byte(B10110110);\n   ssd1306_send_byte(B01011111);\n   ssd1306_send_byte(B01011111);\n   ssd1306_send_byte(B10110110);\n   ssd1306_send_byte(B01011100);\n   ssd1306_send_byte(B10011000);\n  } else if (fill == 2) {\n   ssd1306_send_byte(B00110000);\n   ssd1306_send_byte(B00111110);\n   ssd1306_send_byte(B10110011);\n   ssd1306_send_byte(B01011101);\n   ssd1306_send_byte(B01011101);\n   ssd1306_send_byte(B10110011);\n   ssd1306_send_byte(B00111110);\n   ssd1306_send_byte(B00110000);  \n  } else if (fill == 3) {\n   ssd1306_send_byte(B00011000);\n   ssd1306_send_byte(B00111000);\n   ssd1306_send_byte(B00110100);\n   ssd1306_send_byte(B00110100);\n   ssd1306_send_byte(B00110100);\n   ssd1306_send_byte(B00110100);\n   ssd1306_send_byte(B00111000);\n   ssd1306_send_byte(B00011000);  \n  } else if (fill == 0) {\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n  } \n}\n\nvoid levelUp(int number) {\n\n  fire = 0; // make sure no fire\n  playerFire[0] = 0; // player fire inactive\n  aliencounter=0;\n  firecounter=0;\n  mothercounter=0;\n  firstAlien = 0;\n  lastAlien = 8;\n  newFirst = 0;\n  newLast = 8;\n  lastActiveRow = 2;\n  deadOn1 = 0;\n  deadOn2 = 0;\n  aliensDead = 0;      \n  mothership = 0;\n  alienRow = 0;\n  positionNow = 0;\n  alienDirection = 1;\n  player = 64;\n\n  ssd1306_fillscreen(0x00);\n  ssd1306_char_f6x8(16, 3, \"--------------\");\n  ssd1306_char_f6x8(16, 4, \" L E V E L \");\n  ssd1306_char_f6x8(16, 5, \"--------------\");\n  doNumber(85,4,number);\n  for (int i = 800; i>200; i = i - 200){\n  beep(30,i);\n  }\n  delay(700);    \n  ssd1306_fillscreen(0x00);\n}\n\nvoid drawFire(int x, int y) {\n  if (y%8!=0){\n    ssd1306_setpos(x,y/8);\n    ssd1306_send_data_start();\n    doDrawLS(0,y%8);\n    ssd1306_send_data_stop();\n    \n    ssd1306_setpos(x,y/8+1);\n    ssd1306_send_data_start();\n    doDrawRS(0,8-y%8);\n    ssd1306_send_data_stop();\n  } else {\n    ssd1306_setpos(x,y/8);\n    ssd1306_send_data_start();\n    doDrawLS(0,0);\n    ssd1306_send_data_stop();\n  }\n}\n\n// Drawing routine for the player and fire - with right-shifts\nvoid doDrawRS(long P1, byte P2) {\n  ssd1306_send_byte((B01111110 | P1)>>P2);\n}\n\n// Drawing routine for the player and fire - with left-shifts\nvoid doDrawLS(long P1, byte P2) {\n  ssd1306_send_byte((B01111110 | P1)<<P2);\n}\n\nvoid clearAlienArea(int row, int lastActive) {\n  // clear alien area\n  for (int inc = row; inc <=row+lastActive; inc ++) {\n    ssd1306_setpos(0,inc);\n    ssd1306_send_data_start();\n    for (int bl = 0; bl <16; bl++){\n      sendBlock(0);\n      }   \n      ssd1306_send_data_stop();\n    }\n}\n\nvoid resetAliens(void) {\n  for (byte i =0; i<10;i++){ // reset aliens\n    row[0][i]=0; row[1][i]=0; row[2][i]=0;\n  } \n  for (byte i =0; i<9;i+=2){ // reset aliens\n    row[0][i]=1; row[2][i]=1;\n  } \n  for (byte i =1; i<9;i+=2){ // reset aliens\n    row[1][i]=1;\n  }     \n}\n\n\r\n"
  },
  {
    "path": "SpaceAttackAttiny/font6x8AJ.h",
    "content": "/*\n * SSD1306xLED - Drivers for SSD1306 controlled dot matrix OLED/PLED 128x64 displays\n *\n * @file: font6x8.h\n * @created: 2014-08-12\n * @author: Neven Boyanov\n * \n * Hacked by andy jackson to allow two games (originally by webboggles.com) to \n * fit onto an ATTiny85 at the same time - hence several characters are missing\n * and a couple have been moved to limit the amount of software remapping required\n * to map ASCII values onto locations in this array.\n *\n * Source code available at: https://bitbucket.org/tinusaur/ssd1306xled\n *\n */\n\n// ----------------------------------------------------------------------------\n\n#include <avr/pgmspace.h>\n\n// ----------------------------------------------------------------------------\n\n/* Standard ASCII 6x8 font */\nstatic const uint8_t ssd1306xled_font6x8 [] PROGMEM = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sp\n/*\n  0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // !\n  0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // \"\n  0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // #\n  0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $\n  0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // %\n  0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // &\n  0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // '\n  0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // (\n  0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // )\n  0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // *\n  0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // +\n  0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // ,\n  */\n  0x00, 0x08, 0x08, 0x08, 0x08, 0x08, // -\n  0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // .\n  0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w in place of /\n  //0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // /\n  0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0\n  0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, // 1\n  0x00, 0x42, 0x61, 0x51, 0x49, 0x46, // 2\n  0x00, 0x21, 0x41, 0x45, 0x4B, 0x31, // 3\n  0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, // 4\n  0x00, 0x27, 0x45, 0x45, 0x45, 0x39, // 5\n  0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6\n  0x00, 0x01, 0x71, 0x09, 0x05, 0x03, // 7\n  0x00, 0x36, 0x49, 0x49, 0x49, 0x36, // 8\n  0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, // 9\n  0x00, 0x00, 0x36, 0x36, 0x00, 0x00, // :\n/*\n  0x00, 0x00, 0x56, 0x36, 0x00, 0x00, // ;\n  0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // <\n  0x00, 0x14, 0x14, 0x14, 0x14, 0x14, // =\n  0x00, 0x00, 0x41, 0x22, 0x14, 0x08, // >\n  0x00, 0x02, 0x01, 0x51, 0x09, 0x06, // ?\n  0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, // @\n */\n  0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, // B\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, // C\n  0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, // D\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, // E\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, // F\n  0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, // G\n  0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, // H\n  0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, // I\n  0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, // J\n  0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, // K\n  0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, // L\n  0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M\n  0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, // N\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, // O\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, // P\n  0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q\n  0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, // R\n  0x00, 0x46, 0x49, 0x49, 0x49, 0x31, // S\n  0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, // T\n  0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, // U\n  0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, // V\n  0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, // W\n/*\n  0x00, 0x63, 0x14, 0x08, 0x14, 0x63, // X\n  0x00, 0x07, 0x08, 0x70, 0x08, 0x07, // Y\n  0x00, 0x61, 0x51, 0x49, 0x45, 0x43, // Z\n  0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, // [\n  0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55, // 55\n  0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, // ]\n  0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^\n  0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _\n  0x00, 0x00, 0x01, 0x02, 0x04, 0x00, // '\n*/\n  0x00, 0x20, 0x54, 0x54, 0x54, 0x78, // a\n  0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, // b\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x20, // c\n  0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, // d\n  0x00, 0x38, 0x54, 0x54, 0x54, 0x18, // e\n  0x00, 0x08, 0x7E, 0x09, 0x01, 0x02, // f\n  0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g\n  0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C, // y (in place of h)\n  //0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h\n  0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, // i\n  0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, // j\n  0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, // k\n  0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, // l\n  0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, // m\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, // n\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x38, // o\n  0x00, 0xFC, 0x24, 0x24, 0x24, 0x18, // p\n  0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, // q\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, // r\n  0x00, 0x48, 0x54, 0x54, 0x54, 0x20, // s\n  0x00, 0x04, 0x3F, 0x44, 0x40, 0x20, // t\n  0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, // u\n  0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, // v\n // 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w\n // 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, // x\n // 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C // y\n};\n\n// ----------------------------------------------------------------------------\n\r\n"
  },
  {
    "path": "Space_Attack_Analog/Space_Attack_Analog.ino",
    "content": "/* 2015 / 2016 /2017\n * SpaceAttack game by Andy Jackson - Twitter @andyhighnumber\n * Inspired by http://webboggles.com/ and includes some code from the #AttinyArcade games on that site\n * The code that does not fall under the licenses of sources listed below can be used non commercially with attribution.\n * \n * This is the analog version, which requires a potentiometer across the supply rails, with the centre tap connected to pin 7. There should be a\n * circuit diagram in the folder where you found these files.\n * \n * Also, from standby....\n *  Press and hold button with knob fully clockwise to turn sound on and off\n *  Press and hold button with knob fully counter-clockwise to reset high score\n * \n * If you have problems uploading this sketch, this is probably due to sketch size - you need to update ld.exe in arduino\\hardware\\tools\\avr\\avr\\bin\n * https://github.com/TCWORLD/ATTinyCore/tree/master/PCREL%20Patch%20for%20GCC\n *\n * This sketch is using the screen control and font functions written by Neven Boyanov for the http://tinusaur.wordpress.com/ project\n * Source code and font files available at: https://bitbucket.org/tinusaur/ssd1306xled\n * **Note that this highly size-optimised version requires modified library functions (which are in this source code file) \n * and a modified font header\n * \n * Sleep code is based on this blog post by Matthew Little:\n * http://www.re-innovation.co.uk/web12/index.php/en/blog-75/306-sleep-modes-on-attiny85\n*/\n#include <EEPROM.h>\n#include \"font6x8AJ.h\"\n#include <avr/sleep.h>\n#include <avr/interrupt.h> // needed for the additional interrupt\n\n#define DIGITAL_WRITE_HIGH(PORT) PORTB |= (1 << PORT)\n#define DIGITAL_WRITE_LOW(PORT) PORTB &= ~(1 << PORT)\n\n// Routines to set and clear bits (used in the sleep code)\n#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))\n#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))\n\n// Defines for OLED output\n#define SSD1306XLED_H\n#define SSD1306_SCL   PORTB4  // SCL, Pin 4 on SSD1306 Board - for webbogles board\n#define SSD1306_SDA   PORTB3  // SDA, Pin 3 on SSD1306 Board - for webbogles board\n#define SSD1306_SA    0x78  // Slave address\n\n// Function prototypes\nvoid resetAliens(void);\nvoid drawPlatform(void);\nvoid sendBlock(int);\nvoid playSpaceAttack(void);\nvoid beep(int,int);\nvoid levelUp(int);\nvoid drawFire(int x, int y);\nvoid doDrawLS(long, byte);\nvoid doDrawRS(long, byte);\nvoid clearAlienArea(int row, int lastActive);\nvoid doNumber (int x, int y, int value);\nvoid ssd1306_init(void);\nvoid ssd1306_xfer_start(void);\nvoid ssd1306_xfer_stop(void);\nvoid ssd1306_send_byte(uint8_t byte);\nvoid ssd1306_send_command(uint8_t command);\nvoid ssd1306_send_data_start(void);\nvoid ssd1306_send_data_stop(void);\nvoid ssd1306_setpos(uint8_t x, uint8_t y);\nvoid ssd1306_fillscreen(uint8_t fill_Data);\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]);\nvoid ssd1306_draw_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t bitmap[]);\n\nlong firecounter = 0; // Timer for managing fire\nlong aliencounter = 0; // Timer for alien movement\nint mothercounter = 0; // Timer for movement of the mothership\nint level = 1; // Game level - incremented every time you clear the screen\nint mothershipX = 0; // position of mothership\nint mothership = 0; // is mothership active?\nint mothershipWidth = 8; // mothership width in pixels\nint fireXidx, fireYidx; // mapping of player fire locaiton onto array of aliens\nint leftLimit; // furtherst left in x-axis pixels that the aliens are currently\nint positionNow = 0; // current position of the alien array (as steps from the left)\nboolean alienDirection = 1; // current direction of travel for alien swarm - 1 is right 0 is left\nint alienRow = 0; // which alien row are we considering\nint alienFire[5][3]; // max 5 lots of alien fire  - indices are active, xpos, ypos\nint playerFire[3]; // one lot of player fire - indices are active, xpos, ypos\nboolean row[4][10]; // on-off array of aliens\nint firstAlien = 0; // index of first live alien in the array\nint lastAlien = 8; // index of last live alien in the array\nint newFirst = firstAlien; // as above when it changes\nint newLast = lastAlien; // ...\nint aliensDead = 0; // how many aliens have been killed in total on this level?\nint lastActiveRow = 2; // what's the lowest row in which we will find live aliens?\nint deadOn1 = 0; // how many aliens are dead on row one (middle row)\nint deadOn2 = 0; // how many aliens are dead on row two (bottom row)\n\nboolean fire = 0;\nint topScoreB = 0;\nint player; //0 to 128-platformWidth  - this is the position of the player\nint lastPlayer;\nint platformWidth = 16; \nboolean stopAnimate = 0; // this is set to 1 when a collision is detected\nboolean mute = 0;\nboolean newHigh = 0;\nint score = 0; // score - this affects the difficulty of the game\nint top = 0;\n\n// Interrupt handlers\nISR(PCINT0_vect){ // PB0 pin button interrupt           \n}\n\nvoid playerIncSpaceAttack(){ // PB2 pin button interrupt\n}\n\n// Arduino stuff - setup\nvoid setup() {\n  DDRB = 0b00000010;    // set PB1 as output (for the speaker)\n  PCMSK = 0b00000001; // pin change mask: listen to portb bit 1\n  GIMSK |= 0b00100000;  // enable PCINT interrupt \n  sei();          // enable all interrupts\n}\n\n// Arduino stuff - loop\nvoid loop() { \n  ssd1306_init();\n  ssd1306_fillscreen(0x00);\n  \n  // The lower case character set is seriously compromised because I've had to truncate the ASCII table\n  // to release space for executable code - hence lower case y and w are remapped to h and / respectively.\n  // There is no z in the table (or h!) as these aren't used anywhere in the text here and most of the \n  // symbols are also missing for the same reason (see my hacked version of font6x8.h - font6x8AJ.h for more detail)\n  ssd1306_char_f6x8(0, 1, \"S P A C E\");\n  ssd1306_char_f6x8(4, 2, \"A T T A C K\");\n  ssd1306_char_f6x8(0, 4, \"bh andh jackson\"); // see comments above !\n\n  ssd1306_setpos(85,1);\n  ssd1306_send_data_start();\n  sendBlock(1);\n  sendBlock(0);  \n  sendBlock(1);\n  ssd1306_send_data_stop();\n  ssd1306_setpos(85,2);\n  ssd1306_send_data_start();\n  sendBlock(0);\n  sendBlock(2);\n  sendBlock(0);\n  ssd1306_send_data_stop();\n  ssd1306_setpos(85,3);\n  ssd1306_send_data_start();\n  sendBlock(0);\n  sendBlock(0);  \n  sendBlock(1);\n  sendBlock(0);  \n  sendBlock(1);\n  ssd1306_send_data_stop();\n  player = 96;\n  drawPlatform();\n\n  long startT = millis();\n  long nowT =0;\n  boolean sChange = 0;\n  while(digitalRead(0) == HIGH) {\n    nowT = millis();\n    if (nowT - startT > 2000) {\n      sChange = 1;     \n      if (digitalRead(2) == HIGH) {\n        EEPROM.write(0,0);\n        EEPROM.write(1,0);\n        ssd1306_char_f6x8(8, 0, \"-HIGH SCORE RESET-\");  \n      } else if (mute == 0) { mute = 1; ssd1306_char_f6x8(32, 0, \"-- MUTE --\"); } else { mute = 0; ssd1306_char_f6x8(23, 0, \"-- SOUND ON --\");  }    \n      break;\n    }\n    if (sChange == 1) break;\n  }  \n  while(digitalRead(0) == HIGH);\n\n\n  if (sChange == 0) {\n    for (byte mm = 112;mm>=1;mm--) {\n      if ( (mm>=32) && (mm<56) ) drawFire(104,mm);\n      if (mm == 32) {        \n        ssd1306_setpos(100,3);      \n        ssd1306_send_data_start();\n        sendBlock(0);\n        ssd1306_send_data_stop();\n        ssd1306_setpos(100,4);      \n        ssd1306_send_data_start();\n        sendBlock(0);\n        ssd1306_send_data_stop();\n        beep(30,100);\n      }\n      ssd1306_setpos(mm,0);      \n      ssd1306_send_data_start();\n      sendBlock(3);\n      sendBlock(0);\n      ssd1306_send_data_stop();\n      drawPlatform();\n      delay(20);\n    }\n    ssd1306_setpos(0,0);      \n    ssd1306_send_data_start();\n    sendBlock(0);\n    sendBlock(0);\n    ssd1306_send_data_stop();\n    ssd1306_char_f6x8(0, 6, \"analog\");  // see comments above !\n    ssd1306_char_f6x8(0, 7, \"edition\");  // see comments above !\n    delay(1500);\n    ssd1306_init();\n    ssd1306_fillscreen(0x00);\n    stopAnimate = 0;\n    score = 0;\n\n    playSpaceAttack(); \n    top=topScoreB;\n    \n    ssd1306_fillscreen(0x00);\n    ssd1306_char_f6x8(11, 1, \"----------------\");\n    ssd1306_char_f6x8(11, 2, \"G A M E  O V E R\");\n    ssd1306_char_f6x8(11, 3, \"----------------\");\n    ssd1306_char_f6x8(37, 5, \"SCORE:\");\n    doNumber(75, 5, score);\n    if (!newHigh) {\n      ssd1306_char_f6x8(21, 7, \"HIGH SCORE:\");\n      doNumber(88, 7, top);\n    }\n    for (int i = 0; i<1000; i = i+ 50){\n      beep(50,i);\n    }\n    delay(2000);\n    if (newHigh) {\n      ssd1306_fillscreen(0x00);\n      ssd1306_char_f6x8(10, 1, \"----------------\");\n      ssd1306_char_f6x8(10, 3, \" NEW HIGH SCORE \");\n      ssd1306_char_f6x8(10, 7, \"----------------\");\n      doNumber(50,5,top);\n      for (int i = 700; i>200; i = i - 50){\n      beep(30,i);\n      }\n      newHigh = 0;\n      delay(2700);    \n    } \n  }\n  system_sleep();\n}\n\nvoid doNumber (int x, int y, int value) {\n    char temp[10] = {0,0,0,0,0,0,0,0,0,0};\n    itoa(value,temp,10);\n    ssd1306_char_f6x8(x, y, temp);\n}\n\nvoid ssd1306_init(void){\n  DDRB |= (1 << SSD1306_SDA); // Set port as output\n  DDRB |= (1 << SSD1306_SCL); // Set port as output\n\n  ssd1306_send_command(0xAE); // display off\n  ssd1306_send_command(0x00); // Set Memory Addressing Mode\n  ssd1306_send_command(0x10); // 00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid\n  ssd1306_send_command(0x40); // Set Page Start Address for Page Addressing Mode,0-7\n  ssd1306_send_command(0x81); // Set COM Output Scan Direction\n  ssd1306_send_command(0xCF); // ---set low column address\n  ssd1306_send_command(0xA1); // ---set high column address\n  ssd1306_send_command(0xC8); // --set start line address\n  ssd1306_send_command(0xA6); // --set contrast control register\n  ssd1306_send_command(0xA8);\n  ssd1306_send_command(0x3F); // --set segment re-map 0 to 127\n  ssd1306_send_command(0xD3); // --set normal display\n  ssd1306_send_command(0x00); // --set multiplex ratio(1 to 64)\n  ssd1306_send_command(0xD5); // \n  ssd1306_send_command(0x80); // 0xa4,Output follows RAM content;0xa5,Output ignores RAM content\n  ssd1306_send_command(0xD9); // -set display offset\n  ssd1306_send_command(0xF1); // -not offset\n  ssd1306_send_command(0xDA); // --set display clock divide ratio/oscillator frequency\n  ssd1306_send_command(0x12); // --set divide ratio\n  ssd1306_send_command(0xDB); // --set pre-charge period\n  ssd1306_send_command(0x40); // \n  ssd1306_send_command(0x20); // --set com pins hardware configuration\n  ssd1306_send_command(0x02);\n  ssd1306_send_command(0x8D); // --set vcomh\n  ssd1306_send_command(0x14); // 0x20,0.77xVcc\n  ssd1306_send_command(0xA4); // --set DC-DC enable\n  ssd1306_send_command(0xA6); // \n  ssd1306_send_command(0xAF); // --turn on oled panel \n}\n\nvoid ssd1306_xfer_start(void){\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n}\n\nvoid ssd1306_xfer_stop(void){\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n}\n\nvoid ssd1306_send_byte(uint8_t byte){\n  uint8_t i;\n  for(i=0; i<8; i++)\n  {\n    if((byte << i) & 0x80)\n      DIGITAL_WRITE_HIGH(SSD1306_SDA);\n    else\n      DIGITAL_WRITE_LOW(SSD1306_SDA);\n    \n    DIGITAL_WRITE_HIGH(SSD1306_SCL);\n    DIGITAL_WRITE_LOW(SSD1306_SCL);\n  }\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);\n  DIGITAL_WRITE_LOW(SSD1306_SCL);\n}\n\nvoid ssd1306_send_command(uint8_t command){\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  // Slave address, SA0=0\n  ssd1306_send_byte(0x00);  // write command\n  ssd1306_send_byte(command);\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_send_data_start(void){\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);\n  ssd1306_send_byte(0x40);  //write data\n}\n\nvoid ssd1306_send_data_stop(void){\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_setpos(uint8_t x, uint8_t y)\n{\n  if (y>7) return;\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  //Slave address,SA0=0\n  ssd1306_send_byte(0x00);  //write command\n\n  ssd1306_send_byte(0xb0+y);\n  ssd1306_send_byte(((x&0xf0)>>4)|0x10); // |0x10\n  ssd1306_send_byte((x&0x0f)|0x01); // |0x01\n\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_fillscreen(uint8_t fill_Data){\n  uint8_t m,n;\n  for(m=0;m<8;m++)\n  {\n    ssd1306_send_command(0xb0+m); //page0-page1\n    ssd1306_send_command(0x00);   //low column start address\n    ssd1306_send_command(0x10);   //high column start address\n    ssd1306_send_data_start();\n    for(n=0;n<128;n++)\n    {\n      ssd1306_send_byte(fill_Data);\n    }\n    ssd1306_send_data_stop();\n  }\n}\n\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]){\n  uint8_t c,i,j=0;\n  while(ch[j] != '\\0')\n  {\n    c = ch[j] - 32;\n    if (c >0) c = c - 12;\n    if (c >15) c = c - 6;\n    if (c>40) c=c-9;\n    if(x>126)\n    {\n      x=0;\n      y++;\n    }\n    ssd1306_setpos(x,y);\n    ssd1306_send_data_start();\n    for(i=0;i<6;i++)\n    {\n      ssd1306_send_byte(pgm_read_byte(&ssd1306xled_font6x8[c*6+i]));\n    }\n    ssd1306_send_data_stop();\n    x += 6;\n    j++;\n  }\n}\n\nvoid system_sleep() {\n  ssd1306_fillscreen(0x00);\n  ssd1306_send_command(0xAE);\n  cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF\n  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here\n  sleep_enable();\n  sleep_mode();                        // System actually sleeps here\n  sleep_disable();                     // System continues execution here when watchdog timed out \n  sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON  \n  ssd1306_send_command(0xAF);\n}\n\nvoid beep(int bCount,int bDelay){\n  if (mute) return;\n  for (int i = 0; i<=bCount; i++){digitalWrite(1,HIGH);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}digitalWrite(1,LOW);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}}\n}\n\n\n\n/* ------------------------\n *  SpaceAttack Code\n */\nvoid playSpaceAttack() {\n\n  firecounter = 0; // Timer for managing fire\n  level = 1; // Game level - incremented every time you clear the screen\n  player=64;\n  lastPlayer = 64;\n  topScoreB = 0; // highscore\n  score = 0; // obvious\n  \n  // Initialisations\n  for (byte i = 0; i<5;i++) {\n    alienFire[i][0] = 0;\n  }\n  resetAliens();\n\n  levelUp(1); // This also does various essential initialisations\n  \n  //attachInterrupt(0,playerIncSpaceAttack,CHANGE);\n\n  while (stopAnimate == 0) {\n    while(1) {\n    aliencounter++;\n    firecounter++;\n    mothercounter++;\n    \n    // deal with inputs\n    //if(analogRead(0) < 940) fire =1; // this reads the reset pin (pin 1) of the Attiny85 - to use it, see comments section above\n\n    if(digitalRead(0)==1) {\n      fire = 1;\n    }\n\n    player = (analogRead(1) / 8);\n    if (player > 111) player = 111;\n    if (player <0) player = 0;\n\n    /*\n    if (digitalRead(0)==1){\n      if (digitalRead(2)==1) fire = 1;\n      if (player >1){\n        player--;\n        } \n     }\n*/\n    if ( (mothership == 0) && (random(0,1000) > 998) && (alienRow>0) ) {\n      mothership = 1;\n      mothershipX= 127-16;\n    }\n\n    // draw aliens\n    for (int inc = 0; inc <= lastActiveRow; inc ++) {\n      ssd1306_setpos((positionNow*8),inc+alienRow);\n      ssd1306_send_data_start();\n      for (int bl = firstAlien; bl <=lastAlien; bl++){\n        if(row[inc][bl]==1){\n          if (inc == lastActiveRow) {\n            if(random(0,1000) > (999-level)) { // this alien is going to fire!\n              byte afIndex = 0;\n              while (alienFire[afIndex][0] == 1) {\n                afIndex++; // search for empty alien fire option\n                if (afIndex == 5) break;\n              } \n              if (afIndex < 5) { // we've found a slot\n                alienFire[afIndex][0] = 1; // activate fire on this slot\n                alienFire[afIndex][1] = ( (positionNow*8) + ((bl-firstAlien) * 8) + 4); // x position\n                alienFire[afIndex][2] = (inc+alienRow+1)*8; // Where the fire starts\n              }\n            } // end of this alien firing\n          } // only if we are on the lowest row of live aliens\n          if ( (inc == 0) || (inc == 2) ) {\n            sendBlock(1);\n          } else {\n            sendBlock(2);\n          }\n        }else {\n          sendBlock(0);\n        }\n       }   \n      ssd1306_send_data_stop();\n    }\n\n\n    // Display the score\n    doNumber(0,6,score);\n    \n    // Burn clock cycles to keep game at constant (ish) speed when there are low numbers of live aliens \n    int burnLimit = (8-(lastAlien-firstAlien));\n    for (int burn = 0; burn < burnLimit; burn+=2) {                  \n        drawPlatform();    \n        }\n\n    // Display the mothership\n    if (mothercounter >= 3) {\n      mothercounter = 0;    \n      // draw mothership\n      if (mothership) {\n        ssd1306_setpos(mothershipX,0);\n        ssd1306_send_data_start();\n        sendBlock(3);\n        sendBlock(0);\n        ssd1306_send_data_stop();\n        mothershipX --;\n        if (mothershipX == 0) {\n          mothership = 0;                      \n          ssd1306_setpos(mothershipX,0);\n          ssd1306_send_data_start();\n          sendBlock(0);\n          sendBlock(0);\n          ssd1306_send_data_stop();\n        }\n      }\n    }\n\n    // Move the aliens\n    if (aliencounter >= (92-((level-1)*5)) ) {\n        aliencounter = 0;\n      if(alienDirection) { // Moving right\n        // move down a row\n        if (positionNow >= 6+(8-(lastAlien-firstAlien))) {\n          alienDirection = 0;\n          clearAlienArea(alienRow,lastActiveRow);                                   \n          alienRow++;\n        } else {\n          positionNow++;\n        }\n      } else { // Moving left\n        // move down a row\n        if (positionNow <= 0) {\n          alienDirection = 1;\n          clearAlienArea(alienRow,lastActiveRow);                                   \n          alienRow++;\n        } else {\n          positionNow --;\n        }\n      } \n      clearAlienArea(alienRow,lastActiveRow);                                   \n    }\n\n    // Fire !\n    if ((fire == 1) && (playerFire[0] == 0)) { // fire has been pressed and we're not currently firing - initiate fire!!\n      playerFire[0] = 1;\n      playerFire[1] = player+platformWidth/2; // xposition of new fire!\n      playerFire[2] = 56;\n    }\n\n    // Handle all firing-related stuff (in both directions!)\n    if (firecounter >= 2) {                  \n      firecounter = 0;\n      // --- Deal with player Firing --- \n      if (playerFire[0] == 1) {                      \n          drawFire(playerFire[1], playerFire[2]);\n          if (playerFire[2] == 0) {\n            ssd1306_setpos(playerFire[1],0);\n            uint8_t temp = B00000000;\n            ssd1306_send_data_start();\n            ssd1306_send_byte(temp);  \n            ssd1306_send_data_stop();                                                          \n            playerFire[0] = 0;\n            fire = 0;\n          } else {\n            playerFire[2] = playerFire[2] - 1;                          \n          }\n      }\n      \n      // aliens are at positionNow * 8 + 8* their index\n      \n      leftLimit = positionNow*8;\n      if ((fire == 1)) {\n        fireXidx = firstAlien + floor((playerFire[1]-positionNow*8)/8);                    \n        fireYidx=  floor(floor(playerFire[2]/8) - alienRow);\n        \n        if((mothership == 1) && (playerFire[1] >= mothershipX) && (playerFire[1] <= mothershipX +8) && playerFire[2] <=8) {\n          long scm = random(1,100);\n          if (scm<30) {\n            score +=50;\n          } else if (scm<60) {\n            score += 100;\n          } else if (scm<90) {\n            score += 150;\n          } else {\n            score += 300;\n          }\n            \n          beep(30,400);\n          beep(30,300);          \n          beep(30,200);\n          beep(30,100);\n          mothership = 0;\n          ssd1306_setpos(mothershipX,0);\n          ssd1306_send_data_start();\n          sendBlock(0);\n          sendBlock(0);\n          ssd1306_send_data_stop();\n        }\n\n        // Alien has been hit\n        if ((playerFire[1] >= leftLimit) && (fireYidx>=0) && (fireYidx<=lastActiveRow) && (fireXidx>=0) && (fireXidx<9)) {                    \n          if (row[fireYidx][fireXidx] == 1) { \n\n            int lastActiveToClear = lastActiveRow; // if we kill the last alien on a row - we still need to clear that row (end of this fn)\n            \n            if (fireYidx == 2) deadOn2++;\n            if (fireYidx == 1) deadOn1++;\n            \n            if (deadOn2 == 5) {lastActiveRow = 1;}\n            if ((deadOn1 == 4) && (deadOn2 == 5)) {lastActiveRow = 0;}\n\n            score = score + (int)((3-fireYidx) * 10);\n                        \n            aliensDead++;                      \n            ssd1306_setpos(playerFire[1],alienRow+fireYidx+1);\n            uint8_t temp = B00000000;\n            ssd1306_send_data_start();\n            ssd1306_send_byte(temp);  \n            ssd1306_send_data_stop();                                                          \n            beep(30,100);\n            \n            fire = 0;\n            playerFire[0] = 0;\n            playerFire[1] = 0;\n            playerFire[2] = 7;\n            row[fireYidx][fireXidx] = 0;\n            \n            if (fireXidx == firstAlien) { // this is the first Alien - sweep back and reset to new first alien\n              for (int xi = lastAlien; xi>=firstAlien;xi--) {\n                if ( (row[0][xi] == 1) || (row[1][xi] == 1) || (row[2][xi] == 1) ) newFirst = xi;\n              }\n              positionNow += newFirst - firstAlien;\n              firstAlien = newFirst;\n            }\n            \n            if (fireXidx == lastAlien) { // this is the last Alien - sweep thru and reset to new last alien\n              for (int xi = firstAlien; xi<=lastAlien;xi++) {\n                if ( (row[0][xi] == 1) || (row[1][xi] == 1) || (row[2][xi] == 1) ) newLast = xi;\n              }\n              lastAlien = newLast;\n            }\n            clearAlienArea(alienRow,lastActiveToClear);\n                                               \n          }         \n        }\n      }\n\n\n      // --- Deal with Alien Firing --- \n      for (byte afIndex = 0; afIndex<5; afIndex++) {\n        if(alienFire[afIndex][0] == 1) {\n          drawFire(alienFire[afIndex][1],alienFire[afIndex][2]);\n          alienFire[afIndex][2] = alienFire[afIndex][2] + 1;\n\n          if (alienFire[afIndex][2] >= 56) {\n            ssd1306_setpos(alienFire[afIndex][1],7);\n            uint8_t temp = B00000000;\n            ssd1306_send_data_start();\n            ssd1306_send_byte(temp);  \n            ssd1306_send_data_stop();                                                          \n            alienFire[afIndex][0] = 0; // the fire's got to the end\n            if( ((alienFire[afIndex][1]) > player) && ( (alienFire[afIndex][1]) < player+platformWidth) ) { // you've been hit!!\n              stopAnimate = 1;\n              goto die;\n              }\n          }\n        }                  \n      } // end of aliens firing                  \n    }\n\n    if (aliensDead == 14) {\n      for (int ai = 0; ai <= 5; ai++) alienFire[ai][0] = 0;\n\n      level++;\n      if (level>15) level = 15;\n      levelUp(level);\n\n      resetAliens();\n    }\n    \n    if( ((alienRow == 5) && (lastActiveRow == 2))||  ( (alienRow == 6) && (lastActiveRow == 1)) || ((alienRow == 7) && (lastActiveRow == 0)) || stopAnimate) {\n      stopAnimate = 1;\n      break;\n    }\n    // draw the player\n    drawPlatform();\n    }\n }\ndie:\n  topScoreB = EEPROM.read(0);\n  topScoreB = topScoreB << 8;\n  topScoreB = topScoreB |  EEPROM.read(1);\n\n  if (score > topScoreB) { \n    topScoreB = score;\n    EEPROM.write(1,score & 0xFF); \n    EEPROM.write(0,(score>>8) & 0xFF); \n    newHigh = 1;\n    }\n  }\n\nvoid drawPlatform(){\n if(player > lastPlayer) {\n   ssd1306_setpos(lastPlayer,7);\n   ssd1306_send_data_start();\n   for (int pw = lastPlayer;pw <= player;pw++)  ssd1306_send_byte(B00000000);\n   ssd1306_send_data_stop();  \n }\n ssd1306_setpos(player,7);\n ssd1306_send_data_start();\n ssd1306_send_byte(B00000000);   \n ssd1306_send_byte(B00000000);   \n for (byte pw = 0; pw <5; pw++){ssd1306_send_byte(B11000000);}                \n for (byte pw = 0; pw <4; pw++){ssd1306_send_byte(B11110000);}                \n for (byte pw = 0; pw <5; pw++){ssd1306_send_byte(B11000000);}                \n ssd1306_send_byte(B00000000);   \n ssd1306_send_byte(B00000000);   \n if (player<lastPlayer) {\n  for (int pw = player;pw < lastPlayer;pw++)  ssd1306_send_byte(B00000000);\n }\n ssd1306_send_data_stop();  \n lastPlayer = player;\n}\n\nvoid sendBlock(int fill){\n  if (fill == 1) {\n   ssd1306_send_byte(B10011000);\n   ssd1306_send_byte(B01011100);\n   ssd1306_send_byte(B10110110);\n   ssd1306_send_byte(B01011111);\n   ssd1306_send_byte(B01011111);\n   ssd1306_send_byte(B10110110);\n   ssd1306_send_byte(B01011100);\n   ssd1306_send_byte(B10011000);\n  } else if (fill == 2) {\n   ssd1306_send_byte(B00110000);\n   ssd1306_send_byte(B00111110);\n   ssd1306_send_byte(B10110011);\n   ssd1306_send_byte(B01011101);\n   ssd1306_send_byte(B01011101);\n   ssd1306_send_byte(B10110011);\n   ssd1306_send_byte(B00111110);\n   ssd1306_send_byte(B00110000);  \n  } else if (fill == 3) {\n   ssd1306_send_byte(B00011000);\n   ssd1306_send_byte(B00111000);\n   ssd1306_send_byte(B00110100);\n   ssd1306_send_byte(B00110100);\n   ssd1306_send_byte(B00110100);\n   ssd1306_send_byte(B00110100);\n   ssd1306_send_byte(B00111000);\n   ssd1306_send_byte(B00011000);  \n  } else if (fill == 0) {\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n  } \n}\n\nvoid levelUp(int number) {\n\n  fire = 0; // make sure no fire\n  playerFire[0] = 0; // player fire inactive\n  aliencounter=0;\n  firecounter=0;\n  mothercounter=0;\n  firstAlien = 0;\n  lastAlien = 8;\n  newFirst = 0;\n  newLast = 8;\n  lastActiveRow = 2;\n  deadOn1 = 0;\n  deadOn2 = 0;\n  aliensDead = 0;      \n  mothership = 0;\n  alienRow = 0;\n  positionNow = 0;\n  alienDirection = 1;\n\n  ssd1306_fillscreen(0x00);\n  ssd1306_char_f6x8(16, 3, \"--------------\");\n  ssd1306_char_f6x8(16, 4, \" L E V E L \");\n  ssd1306_char_f6x8(16, 5, \"--------------\");\n  doNumber(85,4,number);\n  for (int i = 800; i>200; i = i - 200){\n  beep(30,i);\n  }\n  delay(700);    \n  ssd1306_fillscreen(0x00);\n}\n\nvoid drawFire(int x, int y) {\n  if (y%8!=0){\n    ssd1306_setpos(x,y/8);\n    ssd1306_send_data_start();\n    doDrawLS(0,y%8);\n    ssd1306_send_data_stop();\n    \n    ssd1306_setpos(x,y/8+1);\n    ssd1306_send_data_start();\n    doDrawRS(0,8-y%8);\n    ssd1306_send_data_stop();\n  } else {\n    ssd1306_setpos(x,y/8);\n    ssd1306_send_data_start();\n    doDrawLS(0,0);\n    ssd1306_send_data_stop();\n  }\n}\n\n// Drawing routine for the player and fire - with right-shifts\nvoid doDrawRS(long P1, byte P2) {\n  ssd1306_send_byte((B01111110 | P1)>>P2);\n}\n\n// Drawing routine for the player and fire - with left-shifts\nvoid doDrawLS(long P1, byte P2) {\n  ssd1306_send_byte((B01111110 | P1)<<P2);\n}\n\nvoid clearAlienArea(int row, int lastActive) {\n  // clear alien area\n  for (int inc = row; inc <=row+lastActive; inc ++) {\n    ssd1306_setpos(0,inc);\n    ssd1306_send_data_start();\n    for (int bl = 0; bl <16; bl++){\n      sendBlock(0);\n      }   \n      ssd1306_send_data_stop();\n    }\n}\n\nvoid resetAliens(void) {\n  for (byte i =0; i<10;i++){ // reset aliens\n    row[0][i]=0; row[1][i]=0; row[2][i]=0;\n  } \n  for (byte i =0; i<9;i+=2){ // reset aliens\n    row[0][i]=1; row[2][i]=1;\n  } \n  for (byte i =1; i<9;i+=2){ // reset aliens\n    row[1][i]=1;\n  }     \n}\n\n\r\n"
  },
  {
    "path": "Space_Attack_Analog/font6x8AJ.h",
    "content": "/*\n * SSD1306xLED - Drivers for SSD1306 controlled dot matrix OLED/PLED 128x64 displays\n *\n * @file: font6x8.h\n * @created: 2014-08-12\n * @author: Neven Boyanov\n * \n * Hacked by andy jackson to allow two games (originally by webboggles.com) to \n * fit onto an ATTiny85 at the same time - hence several characters are missing\n * and a couple have been moved to limit the amount of software remapping required\n * to map ASCII values onto locations in this array.\n *\n * Source code available at: https://bitbucket.org/tinusaur/ssd1306xled\n *\n */\n\n// ----------------------------------------------------------------------------\n\n#include <avr/pgmspace.h>\n\n// ----------------------------------------------------------------------------\n\n/* Standard ASCII 6x8 font */\nstatic const uint8_t ssd1306xled_font6x8 [] PROGMEM = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sp\n/*\n  0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // !\n  0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // \"\n  0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // #\n  0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $\n  0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // %\n  0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // &\n  0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // '\n  0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // (\n  0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // )\n  0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // *\n  0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // +\n  0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // ,\n  */\n  0x00, 0x08, 0x08, 0x08, 0x08, 0x08, // -\n  0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // .\n  0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w in place of /\n  //0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // /\n  0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0\n  0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, // 1\n  0x00, 0x42, 0x61, 0x51, 0x49, 0x46, // 2\n  0x00, 0x21, 0x41, 0x45, 0x4B, 0x31, // 3\n  0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, // 4\n  0x00, 0x27, 0x45, 0x45, 0x45, 0x39, // 5\n  0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6\n  0x00, 0x01, 0x71, 0x09, 0x05, 0x03, // 7\n  0x00, 0x36, 0x49, 0x49, 0x49, 0x36, // 8\n  0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, // 9\n  0x00, 0x00, 0x36, 0x36, 0x00, 0x00, // :\n/*\n  0x00, 0x00, 0x56, 0x36, 0x00, 0x00, // ;\n  0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // <\n  0x00, 0x14, 0x14, 0x14, 0x14, 0x14, // =\n  0x00, 0x00, 0x41, 0x22, 0x14, 0x08, // >\n  0x00, 0x02, 0x01, 0x51, 0x09, 0x06, // ?\n  0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, // @\n */\n  0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, // B\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, // C\n  0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, // D\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, // E\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, // F\n  0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, // G\n  0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, // H\n  0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, // I\n  0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, // J\n  0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, // K\n  0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, // L\n  0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M\n  0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, // N\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, // O\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, // P\n  0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q\n  0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, // R\n  0x00, 0x46, 0x49, 0x49, 0x49, 0x31, // S\n  0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, // T\n  0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, // U\n  0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, // V\n  0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, // W\n/*\n  0x00, 0x63, 0x14, 0x08, 0x14, 0x63, // X\n  0x00, 0x07, 0x08, 0x70, 0x08, 0x07, // Y\n  0x00, 0x61, 0x51, 0x49, 0x45, 0x43, // Z\n  0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, // [\n  0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55, // 55\n  0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, // ]\n  0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^\n  0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _\n  0x00, 0x00, 0x01, 0x02, 0x04, 0x00, // '\n*/\n  0x00, 0x20, 0x54, 0x54, 0x54, 0x78, // a\n  0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, // b\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x20, // c\n  0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, // d\n  0x00, 0x38, 0x54, 0x54, 0x54, 0x18, // e\n  0x00, 0x08, 0x7E, 0x09, 0x01, 0x02, // f\n  0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g\n  0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C, // y (in place of h)\n  //0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h\n  0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, // i\n  0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, // j\n  0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, // k\n  0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, // l\n  0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, // m\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, // n\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x38, // o\n  0x00, 0xFC, 0x24, 0x24, 0x24, 0x18, // p\n  0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, // q\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, // r\n  0x00, 0x48, 0x54, 0x54, 0x54, 0x20, // s\n  0x00, 0x04, 0x3F, 0x44, 0x40, 0x20, // t\n  0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, // u\n  0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, // v\n // 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w\n // 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, // x\n // 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C // y\n};\n\n// ----------------------------------------------------------------------------\n\r\n"
  },
  {
    "path": "Tetris_Attiny_Arcade/Tetris_Attiny_Arcade.ino",
    "content": "/* 2015 / 2016 /2017\n   Tetris for Attiny Arcade\n   ========================\n\n   When the game is running :\n   ==========================\n   Tap LEFT BUTTON - Moves the piece to the left (and wraps around at the left edge)\n   Hold LEFT BUTTON - Move the piece to the right\n   Tap RIGHT BUTTON - Rotates the piece\n   Hold RIGHT BUTTON - Place the piece\n\n   Before the game starts:\n   =======================\n   Hold LEFT BUTTON - Turns 'ghost' piece on and off\n   Hold RIGHT and LEFT BUTTONS together - Turns 'challenge mode' on and off (which fills the screens with random stuff at the start of the game to make\n   it more tricky!)\n\n   _________________________________________________________________________________________________________________________________________________________\n   This version developed by Andy Jackson - Twitter @andyhighnumber - Tweet me if you have any problems getting this to compile or run.\n   The code that does not fall under the licenses of sources listed below can be used non-commercially with or without attribution.\n   This software is supplied without warranty of any kind.\n   \n   Designed for the Attiny85 and optimised for the #AttinyArcade platform. The source code is less than 8KB and the sketch\n   should run happily with less than 300 bytes of RAM. You can find out more about this platform from http://webboggles.com/, buy kits\n   to make it (or get instructions / schematics). This sketch includes some code from the #AttinyArcade games on that site, including interrupt code. \n\n   This game started life as a port but is now essentially a clone of TinyTetris by Anthony Russell, with some additional features. There remain \n   elements of that original codebase, although the vast majority of what's here has been rewritten from scratch (including the screen, text and number \n   rendering code and much of the game engine) in order to optimise for memory, improve responsiveness and allow new features on the limited hardware \n   (added features include Highscore (saved to EEPROM), optional Ghost (or Shadow) Piece, Interrupt Handling and Hard-Mode functionality).  \n   \n   Anthony's source can be found here: https://github.com/AJRussell/Tiny-Tetris and is highly recommended if you'd like a version\n   of Tetris to run on normal Arduino hardware. It has some lovely graphics by Tobozo (which sadly there's not space for on the Attiny85) and it's also\n   possible that some code by Tobozo has made it into this version. Tobozo's repository can be found here; https://github.com/tobozo and is well worth a look. \n   There is an Instructables page relating to this project here: https://www.instructables.com/id/Tetris-Clone-With-OLED-SSD1306I2C-for-Arduino-Nano/ \n        \n   This sketch is using the screen control and font functions written by Neven Boyanov for the http://tinusaur.wordpress.com/ project\n   Source code and font files available at: https://bitbucket.org/tinusaur/ssd1306xled - hacked about by Andy Jackson to make them \n   render side-on for this game. All the necessary functions are in this file, there's no need to download any additional libraries to compile this game.\n\n   The sleep code in this file is based on this blog post by Matthew Little:\n   http://www.re-innovation.co.uk/web12/index.php/en/blog-75/306-sleep-modes-on-attiny85\n*/\n\n// The custom font file is the only additional file you should need to compile this game\n#include \"font8x8AJ.h\"\n\n// Standard Arduino headers\n#include <EEPROM.h> \n#include <avr/pgmspace.h>\n#include <avr/sleep.h>\n#include <avr/interrupt.h> // needed for the additional interrupt\n\n// Mode settings for functions with multiple purposes\n#define NORMAL 0\n#define GHOST 1\n#define FULL 0\n#define PARTIAL 1\n#define DRAW 0\n#define ERASE 1\n\n// The horizontal width of the playing area\n#define HORIZ 10\n// The vertical visible space of the playing area\n#define VERTDRAW 19\n// The size of the array of blocks (some are outside visible area to allow them to drop in from off screen)\n#define VERTMAX 24\n\n// The horizontal position where pieces begin\n#define STARTX 3\n// The vertical position where pieces begin\n#define STARTY 19\n// What level does the game start on\n#define STARTLEVEL 1\n// The multiplying factor that sets how the speed scales with level (one level increment for every row cleared)\n#define LEVELFACTOR 4\n// The number of milliseconds before each drop (baseline)\n#define DROPDELAY 600\n\n#define DIGITAL_WRITE_HIGH(PORT) PORTB |= (1 << PORT)\n#define DIGITAL_WRITE_LOW(PORT) PORTB &= ~(1 << PORT)\n\n// Routines to set and clear bits (used in the sleep code)\n#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))\n#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))\n\n// Defines for OLED output\n#define SSD1306XLED_H\n#define SSD1306_SCL   PORTB4  // SCL, Pin 4 on SSD1306 Board - for webbogles board\n#define SSD1306_SDA   PORTB3  // SDA, Pin 3 on SSD1306 Board - for webbogles board\n#define SSD1306_SA    0x78  // Slave address\n\n// The bitmaps for the little images of next block\nstatic const byte miniBlock[][4] PROGMEM = {\n    {0x77, 0x77, 0x00, 0x00}, \n    {0x70, 0x77, 0x70, 0x00}, \n    {0x70, 0x00, 0x70, 0x77}, \n    {0x70, 0x07, 0x70, 0x07}, \n    {0x70, 0x07, 0x00, 0xEE}, \n    {0x70, 0x77, 0x00, 0x0E}, \n    {0x70, 0x07, 0xEE, 0x00}\n    };\n\n// The bitmaps for the main blocks\nstatic const int blocks[7] PROGMEM = {\n  0x4444, 0x44C0, \n  0x4460, 0x0660, \n  0x06C0, 0x0E40, \n  0x0C60};\n\n// The bitmaps for blocks on the screen\nstatic const byte  blockout[16] PROGMEM = {\n  0xF8, 0x00, 0x3E, 0x80, \n  0x0F, 0xE0, 0x03, 0xF8, \n  0x3E, 0x80, 0x0F, 0xE0, \n  0x03, 0xF8, 0x3E, 0x00};\n\n// The bitmaps for ghost blocks on the screen\nstatic const byte  ghostout[16] PROGMEM = {\n  0x88, 0x00, 0x22, 0x80, \n  0x08, 0x20, 0x02, 0x88, \n  0x22, 0x80, 0x08, 0x20, \n  0x02, 0x88, 0x22, 0x00};\n\n// Decode lookup to translate block positions to the 8 columns on the screen\nstatic const byte startDecode[11] PROGMEM = {0,1,1,2,3,4,4,5,6,7,8};\nstatic const byte endDecode[11] PROGMEM =   {1,2,3,3,4,5,6,6,7,8,8};\n\n// Function prototypes - generic ones I use in all games\nvoid doNumber (int x, int y, int value);\nvoid beep(int,int);\n\n// Function prototypes - screen control modified from https://bitbucket.org/tinusaur/ssd1306xled\nvoid ssd1306_init(void);\nvoid ssd1306_xfer_start(void);\nvoid ssd1306_xfer_stop(void);\nvoid ssd1306_send_byte(uint8_t byte);\nvoid ssd1306_send_command(uint8_t command);\nvoid ssd1306_send_data_start(void);\nvoid ssd1306_send_data_stop(void);\nvoid ssd1306_setpos(uint8_t x, uint8_t y);\nvoid ssd1306_fillscreen(uint8_t fill_Data);\nvoid ssd1306_char_f8x8(uint8_t x, uint8_t y, const char ch[]);\n\n// Function prototypes - tetris-specific\nvoid playTetris(void);\nvoid handleInput(void);\n\nvoid drawScreen(int startCol, int endCol, int startRow, int endRow, byte mode);\nvoid drawScreenBorder(void);\n\nbyte readBlockArray(byte x, byte y);\nvoid writeblockArray(byte x, byte y, bool value);\nbyte readGhostArray(byte x, byte y);\nvoid writeGhostArray(byte x, byte y, bool value);\nvoid fillGrid(byte value, bool mode);\n\nvoid rotatePiece(void);\nbool movePieceDown(void);\nvoid movePieceLeft(void);\nvoid movePieceRight(void);\nbyte checkCollision(void);\n\nbool createGhost(void);\nvoid drawGhost(byte action);\nvoid loadPiece(byte pieceNumber, byte row, byte column);\nvoid drawPiece(byte action);\nvoid setNextBlock(byte pieceNumber);\n\n// Variables \nstruct pieceSpace {\n  byte blocks[4][4];\n  int row;\n  int column;\n};\n\npieceSpace currentPiece = {0};  // The piece in play\npieceSpace oldPiece = {0};      // Buffer to hold the current piece whilst its manipulated\npieceSpace ghostPiece = {0};    // Current ghost piece\n\nunsigned long moveTime = 0;     // Baseline time for current move\nunsigned long keyTime = 0;      // Baseline time for current keypress\n\nbyte keylock = 0;               // Holds the mode of the last keypress (for debounce and stuff)\n\nbyte nextBlockBuffer[8][2];     // The little image of the next block \nbyte nextPiece = 0;             // The identity of the next piece\nbyte blockArray[HORIZ][3];      // The byte-array of blocks\nbyte ghostArray[HORIZ][3];      // The byte-array of ghost pieces\nbool stopAnimate;               // True when the game is running\n\nint lastGhostRow = 0;           // Buffer to hold previous ghost position - for accurate drawing\nint score = 0;                  // Score buffer\nint topScore = 0;               // High score buffer\n\nbool challengeMode = 0;         // Is the system in \"Hard\" mode?\nbool ghost = 1;                 // Is the ghost active?\n\nint level = 0;                  // Current level (increments once per cleared line)\n\nvoid doNumber (int x, int y, int value) {\n  char temp[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\n  itoa(value, temp, 10);\n  ssd1306_char_f8x8(x, y, temp);\n}\n\nvoid beep(int bCount,int bDelay){\n for (int i = 0; i<=bCount; i++){digitalWrite(1,HIGH);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}digitalWrite(1,LOW);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}}\n}\n\nvoid ssd1306_char_f8x8(uint8_t x, uint8_t y, const char ch[]) {\n  uint8_t c, i, j = 0;\n\n  while (ch[j] != '\\0')\n  {\n    c = ch[j] - 32; // to space\n    if (c > 0) c = c - 12; // to dash\n    if (c > 15) c = c - 7; \n    if (c > 40) c = c - 6;\n\n    ssd1306_setpos(y, x);\n    ssd1306_send_data_start();\n    for (byte lxn = 0; lxn < 8; lxn++) {    \n      ssd1306_send_byte(pgm_read_byte(&font[c][7-lxn]));      \n      }\n    ssd1306_send_data_stop();\n    x+= 1;\n    j++;\n  }\n}\n\n// Interrupt handlers - to make sure every button press is caught promptly!\nISR(PCINT0_vect) { // PB0 pin button interrupt\n  if (keylock == 0) {\n    keylock = 1;\n    keyTime = millis();\n    }\n}\nvoid playerIncTetris(){ // PB2 pin button interrupt\n  if (keylock == 0) {\n    keylock = 2;\n    keyTime = millis();\n    }\n}\n\n// Screen control functions\nvoid ssd1306_init(void) {\n  DDRB |= (1 << SSD1306_SDA); // Set port as output\n  DDRB |= (1 << SSD1306_SCL); // Set port as output\n\n  ssd1306_send_command(0xAE); // display off\n  ssd1306_send_command(0x00); // Set Memory Addressing Mode\n  ssd1306_send_command(0x10); // 00,Horizontal Addressing Mode;01,VERTDRAWical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid\n  ssd1306_send_command(0x40); // Set Page Start Address for Page Addressing Mode,0-7\n  ssd1306_send_command(0x81); // Set COM Output Scan Direction\n  ssd1306_send_command(0xCF); // ---set low column address\n  ssd1306_send_command(0xA1); // ---set high column address\n  ssd1306_send_command(0xC8); // --set start line address\n  ssd1306_send_command(0xA6); // --set contrast control register\n  ssd1306_send_command(0xA8);\n  ssd1306_send_command(0x3F); // --set segment re-map 0 to 127\n  ssd1306_send_command(0xD3); // --set normal display\n  ssd1306_send_command(0x00); // --set multiplex ratio(1 to 64)\n  ssd1306_send_command(0xD5); //\n  ssd1306_send_command(0x80); // 0xa4,Output follows RAM content;0xa5,Output ignores RAM content\n  ssd1306_send_command(0xD9); // -set display offset\n  ssd1306_send_command(0xF1); // -not offset\n  ssd1306_send_command(0xDA); // --set display clock divide ratio/oscillator frequency\n  ssd1306_send_command(0x12); // --set divide ratio\n  ssd1306_send_command(0xDB); // --set pre-charge period\n  ssd1306_send_command(0x40); //\n  ssd1306_send_command(0x20); // --set com pins hardware configuration\n  ssd1306_send_command(0x02);\n  ssd1306_send_command(0x8D); // --set vcomh\n  ssd1306_send_command(0x14); // 0x20,0.77xVcc\n  ssd1306_send_command(0xA4); // --set DC-DC enable\n  ssd1306_send_command(0xA6); //\n  ssd1306_send_command(0xAF); // --turn on oled panel\n}\n\nvoid ssd1306_xfer_start(void) {\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n}\n\nvoid ssd1306_xfer_stop(void) {\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n}\n\nvoid ssd1306_send_byte(uint8_t byte) {\n  uint8_t i;\n  for (i = 0; i < 8; i++)\n  {\n    if ((byte << i) & 0x80)\n      DIGITAL_WRITE_HIGH(SSD1306_SDA);\n    else\n      DIGITAL_WRITE_LOW(SSD1306_SDA);\n\n    DIGITAL_WRITE_HIGH(SSD1306_SCL);\n    DIGITAL_WRITE_LOW(SSD1306_SCL);\n  }\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);\n  DIGITAL_WRITE_LOW(SSD1306_SCL);\n}\n\nvoid ssd1306_send_command(uint8_t command) {\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  // Slave address, SA0=0\n  ssd1306_send_byte(0x00);  // write command\n  ssd1306_send_byte(command);\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_send_data_start(void) {\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);\n  ssd1306_send_byte(0x40);  //write data\n}\n\nvoid ssd1306_send_data_stop(void) {\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_setpos(uint8_t x, uint8_t y)\n{\n  if (y > 7) return;\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  //Slave address,SA0=0\n  ssd1306_send_byte(0x00);  //write command\n\n  ssd1306_send_byte(0xb0 + y);\n  ssd1306_send_byte(((x & 0xf0) >> 4) | 0x10); // |0x10\n  ssd1306_send_byte((x & 0x0f) | 0x01); // |0x01\n\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_fillscreen(uint8_t fill_Data) {\n  uint8_t m, n;\n  for (m = 0; m < 8; m++)\n  {\n    ssd1306_send_command(0xb0 + m); //page0-page1\n    ssd1306_send_command(0x00);   //low column start address\n    ssd1306_send_command(0x10);   //high column start address\n    ssd1306_send_data_start();\n    for (n = 0; n < 128; n++)\n    {\n      ssd1306_send_byte(fill_Data);\n    }\n    ssd1306_send_data_stop();\n  }\n}\n\n// Sleep code from http://www.re-innovation.co.uk/web12/index.php/en/blog-75/306-sleep-modes-on-attiny85\nvoid system_sleep() {\n  ssd1306_fillscreen(0x00);\n  ssd1306_send_command(0xAE);\n  cbi(ADCSRA,ADEN);                    // switch Analog to DigitalconVERTDRAWer OFF\n  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here\n  sleep_enable();\n  sleep_mode();                        // System actually sleeps here\n  sleep_disable();                     // System continues execution here when watchdog timed out \n  sbi(ADCSRA,ADEN);                    // switch Analog to DigitalconVERTDRAWer ON  \n  ssd1306_send_command(0xAF);\n}\n\n// Arduino stuff\nvoid setup() {\n  DDRB = 0b00000010;    // set PB1 as output (for the speaker)\n  PCMSK = 0b00000001;   // pin change mask: listen to portb bit 1\n  GIMSK |= 0b00100000;  // enable PCINT interrupt\n  sei();                // enable all interrupts\n  ssd1306_init();       // initialise the screen\n  keylock = 0;\n}\n\nvoid loop() {\n  ssd1306_init();\n  ssd1306_fillscreen(0x00);\n\n  ssd1306_char_f8x8(0, 88,\" ------ \");\n  ssd1306_char_f8x8(0, 80,\" TETRIS \");\n  ssd1306_char_f8x8(0, 72, \" ------ \");\n  ssd1306_char_f8x8(0, 64, \" Attiny \");\n  ssd1306_char_f8x8(0, 56, \" Arcade \");\n  ssd1306_char_f8x8(0, 48, \" ------ \");\n\n  long startT = millis();\n  long nowT =0;\n  boolean sChange = 0;\n  while(digitalRead(0) == HIGH) {\n    nowT = millis();\n    if (nowT - startT > 2000) {\n      sChange = 1;     \n      if (digitalRead(2) == HIGH) {\n        if (challengeMode == 0) { \n          challengeMode = 1; \n          ssd1306_char_f8x8(0, 16, \"  HARD \"); \n          ssd1306_char_f8x8(0, 8, \"  MODE \"); \n        } else { \n          challengeMode = 0; \n          ssd1306_char_f8x8(0, 16, \" NORMAL\"); \n          ssd1306_char_f8x8(0, 8, \"  MODE \"); \n        }\n      } else if (ghost == 0) { \n        ghost = 1; \n        ssd1306_char_f8x8(0, 16, \" GHOST \"); \n        ssd1306_char_f8x8(0, 8, \"  ON   \"); \n      } else { \n        ghost = 0; \n        ssd1306_char_f8x8(0, 16, \" GHOST \"); \n        ssd1306_char_f8x8(0, 8, \"  OFF  \"); \n      }    \n      break;\n    }\n    if (sChange == 1) break;\n  }  \n  while(digitalRead(0) == HIGH);\n  if (sChange == 0) {\n    delay(2500);\n    ssd1306_fillscreen(0x00);\n    playTetris();\n  }\n  delay(1000);\n  system_sleep();\n}\n\n\nbyte readBlockArray(byte x, byte y) {\n    if (y < 8) {\n      return ((blockArray[x][0] & B00000001 << y) >> y);\n    } else if (y > 15) {\n      return ((blockArray[x][2] & B00000001 << y-15) >> y-15);\n    } else {\n      return ((blockArray[x][1] & B00000001 << y-8) >> y-8);\n    }   \n}\n\nvoid writeblockArray(byte x, byte y, bool value) {\n    byte arr = 0;\n    if (y<8) {\n      // do nothing \n    } else if (y > 15) {\n      arr = 2;\n      y-=15;\n    } else  {\n      arr = 1;\n      y-=8;\n    }  \n    if (value == 1) blockArray[x][arr] |= B00000001 << y; else blockArray[x][arr] &= (B11111110 << y) | (B01111111 >> 7-y);\n}\n\nbyte readGhostArray(byte x, byte y) {\n    if (y < 8) {\n      return ((ghostArray[x][0] & B00000001 << y) >> y);\n    } else if (y > 15) {\n      return ((ghostArray[x][2] & B00000001 << y-15) >> y-15);\n    } else {\n      return ((ghostArray[x][1] & B00000001 << y-8) >> y-8);\n    }   \n}\n\nvoid writeGhostArray(byte x, byte y, bool value) {\n    byte arr = 0;\n    if (y<8) {\n      // do nothing\n    } else if (y > 15) {\n      arr = 2;\n      y-=15;\n    } else  {\n      arr = 1;\n      y-=8;\n    }  \n    if (value == 1) ghostArray[x][arr] |= B00000001 << y; else ghostArray[x][arr] &= (B11111110 << y) | (B01111111 >> 7-y);\n}\n\nvoid fillGrid(byte value, bool mode) {\n  for (char r = 0; r < VERTMAX; r++) {\n    for (char c = 0; c < HORIZ; c++) {\n      if (mode == GHOST) writeGhostArray(c,r, value); else writeblockArray(c,r, value);\n    }\n  }\n}\n\nvoid rotatePiece(void) {\n  byte blocks[4][4];\n\n  memcpy(oldPiece.blocks, currentPiece.blocks, 16);\n  oldPiece.row = currentPiece.row;\n  oldPiece.column = currentPiece.column;\n\n  for (byte i = 0; i < 4; ++i) {\n    for (byte j = 0; j < 4; ++j) {\n      blocks[j][i] = currentPiece.blocks[4 - i - 1][j];\n    }\n  }\n  oldPiece = currentPiece;\n  memcpy(currentPiece.blocks, blocks, 16);\n  if (checkCollision()) currentPiece = oldPiece; else {\n    drawGhost(ERASE);\n    if (createGhost()) drawGhost(DRAW);\n    }\n}\n\nbool movePieceDown(void) {\n  int rndPiece = 0;\n\n  memcpy(oldPiece.blocks, currentPiece.blocks, 16);\n  oldPiece.row = currentPiece.row;\n  oldPiece.column = currentPiece.column;\n\n  currentPiece.row--;\n\n  //check collision\n  if (checkCollision()) {\n    currentPiece.row = oldPiece.row;\n    drawPiece(DRAW);\n    byte totalRows = 0;\n    \n    for (byte row = 0; row < VERTMAX; row++) { // scan the whole block (it's quick - there's no drawing to do)\n      bool rowFull = 1;\n      for (byte col = 0; col < HORIZ; col++) { // scan across this row - every column\n        if (readBlockArray(col,row) == 0) rowFull = 0; // if we hit any blank spaces, the row's not full\n      }\n      if (rowFull) {\n        totalRows++;\n        for (int i = 800; i>200; i = i - 200)beep(30,i); // happy sound\n        for (byte col = 0; col < HORIZ; col++) writeblockArray(col,row,0); // write zeros across this whole row\n        drawGameScreen(0,HORIZ-1,row,row+1,PARTIAL); // draw the row we're removing (for animation)\n        delay(30); // delay slightly to make the deletion of rows visible\n        for (byte dropCol = 0; dropCol < HORIZ; dropCol++) { // for every column\n          for (byte dropRow = row; dropRow < VERTMAX-1; dropRow ++) writeblockArray(dropCol,dropRow,readBlockArray(dropCol,dropRow+1)); // drop everything down as many as the row's we've cleared\n        }\n        row--; // we need to check this row again as it could now have things in it!\n      }\n    }\n    level += totalRows;\n    switch (totalRows) {\n      case 1:   score += 40; break;\n      case 2:   score += 100; break;\n      case 3:   score += 300; break;\n      case 4:   score += 800; \n    }\n    drawGameScreen(0,10, 0,VERTDRAW,FULL); \n    loadPiece(nextPiece, STARTY, STARTX);\n    if (checkCollision()) {\n      stopAnimate = true;\n    } else {\n      loadPiece(nextPiece, STARTY, STARTX);\n      drawGhost(ERASE);\n      if (createGhost()) drawGhost(DRAW);\n    }\n    nextPiece = random(1, 8);\n    setNextBlock(nextPiece);\n  }\n  drawGhost(ERASE);\n  if (createGhost()) drawGhost(DRAW);\n}\n\nvoid movePieceLeft(void) {\n  byte response;\n \n  oldPiece = currentPiece;\n  currentPiece.column = currentPiece.column - 1;\n\n  response = checkCollision();\n\n  if (response == 1) {\n    currentPiece = oldPiece; // back to where it was\n  } else if (response == 2) {\n    int wide = 0;\n    for (byte i = 0;i<4;i++) {\n      if (currentPiece.blocks[3][i]) wide = 1;\n    }\n    boolean narrow = true;\n    for (byte i = 0;i<4;i++) {\n      if (currentPiece.blocks[2][i]) narrow = false;\n    }\n    if (narrow) wide = -1;\n    currentPiece.column = 7-wide;\n    response = checkCollision(); // Check again - does wrapping around cause a collision?\n    if (response == 1) {\n      currentPiece = oldPiece; // back to where it was\n    } else {\n      drawGhost(ERASE);\n      if (createGhost()) drawGhost(DRAW);\n      drawGameScreen(0,10,0,VERTDRAW,FULL); \n    }\n  } else {\n    drawGhost(ERASE);\n    if (createGhost()) drawGhost(DRAW);\n  }\n}\n\nvoid movePieceRight(void) {\n  oldPiece = currentPiece;\n  currentPiece.column = currentPiece.column + 1;\n  //check collision\n  if (checkCollision()) \t{\n    currentPiece = oldPiece; // back to where it was\n  } else {\n    drawGhost(ERASE);\n    if (createGhost()) drawGhost(DRAW);\n  }\n}\n\nbyte checkCollision(void) {\n  byte pieceRow = 0;\n  byte pieceColumn = 0;\n\n  for (int c = currentPiece.column; c < currentPiece.column + 4; c++) {\n    for (int r = currentPiece.row; r < currentPiece.row + 4; r++) {\n      if (currentPiece.blocks[pieceColumn][pieceRow]) {\n        if (c < 0) return 2;\n        if (c > 9) return 1;\n        if (r < 0) return 1;\n        if (c >= 0 && r >= 0 && c < HORIZ && r < VERTMAX) {\n          if (readBlockArray(c,r)) {\n            return 1; //is it on landed blocks?\n          }\n        }\n      }\n      pieceRow++;\n    }\n    pieceRow = 0;\n    pieceColumn++;\n  }\n  return 0;\n}\n\nvoid handleInput(void) {\n  if (digitalRead(2) == HIGH && keylock == 2 && millis() - keyTime > 300) {\n    while (digitalRead(2) == HIGH) {\n      drawPiece(ERASE);\n      movePieceDown();\n      drawPiece(DRAW);\n      drawGameScreen(currentPiece.column, currentPiece.column + 4, currentPiece.row, currentPiece.row+5,PARTIAL);         \n      delay(10);\n      if (stopAnimate) return;\n    }\n    keylock = 0;\n  }\n  \n  if (digitalRead(0) == HIGH && (keylock == 1 || keylock == 3) && millis() - keyTime > 200) {\n    drawPiece(ERASE);\n    movePieceRight();\n    drawPiece(DRAW);\n    drawGameScreen(currentPiece.column-1, currentPiece.column + 4, currentPiece.row, currentPiece.row+4,PARTIAL);         \n    keyTime = millis() + 100;\n    keylock = 3;\n  }\n\n  if (digitalRead(0) == LOW && digitalRead(2) == LOW) {\n    if (keylock == 2  && millis() - keyTime < 300) {\n      drawPiece(ERASE);\n      rotatePiece();\n      drawPiece(DRAW);\n      drawGameScreen(currentPiece.column, currentPiece.column + 4, currentPiece.row, currentPiece.row+4,PARTIAL);         \n    } else if (keylock == 1) {\n    drawPiece(ERASE);\n    movePieceLeft();\n    drawPiece(DRAW);\n    drawGameScreen(currentPiece.column, currentPiece.column + 5, currentPiece.row, currentPiece.row+4, PARTIAL);         \n    }\n    keylock = 0;\n  }\n  delay(30);\n}\n\nvoid setNextBlock(byte pieceNumber) {\n  memset(nextBlockBuffer, 0, sizeof nextBlockBuffer); //clear buffer\n  pieceNumber--;\n  if (pieceNumber == 0) {\n      for (int k = 2; k < 6; k++) {\n        nextBlockBuffer[k][0] = pgm_read_byte(&miniBlock[pieceNumber][0]);\n        nextBlockBuffer[k][1] = pgm_read_byte(&miniBlock[pieceNumber][0]);\n      }\n  \n  } else {  \n      for (int k = 0; k < 3; k++) {\n        nextBlockBuffer[k][0] = pgm_read_byte(&miniBlock[pieceNumber][0]);\n        nextBlockBuffer[k][1] = pgm_read_byte(&miniBlock[pieceNumber][1]);\n      }\n      for (int k = 4; k < 7; k++) {\n        nextBlockBuffer[k][0] = pgm_read_byte(&miniBlock[pieceNumber][2]);\n        nextBlockBuffer[k][1] = pgm_read_byte(&miniBlock[pieceNumber][3]);\n      }\n  }\n  drawGameScreen(0,10,0,VERTDRAW, FULL);\n}\n\nvoid drawScreenBorder(void) {\n    ssd1306_setpos(0, 0);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(0xFF);  \n    for (byte c = 1; c < 126; c++) {\n      ssd1306_send_byte(B00000001);  \n    }\n    ssd1306_send_byte(0xFF);  \n    ssd1306_send_data_stop();  \n    \n    for (byte r = 1; r < 7; r++) {\n    ssd1306_setpos(0, r);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(0xFF);        \n    for (byte c = 1; c < 126; c++) {\n        ssd1306_send_byte(B00000000);  \n    }    \n    ssd1306_send_byte(0xFF);        \n    }\n    ssd1306_send_data_stop();  \n\n    ssd1306_setpos(0, 7);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(0xFF);  \n    for (byte c = 1; c < 126; c++) {\n      ssd1306_send_byte(B10000000);  \n    }\n    ssd1306_send_byte(0xFF);  \n    ssd1306_send_data_stop();  \n}\n\nvoid displayScore(int score, int xpos, int y, bool blank) {\n  byte scoreOut[6];\n  scoreOut[5] = (score % 10);\n  scoreOut[4] = ((score / 10) % 10);\n  scoreOut[3] = ((score / 100) % 10);\n  scoreOut[2] = ((score / 1000) % 10);\n  scoreOut[1] = ((score / 10000) % 10);\n  scoreOut[0] = ((score / 100000) % 10);\n\n  for (byte x = xpos; x<xpos+6; x++) {\n    ssd1306_setpos(y, x);\n    ssd1306_send_data_start();\n    for (byte lxn = 0; lxn < 8; lxn++) {    \n      if (blank) ssd1306_send_byte(0); else ssd1306_send_byte(pgm_read_byte(&font[4+scoreOut[x-xpos]][7-lxn]));      \n    }\n    ssd1306_send_data_stop();\n  }\n}\n\nvoid drawGameScreen(int startCol, int endCol, int startRow, int endRow, byte mode) {\n  drawScreen(startCol, endCol, startRow, endRow, mode);\n\n  if (mode == PARTIAL) {\n    if (ghostPiece.row < lastGhostRow) { // ghost has moved down :)\n      drawScreen(startCol, endCol, ghostPiece.row, lastGhostRow + 4, mode) ;  \n    } else { // ghost has moved up (presumably!)\n      drawScreen(startCol, endCol, lastGhostRow, ghostPiece.row + 4, mode) ;  \n    }\n    \n  }\n}\n\nvoid drawScreen(int startCol, int endCol, int startRow, int endRow, byte mode) {\n  byte temp = 0;\n  byte separator = 0;\n  byte scoreOut[6];\n  byte reader = 0;\n  byte blockReader = 0;\n  \n  if(startCol < 0) startCol = 0;\n  if(endCol > 10) endCol = 10;\n  if(startRow < 0) startRow = 0;\n  if(endRow > VERTDRAW) endRow = VERTDRAW;\n  \n  byte startScreenCol = pgm_read_byte(&startDecode[startCol]);\n  byte endScreenCol = pgm_read_byte(&endDecode[endCol]);\n  \n  scoreOut[5] = (score % 10);\n  scoreOut[4] = ((score / 10) % 10);\n  scoreOut[3] = ((score / 100) % 10);\n  scoreOut[2] = ((score / 1000) % 10);\n  scoreOut[1] = ((score / 10000) % 10);\n  scoreOut[0] = ((score / 100000) % 10);\n\n    for (byte col = startScreenCol; col < endScreenCol; col++) {\n    if (col < 4) reader = col; else if (col < 7) reader = col+1; else reader = col + 2;\n    blockReader = 2 * col;\n    ssd1306_setpos(startRow*6, col); // Start from the end of this column (working up the screen) on the required row\n    ssd1306_send_data_start(); \n    if (startRow == 0) ssd1306_send_byte(B11111111); else {\n      if (col == 0) ssd1306_send_byte(B00000001); else if (col == 7) ssd1306_send_byte(B10000000); else ssd1306_send_byte(B00000000);\n    }\n    for (byte r = startRow; r < endRow; r++ ) { // For each row in the array of tetris blocks\n      for (byte piece = 0; piece < 5; piece ++) { // for each of the 5 filled lines of the block\n        if (col == 0) temp = B00000001; else if (col == 7) temp = B10000000; else temp = 0x00; // if we're on the far left, draw the left wall, on the far right draw the right wall, otherwise its a blank separator between blocks\n        separator = temp; // we'll need this again later! \n\n        if (readBlockArray(reader,r)) { \n          temp = temp | pgm_read_byte(&blockout[blockReader]);\n        }\n        if (readBlockArray(reader+1,r)) { \n          temp = temp | pgm_read_byte(&blockout[blockReader+1]);\n        }\n\n        if(ghost) {\n          if (readGhostArray(reader,r) && (piece == 0 || piece == 4)) { \n            temp = temp | pgm_read_byte(&blockout[blockReader]);\n          } else if (readGhostArray(reader,r)) { \n            temp = temp | pgm_read_byte(&ghostout[blockReader]);\n          }\n                \n          if (readGhostArray(reader+1,r) && (piece == 0 || piece == 4)) { \n            temp = temp | pgm_read_byte(&blockout[blockReader+1]);\n          } else if (readGhostArray(reader+1,r)) { \n            temp = temp | pgm_read_byte(&ghostout[blockReader+1]);\n          }\n        }\n        ssd1306_send_byte(temp);          \n      }\n      ssd1306_send_byte(separator); // between blocks - same one as we used at the start\n    }    \n    if (mode == FULL) if (col < 6) for (byte numline = 0; numline < 8; numline++) ssd1306_send_byte(pgm_read_byte(&font[scoreOut[col]+4][7-numline])); else for (byte blockline = 0; blockline < 8; blockline++) ssd1306_send_byte(nextBlockBuffer[blockline][col-6]);\n    ssd1306_send_data_stop(); \n  }\n}\n\nbool createGhost(void) {\n  byte tempRow = currentPiece.row;\n\n  if (currentPiece.row < 3) return 0;\n\n  currentPiece.row-=2;\n  while(checkCollision() == 0) currentPiece.row--;\n\n  memcpy(ghostPiece.blocks, currentPiece.blocks, 16);\n  ghostPiece.row = currentPiece.row+1;\n  ghostPiece.column = currentPiece.column;\n  currentPiece.row = tempRow;\n  \n  if (ghostPiece.row > currentPiece.row - 3) return 0; else return 1;\n}\n\nvoid loadPiece(byte pieceNumber, byte row, byte column) {\n  byte incr = 0;\n\n  pieceNumber--;\n  \n  for (byte lxn = 0; lxn < 4; lxn++) {\n    for (byte lxn2 = 0; lxn2 < 4; lxn2++) {\n      if ( ((1 << incr) & pgm_read_word(&blocks[pieceNumber])) >> incr == 1) {\n        currentPiece.blocks[lxn][lxn2] = 1;                \n      } else currentPiece.blocks[lxn][lxn2] = 0;\n      incr++;\n    }\n  }\n  currentPiece.row = row;\n  currentPiece.column = column;\n}\n\nvoid drawPiece(byte action) {\n  for (byte lxn = 0; lxn < 4; lxn++) {\n    for (byte lxn2 = 0; lxn2 < 4; lxn2++) {\n      if (currentPiece.blocks[lxn][lxn2] == 1) {\n        if (action == DRAW) writeblockArray(currentPiece.column + lxn,currentPiece.row + lxn2,1); else if (action == ERASE) writeblockArray(currentPiece.column + lxn,currentPiece.row + lxn2,0);                \n      }\n    }\n  }\n}\n\nvoid drawGhost(byte action) {\n  for (byte lxn = 0; lxn < 4; lxn++) {\n    for (byte lxn2 = 0; lxn2 < 4; lxn2++) {\n      if (ghostPiece.blocks[lxn][lxn2] == 1) {\n        if (action == DRAW) writeGhostArray(ghostPiece.column + lxn,ghostPiece.row + lxn2,1); else if (action == ERASE) {writeGhostArray(ghostPiece.column + lxn,ghostPiece.row + lxn2,0); lastGhostRow = ghostPiece.row; }                \n      }\n    }\n  }\n}\n\nvoid playTetris(void) {\n  stopAnimate = 0;\n  score = 0;\n\n  fillGrid(0, NORMAL);\n  fillGrid(0, GHOST);\n\n  // Attach the interrupt to read key 2\n  attachInterrupt(0,playerIncTetris,RISING);\n\n  loadPiece(random(1, 8), STARTY, STARTX);\n  drawPiece(DRAW);\n  if (createGhost()) drawGhost(DRAW);\n  drawGhost(DRAW);\n  nextPiece = random(1, 8);\n  setNextBlock(nextPiece);\n  \n  // Fill up the screen with random crap if it's in challenge mode!\n  if (challengeMode) {\n    for (byte cl = 0; cl < 100; cl++) {\n      drawPiece(ERASE);\n      movePieceDown();\n      if (random(1,8) >4) movePieceLeft();\n      drawPiece(DRAW);      \n    }\n  } \n\n  // Reset the level\n  level = STARTLEVEL;\n  \n  drawGameScreen(0,10,0,VERTDRAW, FULL); \n\n  while (stopAnimate == 0) {\n    drawPiece(ERASE);\n    movePieceDown();\n    drawPiece(DRAW);\n    drawGameScreen(currentPiece.column, currentPiece.column + 4, currentPiece.row, currentPiece.row+5, PARTIAL);         \n    moveTime = millis();\n    if (level * LEVELFACTOR > DROPDELAY) level = DROPDELAY / LEVELFACTOR;\n    while ((millis() - moveTime) < (DROPDELAY - level* LEVELFACTOR)) {\n      handleInput();\n    }\n  }\n\n  ssd1306_fillscreen(0x00);\n\n  bool newHigh = false;\n  topScore = EEPROM.read(0);\n  topScore = topScore << 8;\n  topScore = topScore |  EEPROM.read(1);\n  \n  if (score > topScore) { \n    topScore = score;\n    EEPROM.write(1,score & 0xFF); \n    EEPROM.write(0,(score>>8) & 0xFF);\n    newHigh = true; \n  }\n  drawScreenBorder();\n\n  displayScore(score, 1,80,0);\n  displayScore(topScore, 1,40,0);\n   for (int i = 0; i<1000; i = i+ 50){\n    beep(50,i);\n    }\n  for (byte lx = 0; lx<4;lx++) {\n    displayScore(score, 1,80,1);    \n    if (newHigh) displayScore(topScore, 1,40,1);\n    delay(200);\n    displayScore(score, 1,80,0);    \n    if (newHigh) displayScore(topScore, 1,40,0);\n    delay(200);\n  }\n}\r\n"
  },
  {
    "path": "Tetris_Attiny_Arcade/font8x8AJ.h",
    "content": "/*\n * This font is from http://arduino-er.blogspot.co.uk/2014/08/port-ascii-font-to-arduino-88-led-matrix.html\n *  \n * Source code adapted by @andyhighnumber from that available at: https://bitbucket.org/tinusaur/ssd1306xled\n *\n */\n\n// ----------------------------------------------------------------------------\n\n#include <avr/pgmspace.h>\n\n// ----------------------------------------------------------------------------\n\nstatic const byte font[][8] PROGMEM = {\n    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0020 (space)\n    { 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00},   // U+002D (-)\n    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00},   // U+002E (.)\n    { 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00},   // U+002F (/)\n    { 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00},   // U+0030 (0)\n    { 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00},   // U+0031 (1)\n    { 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00},   // U+0032 (2)\n    { 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00},   // U+0033 (3)\n    { 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00},   // U+0034 (4)\n    { 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00},   // U+0035 (5)\n    { 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00},   // U+0036 (6)\n    { 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00},   // U+0037 (7)\n    { 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00},   // U+0038 (8)\n    { 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00},   // U+0039 (9)\n    { 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00},   // U+0041 (A)\n    { 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00},   // U+0042 (B)\n    { 0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00},   // U+0043 (C)\n    { 0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00},   // U+0044 (D)\n    { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00},   // U+0045 (E)\n    { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00},   // U+0046 (F)\n    { 0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00},   // U+0047 (G)\n    { 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00},   // U+0048 (H)\n    { 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},   // U+0049 (I)\n    { 0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00},   // U+004A (J)\n    { 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00},   // U+004B (K)\n    { 0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00},   // U+004C (L)\n    { 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00},   // U+004D (M)\n    { 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00},   // U+004E (N)\n    { 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00},   // U+004F (O)\n    { 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00},   // U+0050 (P)\n    { 0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00},   // U+0051 (Q)\n    { 0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00},   // U+0052 (R)\n    { 0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00},   // U+0053 (S)\n    { 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},   // U+0054 (T)\n    { 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00},   // U+0055 (U)\n    { 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00},   // U+0056 (V)\n    { 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00},   // U+0057 (W)\n    { 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00},   // U+0058 (X)\n    { 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00},   // U+0059 (Y)\n    { 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00},   // U+005A (Z)\n    { 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00},   // U+0061 (a)\n    { 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00},   // U+0062 (b)\n    { 0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00},   // U+0063 (c)\n    { 0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00},   // U+0064 (d)\n    { 0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00},   // U+0065 (e)\n    { 0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00},   // U+0066 (f)\n    { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F},   // U+0067 (g)\n    { 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00},   // U+0068 (h)\n    { 0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},   // U+0069 (i)\n    { 0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E},   // U+006A (j)\n    { 0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00},   // U+006B (k)\n    { 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},   // U+006C (l)\n    { 0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00},   // U+006D (m)\n    { 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00},   // U+006E (n)\n    { 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00},   // U+006F (o)\n    { 0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F},   // U+0070 (p)\n    { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78},   // U+0071 (q)\n    { 0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00},   // U+0072 (r)\n    { 0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00},   // U+0073 (s)\n    { 0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00},   // U+0074 (t)\n    { 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00},   // U+0075 (u)\n    { 0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00},   // U+0076 (v)\n    { 0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00},   // U+0077 (w)\n    { 0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00},   // U+0078 (x)\n    { 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F},   // U+0079 (y)\n    { 0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00},   // U+007A (z)\n};\n\n\n// ----------------------------------------------------------------------------\n\r\n"
  },
  {
    "path": "Tetris_Multi_Button/Tetris_Multi_Button.ino",
    "content": "/* 2015 / 2016 /2017\n   Tetris for Attiny Arcade\n   ========================\n\n   Before the game starts:\n   =======================\n   Hold \"DROP\" BUTTON - Turns 'ghost' piece on and off\n   Hold \"DROP\" and \"ROTATE\" together - Turns 'challenge mode' on and off (which fills the screens with random stuff at the start of the game to make\n   it more tricky!)\n\n   _________________________________________________________________________________________________________________________________________________________\n   This version developed by Andy Jackson - Twitter @andyhighnumber - Tweet me if you have any problems getting this to compile or run.\n   The code that does not fall under the licenses of sources listed below can be used non-commercially with or without attribution.\n   This software is supplied without warranty of any kind.\n\n   This code is designed to run on (very simple and cheap to build) custom hardware and you should find a schematic for the circuit in the folder where you \n   found this file. Because the voltages of the switches are important, it's good to insulate the back of the board from fingers if you can (I use hot melt\n   glue but other methods would work - ideally put it in a case!)\n   \n   Designed originally for the Attiny85 and optimised for the #AttinyArcade platform. The source code is less than 8KB and the sketch\n   should run happily with less than 300 bytes of RAM. You can find out more about this platform from http://webboggles.com/, buy kits\n   to make it (or get instructions / schematics). This sketch includes some code from the #AttinyArcade games on that site, including interrupt code. \n\n   This game started life as a port but is now essentially a clone of TinyTetris by Anthony Russell, with some additional features. There remain \n   elements of that original codebase, although the vast majority of what's here has been rewritten from scratch (including the screen, text and number \n   rendering code and much of the game engine) in order to optimise for memory, improve responsiveness and allow new features on the limited hardware \n   (added features include Highscore (saved to EEPROM), optional Ghost (or Shadow) Piece, Interrupt Handling and Hard-Mode functionality).  \n   \n   Anthony's source can be found here: https://github.com/AJRussell/Tiny-Tetris and is highly recommended if you'd like a version\n   of Tetris to run on normal Arduino hardware. It has some lovely graphics by Tobozo (one image from which is now inclded the opening screen here!) and it's \n   also possible that some code by Tobozo has made it into this version. Tobozo's repository can be found here; https://github.com/tobozo and is well worth a look. \n   There is an Instructables page relating to this project here: https://www.instructables.com/id/Tetris-Clone-With-OLED-SSD1306I2C-for-Arduino-Nano/ \n        \n   This sketch is using the screen control and font functions written by Neven Boyanov for the http://tinusaur.wordpress.com/ project\n   Source code and font files available at: https://bitbucket.org/tinusaur/ssd1306xled - hacked about by Andy Jackson to make them \n   render side-on for this game. All the necessary functions are in this file, there's no need to download any additional libraries to compile this game.\n\n   The sleep code in this file is based on this blog post by Matthew Little:\n   http://www.re-innovation.co.uk/web12/index.php/en/blog-75/306-sleep-modes-on-attiny85\n*/\n\n// The custom font file is the only additional file you should need to compile this game\n#include \"font8x8AJ.h\"\n\n// Standard Arduino headers\n#include <EEPROM.h> \n#include <avr/pgmspace.h>\n#include <avr/sleep.h>\n#include <avr/interrupt.h> // needed for the additional interrupt\n\n// Mode settings for functions with multiple purposes\n#define NORMAL 0\n#define GHOST 1\n#define FULL 0\n#define PARTIAL 1\n#define DRAW 0\n#define ERASE 1\n\n// The horizontal width of the playing area\n#define HORIZ 10\n// The vertical visible space of the playing area\n#define VERTDRAW 19\n// The size of the array of blocks (some are outside visible area to allow them to drop in from off screen)\n#define VERTMAX 24\n\n// The horizontal position where pieces begin\n#define STARTX 3\n// The vertical position where pieces begin\n#define STARTY 19\n// What level does the game start on\n#define STARTLEVEL 1\n// The multiplying factor that sets how the speed scales with level (one level increment for every row cleared)\n#define LEVELFACTOR 4\n// The number of milliseconds before each drop (baseline)\n#define DROPDELAY 600\n\n#define DIGITAL_WRITE_HIGH(PORT) PORTB |= (1 << PORT)\n#define DIGITAL_WRITE_LOW(PORT) PORTB &= ~(1 << PORT)\n\n// Routines to set and clear bits (used in the sleep code)\n#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))\n#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))\n\n// Defines for OLED output\n#define SSD1306XLED_H\n#define SSD1306_SCL   PORTB4  // SCL, Pin 4 on SSD1306 Board - for webbogles board\n#define SSD1306_SDA   PORTB3  // SDA, Pin 3 on SSD1306 Board - for webbogles board\n#define SSD1306_SA    0x78  // Slave address\n\n// The bitmaps for the little images of next block\nstatic const byte miniBlock[][4] PROGMEM = {\n    {0x77, 0x77, 0x00, 0x00}, \n    {0x70, 0x77, 0x70, 0x00}, \n    {0x70, 0x00, 0x70, 0x77}, \n    {0x70, 0x07, 0x70, 0x07}, \n    {0x70, 0x07, 0x00, 0xEE}, \n    {0x70, 0x77, 0x00, 0x0E}, \n    {0x70, 0x07, 0xEE, 0x00}\n    };\n\n// The bitmaps for the main blocks\nstatic const int blocks[7] PROGMEM = {\n  0x4444, 0x44C0, \n  0x4460, 0x0660, \n  0x06C0, 0x0E40, \n  0x0C60};\n\n// The bitmaps for blocks on the screen\nstatic const byte  blockout[16] PROGMEM = {\n  0xF8, 0x00, 0x3E, 0x80, \n  0x0F, 0xE0, 0x03, 0xF8, \n  0x3E, 0x80, 0x0F, 0xE0, \n  0x03, 0xF8, 0x3E, 0x00};\n\n// The bitmaps for ghost blocks on the screen\nstatic const byte  ghostout[16] PROGMEM = {\n  0x88, 0x00, 0x22, 0x80, \n  0x08, 0x20, 0x02, 0x88, \n  0x22, 0x80, 0x08, 0x20, \n  0x02, 0x88, 0x22, 0x00};\n\n// Decode lookup to translate block positions to the 8 columns on the screen\nstatic const byte startDecode[11] PROGMEM = {0,1,1,2,3,4,4,5,6,7,8};\nstatic const byte endDecode[11] PROGMEM =   {1,2,3,3,4,5,6,6,7,8,8};\n\n// The  logo on the opening screen - adapted from the original by Tobozo https://github.com/tobozo\nconst byte brickLogo[] PROGMEM= {\n  0x01, 0x01, 0x01, 0x01, 0x81, 0x81, 0xC1, 0xE1, \n  0xF1, 0xF1, 0x01, 0x11, 0xF1, 0xF1, 0xE1, 0xC1, \n  0xC1, 0x81, 0x81, 0x01, 0x01, 0x01, 0x01, 0x01, \n  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, \n  0x01, 0x01, 0x01, 0x01, 0xFC, 0xFC, 0xFE, 0xFF, \n  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, \n  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \n  0xFF, 0xFE, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n  0xFF, 0xFF, 0x7F, 0x3F, 0xBF, 0x9F, 0xCF, 0xEF, \n  0xE7, 0xF7, 0xFB, 0xE0, 0x01, 0xFB, 0xF3, 0xF7, \n  0xE7, 0xEF, 0xCF, 0xDF, 0xDF, 0xBF, 0xBF, 0x30, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, \n  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \n  0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \n  0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x06, 0xFE, 0xFC, \n  0xFC, 0xFC, 0xF8, 0xF8, 0xF0, 0xF0, 0xE0, 0x00, \n  0x00, 0xFF, 0xFF, 0x7F, 0x7F, 0x3F, 0xBF, 0x9F, \n  0xDF, 0xCF, 0xEF, 0xEF, 0xE4, 0x00, 0xF7, 0xE7, \n  0xEF, 0xEF, 0xCF, 0xDF, 0xDF, 0x9F, 0xBF, 0xBF, \n  0x3F, 0x00, 0x07, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF,\n  0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xFC, 0xFE, 0xFE, \n  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \n  0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \n  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x0E, \n  0x3E, 0x1E, 0x1C, 0x1D, 0x0D, 0x09, 0x03, 0x03, \n  0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \n  0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x3F, 0x00, 0x3F, \n  0x3F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, \n  0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, \n  0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x83, 0x83, \n  0x83, 0x89, 0x8D, 0x8D, 0x8C, 0x8E, 0x8E, 0x8E, \n  0x8F, 0x8F, 0x9F, 0x8F, 0x8F, 0x8F, 0x8F, 0x87, \n  0x86, 0x86, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80,\n  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80};\n\n\n// Function prototypes - generic ones I use in all games\nvoid beep(int,int);\n\n// Function prototypes - screen control modified from https://bitbucket.org/tinusaur/ssd1306xled\nvoid ssd1306_init(void);\nvoid ssd1306_xfer_start(void);\nvoid ssd1306_xfer_stop(void);\nvoid ssd1306_send_byte(uint8_t byte);\nvoid ssd1306_send_command(uint8_t command);\nvoid ssd1306_send_data_start(void);\nvoid ssd1306_send_data_stop(void);\nvoid ssd1306_setpos(uint8_t x, uint8_t y);\nvoid ssd1306_fillscreen(uint8_t fill_Data);\nvoid ssd1306_char_f8x8(uint8_t x, uint8_t y, const char ch[]);\n\n// Function prototypes - tetris-specific\nvoid playTetris(void);\nvoid handleInput(void);\n\nvoid drawScreen(int startCol, int endCol, int startRow, int endRow, byte mode);\nvoid drawScreenBorder(void);\n\nbyte readBlockArray(byte x, byte y);\nvoid writeblockArray(byte x, byte y, bool value);\nbyte readGhostArray(byte x, byte y);\nvoid writeGhostArray(byte x, byte y, bool value);\nvoid fillGrid(byte value, bool mode);\n\nvoid rotatePiece(void);\nbool movePieceDown(void);\nvoid movePieceLeft(void);\nvoid movePieceRight(void);\nbyte checkCollision(void);\n\nbool createGhost(void);\nvoid drawGhost(byte action);\nvoid loadPiece(byte pieceNumber, byte row, byte column);\nvoid drawPiece(byte action);\nvoid setNextBlock(byte pieceNumber);\n\n// Variables \nstruct pieceSpace {\n  byte blocks[4][4];\n  int row;\n  int column;\n};\n\npieceSpace currentPiece = {0};  // The piece in play\npieceSpace oldPiece = {0};      // Buffer to hold the current piece whilst its manipulated\npieceSpace ghostPiece = {0};    // Current ghost piece\n\nunsigned long moveTime = 0;     // Baseline time for current move\nunsigned long keyTime = 0;      // Baseline time for current keypress\n\nbyte keyLock = 0;               // Holds the mode of the last keypress (for debounce and stuff)\n\nbyte nextBlockBuffer[8][2];     // The little image of the next block \nbyte nextPiece = 0;             // The identity of the next piece\nbyte blockArray[HORIZ][3];      // The byte-array of blocks\nbyte ghostArray[HORIZ][3];      // The byte-array of ghost pieces\nbool stopAnimate;               // True when the game is running\n\nint lastGhostRow = 0;           // Buffer to hold previous ghost position - for accurate drawing\nint score = 0;                  // Score buffer\nint topScore = 0;               // High score buffer\n\nbool challengeMode = 0;         // Is the system in \"Hard\" mode?\nbool ghost = 1;                 // Is the ghost active?\n\nint level = 0;                  // Current level (increments once per cleared line)\n\n\n\n/* \n * Interrupt handlers - to make sure every button press is caught promptly! \n */\n\n// PB0 pin button interrupt\nISR(PCINT0_vect) { \n  if (keyLock == 0) {\n    keyLock = 4; // Nothing complicated to do here - this is picked up in the handleInput() function \n    }\n}\n\n/*\n * This interrupt routine relies on having three buttons wired to pin 7 of the Attiny85 - all with a single pull-down resistor (10k) and \n *  - One that pulls-up to +Vcc (giving an analog reading of 1023)\n *  - One that pulls-up via a 1k resistor (analog reading somewhere around 930ish)\n *  - One that pulls-up via a 2.2 resistor (analog reading around 840)\n * \n * The key point is that all three buttons provide a voltage that sends the pin to logic-high, thus triggering the interrupt\n * (therefore you could add more buttons, as long as the voltage is always above the threshold that the Attiny85 would class\n * as logic-high). \n * \n * In practice, this technique requires a reasonably well made and well insulated board - adding moisture to to board (via damp\n * hands for example) would likely throw the voltages out enough that this technique would become unreliable.\n * \n */\n // PB2 pin button interrupt\nvoid playerIncTetris() { \n  if (keyLock == 0) {\n    int ic = analogRead(1);\n    if (ic > 800 && ic < 855) {\n      keyLock = 1;\n    } else if (ic > 855 && ic < 970) {\n      keyLock = 2;\n    } else if (ic > 970 && ic < 1025) {\n      keyLock = 3;\n    }\n  }\n}\n\n// Beep function - originally from the games by www.webboggles.com \nvoid beep(int bCount,int bDelay){\n for (int i = 0; i<=bCount; i++){digitalWrite(1,HIGH);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}digitalWrite(1,LOW);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}}\n}\n\n// SSD1306 screen drawing functions - adapted from https://bitbucket.org/tinusaur/ssd1306xled\nvoid ssd1306_char_f8x8(uint8_t x, uint8_t y, const char ch[]) {\n  uint8_t c, i, j = 0;\n\n  while (ch[j] != '\\0')\n  {\n    // These corrections allow for the fact that I've stripped out sections of the ASCII map from the font file\n    // If code space allows, then you could add some or all of them back in, but then you'd need to remove some or all of these lines.\n    c = ch[j] - 32; // to space\n    if (c > 0) c = c - 12; // to dash\n    if (c > 15) c = c - 7; \n    if (c > 40) c = c - 6;\n\n    ssd1306_setpos(y, x);\n    ssd1306_send_data_start();\n    for (byte lxn = 0; lxn < 8; lxn++) {    \n      ssd1306_send_byte(pgm_read_byte(&font[c][7-lxn]));      \n      }\n    ssd1306_send_data_stop();\n    x+= 1;\n    j++;\n  }\n}\n\nvoid ssd1306_init(void) {\n  DDRB |= (1 << SSD1306_SDA); // Set port as output\n  DDRB |= (1 << SSD1306_SCL); // Set port as output\n\n  ssd1306_send_command(0xAE); // display off\n  ssd1306_send_command(0x00); // Set Memory Addressing Mode\n  ssd1306_send_command(0x10); // 00,Horizontal Addressing Mode;01,VERTDRAWical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid\n  ssd1306_send_command(0x40); // Set Page Start Address for Page Addressing Mode,0-7\n  ssd1306_send_command(0x81); // Set COM Output Scan Direction\n  ssd1306_send_command(0xCF); // ---set low column address\n  ssd1306_send_command(0xA1); // ---set high column address\n  ssd1306_send_command(0xC8); // --set start line address\n  ssd1306_send_command(0xA6); // --set contrast control register\n  ssd1306_send_command(0xA8);\n  ssd1306_send_command(0x3F); // --set segment re-map 0 to 127\n  ssd1306_send_command(0xD3); // --set normal display\n  ssd1306_send_command(0x00); // --set multiplex ratio(1 to 64)\n  ssd1306_send_command(0xD5); //\n  ssd1306_send_command(0x80); // 0xa4,Output follows RAM content;0xa5,Output ignores RAM content\n  ssd1306_send_command(0xD9); // -set display offset\n  ssd1306_send_command(0xF1); // -not offset\n  ssd1306_send_command(0xDA); // --set display clock divide ratio/oscillator frequency\n  ssd1306_send_command(0x12); // --set divide ratio\n  ssd1306_send_command(0xDB); // --set pre-charge period\n  ssd1306_send_command(0x40); //\n  ssd1306_send_command(0x20); // --set com pins hardware configuration\n  ssd1306_send_command(0x02);\n  ssd1306_send_command(0x8D); // --set vcomh\n  ssd1306_send_command(0x14); // 0x20,0.77xVcc\n  ssd1306_send_command(0xA4); // --set DC-DC enable\n  ssd1306_send_command(0xA6); //\n  ssd1306_send_command(0xAF); // --turn on oled panel\n}\n\nvoid ssd1306_xfer_start(void) {\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n}\n\nvoid ssd1306_xfer_stop(void) {\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n}\n\nvoid ssd1306_send_byte(uint8_t byte) {\n  uint8_t i;\n  for (i = 0; i < 8; i++)\n  {\n    if ((byte << i) & 0x80)\n      DIGITAL_WRITE_HIGH(SSD1306_SDA);\n    else\n      DIGITAL_WRITE_LOW(SSD1306_SDA);\n\n    DIGITAL_WRITE_HIGH(SSD1306_SCL);\n    DIGITAL_WRITE_LOW(SSD1306_SCL);\n  }\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);\n  DIGITAL_WRITE_LOW(SSD1306_SCL);\n}\n\nvoid ssd1306_send_command(uint8_t command) {\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  // Slave address, SA0=0\n  ssd1306_send_byte(0x00);  // write command\n  ssd1306_send_byte(command);\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_send_data_start(void) {\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);\n  ssd1306_send_byte(0x40);  //write data\n}\n\nvoid ssd1306_send_data_stop(void) {\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_setpos(uint8_t x, uint8_t y)\n{\n  if (y > 7) return;\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  //Slave address,SA0=0\n  ssd1306_send_byte(0x00);  //write command\n\n  ssd1306_send_byte(0xb0 + y);\n  ssd1306_send_byte(((x & 0xf0) >> 4) | 0x10); // |0x10\n  ssd1306_send_byte((x & 0x0f) | 0x01); // |0x01\n\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_fillscreen(uint8_t fill_Data) {\n  uint8_t m, n;\n  for (m = 0; m < 8; m++)\n  {\n    ssd1306_send_command(0xb0 + m); //page0-page1\n    ssd1306_send_command(0x00);   //low column start address\n    ssd1306_send_command(0x10);   //high column start address\n    ssd1306_send_data_start();\n    for (n = 0; n < 128; n++)\n    {\n      ssd1306_send_byte(fill_Data);\n    }\n    ssd1306_send_data_stop();\n  }\n}\n\n// Sleep code from http://www.re-innovation.co.uk/web12/index.php/en/blog-75/306-sleep-modes-on-attiny85\nvoid system_sleep() {\n  ssd1306_fillscreen(0x00);\n  ssd1306_send_command(0xAE);\n  cbi(ADCSRA,ADEN);                    // switch Analog to DigitalconVERTDRAWer OFF\n  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here\n  sleep_enable();\n  sleep_mode();                        // System actually sleeps here\n  sleep_disable();                     // System continues execution here when watchdog timed out \n  sbi(ADCSRA,ADEN);                    // switch Analog to DigitalconVERTDRAWer ON  \n  ssd1306_send_command(0xAF);\n}\n\n// Arduino stuff\nvoid setup() {\n  DDRB = 0b00000010;    // set PB1 as output (for the speaker)\n  PCMSK = 0b00000001;   // pin change mask: listen to portb bit 1\n  GIMSK |= 0b00100000;  // enable PCINT interrupt\n  sei();                // enable all interrupts\n  ssd1306_init();       // initialise the screen\n}\n\nvoid loop() {\n  ssd1306_init();\n  ssd1306_fillscreen(0x00);\n\n  drawScreenBorder();\n  ssd1306_char_f8x8(1, 64,\"TETRIS\");\n  ssd1306_char_f8x8(1, 48, \"Attiny\");\n  ssd1306_char_f8x8(1, 40, \"Arcade\");\n  drawScreenBorder();\n\n  for (byte lxn = 0; lxn < 8; lxn++) {\n    ssd1306_setpos(78, lxn); \n    ssd1306_send_data_start(); \n    for (byte lxn2 = 0; lxn2 < 36; lxn2++) {\n      ssd1306_send_byte(pgm_read_byte(&brickLogo[36*lxn+lxn2]));  \n    }\n    ssd1306_send_data_stop(); \n  }\n\n  long startT = millis();\n  long nowT =0;\n  boolean sChange = 0;\n  while(digitalRead(0) == HIGH) {\n    nowT = millis();\n    if (nowT - startT > 2000) {\n      sChange = 1;     \n      if (digitalRead(2) == HIGH) {\n        ssd1306_char_f8x8(2, 8, \"MODE\"); \n        if (challengeMode == 0) { \n          challengeMode = 1; \n          ssd1306_char_f8x8(2, 16, \"HARD\"); \n        } else { \n          challengeMode = 0; \n          ssd1306_char_f8x8(1, 16, \"NORMAL\"); \n        }\n      } else {\n        ssd1306_char_f8x8(1, 16, \"GHOST\"); \n        if (ghost == 0) { \n          ghost = 1; \n          ssd1306_char_f8x8(2, 8, \"ON\"); \n        } else { \n          ghost = 0; \n          ssd1306_char_f8x8(2, 8, \"OFF\"); \n        }    \n      }\n      break;\n    }\n    if (sChange == 1) break;\n  }  \n  while(digitalRead(0) == HIGH);\n  \n  if (sChange == 0) {\n    delay(1600);\n    ssd1306_char_f8x8(1, 20, \"Andy-J\"); \n    delay(1500);\n    ssd1306_fillscreen(0x00);\n    playTetris();\n  }\n  delay(1000);\n  system_sleep();\n}\n\n/*\n *  These functional allow optimal storing of the array of Tetris and Ghost blocks by using a 10x3 array of bytes and extracting the relevant bit through shifting and masking\n */\n\nbyte readBlockArray(byte x, byte y) {\n    if (y < 8) {\n      return ((blockArray[x][0] & B00000001 << y) >> y);\n    } else if (y > 15) {\n      return ((blockArray[x][2] & B00000001 << y-15) >> y-15);\n    } else {\n      return ((blockArray[x][1] & B00000001 << y-8) >> y-8);\n    }   \n}\n\nvoid writeblockArray(byte x, byte y, bool value) {\n    byte arr = 0;\n    if (y<8) {\n      // do nothing \n    } else if (y > 15) {\n      arr = 2;\n      y-=15;\n    } else  {\n      arr = 1;\n      y-=8;\n    }  \n    if (value == 1) blockArray[x][arr] |= B00000001 << y; else blockArray[x][arr] &= (B11111110 << y) | (B01111111 >> 7-y);\n}\n\nbyte readGhostArray(byte x, byte y) {\n    if (y < 8) {\n      return ((ghostArray[x][0] & B00000001 << y) >> y);\n    } else if (y > 15) {\n      return ((ghostArray[x][2] & B00000001 << y-15) >> y-15);\n    } else {\n      return ((ghostArray[x][1] & B00000001 << y-8) >> y-8);\n    }   \n}\n\nvoid writeGhostArray(byte x, byte y, bool value) {\n    byte arr = 0;\n    if (y<8) {\n      // do nothing\n    } else if (y > 15) {\n      arr = 2;\n      y-=15;\n    } else  {\n      arr = 1;\n      y-=8;\n    }  \n    if (value == 1) ghostArray[x][arr] |= B00000001 << y; else ghostArray[x][arr] &= (B11111110 << y) | (B01111111 >> 7-y);\n}\n\nvoid fillGrid(byte value, bool mode) {\n  for (char r = 0; r < VERTMAX; r++) {\n    for (char c = 0; c < HORIZ; c++) {\n      if (mode == GHOST) writeGhostArray(c,r, value); else writeblockArray(c,r, value);\n    }\n  }\n}\n\nvoid rotatePiece(void) {\n  byte blocks[4][4];\n\n  memcpy(oldPiece.blocks, currentPiece.blocks, 16);\n  oldPiece.row = currentPiece.row;\n  oldPiece.column = currentPiece.column;\n\n  for (byte i = 0; i < 4; ++i) {\n    for (byte j = 0; j < 4; ++j) {\n      blocks[j][i] = currentPiece.blocks[4 - i - 1][j];\n    }\n  }\n  oldPiece = currentPiece;\n  memcpy(currentPiece.blocks, blocks, 16);\n  if (checkCollision()) currentPiece = oldPiece; else {\n    drawGhost(ERASE);\n    if (createGhost()) drawGhost(DRAW);\n    }\n}\n\nbool movePieceDown(void) {\n  int rndPiece = 0;\n\n  memcpy(oldPiece.blocks, currentPiece.blocks, 16);\n  oldPiece.row = currentPiece.row;\n  oldPiece.column = currentPiece.column;\n\n  currentPiece.row--;\n\n  //check collision\n  if (checkCollision()) {\n    currentPiece.row = oldPiece.row;\n    drawPiece(DRAW);\n    byte totalRows = 0;\n    \n    for (byte row = 0; row < VERTMAX; row++) { // scan the whole block (it's quick - there's no drawing to do)\n      bool rowFull = 1;\n      for (byte col = 0; col < HORIZ; col++) { // scan across this row - every column\n        if (readBlockArray(col,row) == 0) rowFull = 0; // if we hit any blank spaces, the row's not full\n      }\n      if (rowFull) {\n        totalRows++;\n        for (int i = 800; i>200; i = i - 200) beep(30,i); // happy sound\n        for (byte col = 0; col < HORIZ; col++) writeblockArray(col,row,0); // write zeros across this whole row\n        drawGameScreen(0,HORIZ-1,row,row+1,PARTIAL); // draw the row we're removing (for animation)\n        delay(30); // delay slightly to make the deletion of rows visible\n        for (byte dropCol = 0; dropCol < HORIZ; dropCol++) { // for every column\n          for (byte dropRow = row; dropRow < VERTMAX-1; dropRow ++) writeblockArray(dropCol,dropRow,readBlockArray(dropCol,dropRow+1)); // drop everything down as many as the row's we've cleared\n        }\n        row--; // we need to check this row again as it could now have things in it!\n      }\n    }\n    level += totalRows;\n    switch (totalRows) {\n      case 1:   score += 40; break;\n      case 2:   score += 100; break;\n      case 3:   score += 300; break;\n      case 4:   score += 800; \n    }\n    drawGameScreen(0,10, 0,VERTDRAW,FULL); \n    displayScore(score, 0,117,0);\n    loadPiece(nextPiece, STARTY, STARTX);\n    if (checkCollision()) {\n      stopAnimate = true;\n    } else {\n      loadPiece(nextPiece, STARTY, STARTX);\n      drawGhost(ERASE);\n      if (createGhost()) drawGhost(DRAW);\n    }\n    nextPiece = random(1, 8);\n    setNextBlock(nextPiece);\n  }\n  drawGhost(ERASE);\n  if (createGhost()) drawGhost(DRAW);\n}\n\nvoid movePieceLeft(void) {\n  byte response;\n \n  oldPiece = currentPiece;\n  currentPiece.column = currentPiece.column - 1;\n\n  response = checkCollision();\n\n  if (checkCollision()) {\n    currentPiece = oldPiece; // back to where it was\n  } else {\n    drawGhost(ERASE);\n    if (createGhost()) drawGhost(DRAW);\n  }\n}\n\nvoid movePieceRight(void) {\n  oldPiece = currentPiece;\n  currentPiece.column = currentPiece.column + 1;\n  //check collision\n  if (checkCollision()) \t{\n    currentPiece = oldPiece; // back to where it was\n  } else {\n    drawGhost(ERASE);\n    if (createGhost()) drawGhost(DRAW);\n  }\n}\n\nbyte checkCollision(void) {\n  byte pieceRow = 0;\n  byte pieceColumn = 0;\n\n  for (int c = currentPiece.column; c < currentPiece.column + 4; c++) {\n    for (int r = currentPiece.row; r < currentPiece.row + 4; r++) {\n      if (currentPiece.blocks[pieceColumn][pieceRow]) {\n        if (c < 0) return 2;\n        if (c > 9) return 1;\n        if (r < 0) return 1;\n        if (c >= 0 && r >= 0 && c < HORIZ && r < VERTMAX) {\n          if (readBlockArray(c,r)) {\n            return 1; //is it on landed blocks?\n          }\n        }\n      }\n      pieceRow++;\n    }\n    pieceRow = 0;\n    pieceColumn++;\n  }\n  return 0;\n}\n\nvoid handleInput(void) {\n  if (digitalRead(0) == LOW && digitalRead(2) == LOW) {\n    if (keyLock == 1) {\n      drawPiece(ERASE);\n      movePieceLeft();\n      drawPiece(DRAW);\n      drawGameScreen(currentPiece.column, currentPiece.column + 5, currentPiece.row, currentPiece.row+4, PARTIAL);         \n    } else if (keyLock == 2) {\n      drawPiece(ERASE);\n      movePieceRight();\n      drawPiece(DRAW);\n      drawGameScreen(currentPiece.column-1, currentPiece.column + 4, currentPiece.row, currentPiece.row+4,PARTIAL);         \n    } else if (keyLock == 3) {\n      drawPiece(ERASE);\n      rotatePiece();\n      drawPiece(DRAW);\n      drawGameScreen(currentPiece.column, currentPiece.column + 4, currentPiece.row, currentPiece.row+4,PARTIAL);         \n    }\n    keyLock = 0;      \n  }\n\n  if (keyLock == 4) {\n    while (digitalRead(0) == HIGH) {\n      drawPiece(ERASE);\n      movePieceDown();\n      drawPiece(DRAW);\n      drawGameScreen(currentPiece.column, currentPiece.column + 4, currentPiece.row, currentPiece.row+5,PARTIAL);         \n      delay(10);\n      if (stopAnimate) return;\n    }\n    keyLock = 0;\n  }\n  delay(30);\n}\n\nvoid setNextBlock(byte pieceNumber) {\n  memset(nextBlockBuffer, 0, sizeof nextBlockBuffer); //clear buffer\n  pieceNumber--;\n  if (pieceNumber == 0) {\n      for (int k = 2; k < 6; k++) {\n        nextBlockBuffer[k][0] = pgm_read_byte(&miniBlock[pieceNumber][0]);\n        nextBlockBuffer[k][1] = pgm_read_byte(&miniBlock[pieceNumber][0]);\n      }\n  \n  } else {  \n      for (int k = 0; k < 3; k++) {\n        nextBlockBuffer[k][0] = pgm_read_byte(&miniBlock[pieceNumber][0]);\n        nextBlockBuffer[k][1] = pgm_read_byte(&miniBlock[pieceNumber][1]);\n      }\n      for (int k = 4; k < 7; k++) {\n        nextBlockBuffer[k][0] = pgm_read_byte(&miniBlock[pieceNumber][2]);\n        nextBlockBuffer[k][1] = pgm_read_byte(&miniBlock[pieceNumber][3]);\n      }\n  }\n  drawGameScreen(0,10,0,VERTDRAW, FULL);\n}\n\nvoid drawScreenBorder(void) {\n    ssd1306_setpos(0, 0);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(0xFF);  \n    for (byte c = 1; c < 126; c++) {\n      ssd1306_send_byte(B00000001);  \n    }\n    ssd1306_send_byte(0xFF);  \n    ssd1306_send_data_stop();  \n    \n    for (byte r = 1; r < 7; r++) {\n    ssd1306_setpos(0, r);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(0xFF);        \n    ssd1306_send_data_stop();  \n    ssd1306_setpos(127, r);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(0xFF);        \n    ssd1306_send_data_stop();  \n    }\n\n    ssd1306_setpos(0, 7);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(0xFF);  \n    for (byte c = 1; c < 126; c++) {\n      ssd1306_send_byte(B10000000);  \n    }\n    ssd1306_send_byte(0xFF);  \n    ssd1306_send_data_stop();  \n}\n\nvoid displayScore(int score, int xpos, int y, bool blank) {\n  byte scoreOut[6];\n  scoreOut[5] = (score % 10);\n  scoreOut[4] = ((score / 10) % 10);\n  scoreOut[3] = ((score / 100) % 10);\n  scoreOut[2] = ((score / 1000) % 10);\n  scoreOut[1] = ((score / 10000) % 10);\n  scoreOut[0] = ((score / 100000) % 10);\n\n  for (byte x = xpos; x<xpos+6; x++) {\n    ssd1306_setpos(y, x);\n    ssd1306_send_data_start();\n    for (byte lxn = 0; lxn < 8; lxn++) {    \n      if (blank) ssd1306_send_byte(0); else ssd1306_send_byte(pgm_read_byte(&font[4+scoreOut[x-xpos]][7-lxn]));      \n    }\n    ssd1306_send_data_stop();\n  }\n}\n\nvoid drawGameScreen(int startCol, int endCol, int startRow, int endRow, byte mode) {\n  drawScreen(startCol, endCol, startRow, endRow, mode);\n\n  if (mode == PARTIAL) {\n    if (ghostPiece.row < lastGhostRow) { // ghost has moved down :)\n      drawScreen(startCol, endCol, ghostPiece.row, lastGhostRow + 4, mode) ;  \n    } else { // ghost has moved up (presumably!)\n      drawScreen(startCol, endCol, lastGhostRow, ghostPiece.row + 4, mode) ;  \n    }\n    \n  }\n}\n\nvoid drawScreen(int startCol, int endCol, int startRow, int endRow, byte mode) {\n  byte temp = 0;\n  byte separator = 0;\n  byte reader = 0;\n  byte blockReader = 0;\n  \n  if(startCol < 0) startCol = 0;\n  if(endCol > 10) endCol = 10;\n  if(startRow < 0) startRow = 0;\n  if(endRow > VERTDRAW) endRow = VERTDRAW;\n  \n  byte startScreenCol = pgm_read_byte(&startDecode[startCol]);\n  byte endScreenCol = pgm_read_byte(&endDecode[endCol]);\n  \n    for (byte col = startScreenCol; col < endScreenCol; col++) {\n    if (col < 4) reader = col; else if (col < 7) reader = col+1; else reader = col + 2;\n    blockReader = 2 * col;\n    ssd1306_setpos(startRow*6, col); // Start from the end of this column (working up the screen) on the required row\n    ssd1306_send_data_start(); \n    if (startRow == 0) ssd1306_send_byte(B11111111); else {\n      if (col == 0) ssd1306_send_byte(B00000001); else if (col == 7) ssd1306_send_byte(B10000000); else ssd1306_send_byte(B00000000);\n    }\n    for (byte r = startRow; r < endRow; r++ ) { // For each row in the array of tetris blocks\n      for (byte piece = 0; piece < 5; piece ++) { // for each of the 5 filled lines of the block\n        if (col == 0) temp = B00000001; else if (col == 7) temp = B10000000; else temp = 0x00; // if we're on the far left, draw the left wall, on the far right draw the right wall, otherwise its a blank separator between blocks\n        separator = temp; // we'll need this again later! \n\n        if (readBlockArray(reader,r)) { \n          temp = temp | pgm_read_byte(&blockout[blockReader]);\n        }\n        if (readBlockArray(reader+1,r)) { \n          temp = temp | pgm_read_byte(&blockout[blockReader+1]);\n        }\n\n        if(ghost) {\n          if (readGhostArray(reader,r) && (piece == 0 || piece == 4)) { \n            temp = temp | pgm_read_byte(&blockout[blockReader]);\n          } else if (readGhostArray(reader,r)) { \n            temp = temp | pgm_read_byte(&ghostout[blockReader]);\n          }\n                \n          if (readGhostArray(reader+1,r) && (piece == 0 || piece == 4)) { \n            temp = temp | pgm_read_byte(&blockout[blockReader+1]);\n          } else if (readGhostArray(reader+1,r)) { \n            temp = temp | pgm_read_byte(&ghostout[blockReader+1]);\n          }\n        }\n        ssd1306_send_byte(temp);          \n      }\n      ssd1306_send_byte(separator); // between blocks - same one as we used at the start\n    }    \n    if (mode == FULL) if (col > 5) for (byte blockline = 0; blockline < 8; blockline++) ssd1306_send_byte(nextBlockBuffer[blockline][col-6]);\n    ssd1306_send_data_stop(); \n  }\n}\n\nbool createGhost(void) {\n  byte tempRow = currentPiece.row;\n\n  if (currentPiece.row < 3) return 0;\n\n  currentPiece.row-=2;\n  while(checkCollision() == 0) currentPiece.row--;\n\n  memcpy(ghostPiece.blocks, currentPiece.blocks, 16);\n  ghostPiece.row = currentPiece.row+1;\n  ghostPiece.column = currentPiece.column;\n  currentPiece.row = tempRow;\n  \n  if (ghostPiece.row > currentPiece.row - 3) return 0; else return 1;\n}\n\nvoid loadPiece(byte pieceNumber, byte row, byte column) {\n  byte incr = 0;\n\n  pieceNumber--;\n  \n  for (byte lxn = 0; lxn < 4; lxn++) {\n    for (byte lxn2 = 0; lxn2 < 4; lxn2++) {\n      if ( ((1 << incr) & pgm_read_word(&blocks[pieceNumber])) >> incr == 1) {\n        currentPiece.blocks[lxn][lxn2] = 1;                \n      } else currentPiece.blocks[lxn][lxn2] = 0;\n      incr++;\n    }\n  }\n  currentPiece.row = row;\n  currentPiece.column = column;\n}\n\nvoid drawPiece(byte action) {\n  for (byte lxn = 0; lxn < 4; lxn++) {\n    for (byte lxn2 = 0; lxn2 < 4; lxn2++) {\n      if (currentPiece.blocks[lxn][lxn2] == 1) {\n        if (action == DRAW) writeblockArray(currentPiece.column + lxn,currentPiece.row + lxn2,1); else if (action == ERASE) writeblockArray(currentPiece.column + lxn,currentPiece.row + lxn2,0);                \n      }\n    }\n  }\n}\n\nvoid drawGhost(byte action) {\n  for (byte lxn = 0; lxn < 4; lxn++) {\n    for (byte lxn2 = 0; lxn2 < 4; lxn2++) {\n      if (ghostPiece.blocks[lxn][lxn2] == 1) {\n        if (action == DRAW) writeGhostArray(ghostPiece.column + lxn,ghostPiece.row + lxn2,1); else if (action == ERASE) {writeGhostArray(ghostPiece.column + lxn,ghostPiece.row + lxn2,0); lastGhostRow = ghostPiece.row; }                \n      }\n    }\n  }\n}\n\nvoid playTetris(void) {\n  stopAnimate = 0;\n  score = 0;\n  keyLock = 0;\n\n  fillGrid(0, NORMAL);\n  fillGrid(0, GHOST);\n\n  // Attach the interrupt to read key 2\n    attachInterrupt(0,playerIncTetris,RISING);\n\n  loadPiece(random(1, 8), STARTY, STARTX);\n  drawPiece(DRAW);\n  if (createGhost()) drawGhost(DRAW);\n  drawGhost(DRAW);\n  nextPiece = random(1, 8);\n  setNextBlock(nextPiece);\n  \n  // Fill up the screen with random crap if it's in challenge mode!\n  if (challengeMode) {\n    for (byte cl = 0; cl < 100; cl++) {\n      drawPiece(ERASE);\n      movePieceDown();\n      if (random(1,8) >4) movePieceLeft();\n      drawPiece(DRAW);      \n    }\n  } \n\n  // Reset the level\n  level = STARTLEVEL;\n  \n  drawGameScreen(0,10,0,VERTDRAW, FULL); \n  displayScore(score, 0,117,0);\n  \n  while (stopAnimate == 0) {\n    drawPiece(ERASE);\n    movePieceDown();\n    drawPiece(DRAW);\n    drawGameScreen(currentPiece.column, currentPiece.column + 4, currentPiece.row, currentPiece.row+5, PARTIAL);         \n    moveTime = millis();\n    if (level * LEVELFACTOR > DROPDELAY) level = DROPDELAY / LEVELFACTOR;\n    while ((millis() - moveTime) < (DROPDELAY - level* LEVELFACTOR)) {\n      handleInput();\n    }\n  }\n\n  ssd1306_fillscreen(0x00);\n\n  bool newHigh = false;\n  topScore = EEPROM.read(0);\n  topScore = topScore << 8;\n  topScore = topScore |  EEPROM.read(1);\n  \n  if (score > topScore) { \n    topScore = score;\n    EEPROM.write(1,score & 0xFF); \n    EEPROM.write(0,(score>>8) & 0xFF);\n    newHigh = true; \n  }\n  drawScreenBorder();\n\n  displayScore(score, 1,80,0);\n  displayScore(topScore, 1,40,0);\n   for (int i = 0; i<1000; i = i+ 50){\n    beep(50,i);\n    }\n  for (byte lx = 0; lx<4;lx++) {\n    displayScore(score, 1,80,1);    \n    if (newHigh) displayScore(topScore, 1,40,1);\n    delay(200);\n    displayScore(score, 1,80,0);    \n    if (newHigh) displayScore(topScore, 1,40,0);\n    delay(200);\n  }\n}\r\n"
  },
  {
    "path": "Tetris_Multi_Button/font8x8AJ.h",
    "content": "/*\n * This font is from http://arduino-er.blogspot.co.uk/2014/08/port-ascii-font-to-arduino-88-led-matrix.html\n *  \n * Source code adapted by @andyhighnumber from that available at: https://bitbucket.org/tinusaur/ssd1306xled\n *\n * Hacked to remove unused letters and thus minimise code space for the Attiny85\n *\n */\n\n// ----------------------------------------------------------------------------\n\n#include <avr/pgmspace.h>\n\n// ----------------------------------------------------------------------------\n\nstatic const byte font[][8] PROGMEM = {\n    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0020 (space)\n    { 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00},   // U+002D (-)\n    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00},   // U+002E (.)\n    { 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00},   // U+002F (/)\n    { 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00},   // U+0030 (0)\n    { 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00},   // U+0031 (1)\n    { 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00},   // U+0032 (2)\n    { 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00},   // U+0033 (3)\n    { 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00},   // U+0034 (4)\n    { 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00},   // U+0035 (5)\n    { 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00},   // U+0036 (6)\n    { 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00},   // U+0037 (7)\n    { 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00},   // U+0038 (8)\n    { 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00},   // U+0039 (9)\n    { 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00},   // U+0041 (A)\n    { 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00},   // U+0042 (B)\n    { 0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00},   // U+0043 (C)\n    { 0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00},   // U+0044 (D)\n    { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00},   // U+0045 (E)\n    { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00},   // U+0046 (F)\n    { 0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00},   // U+0047 (G)\n    { 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00},   // U+0048 (H)\n    { 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},   // U+0049 (I)\n    { 0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00},   // U+004A (J)\n    { 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00},   // U+004B (K)\n    { 0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00},   // U+004C (L)\n    { 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00},   // U+004D (M)\n    { 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00},   // U+004E (N)\n    { 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00},   // U+004F (O)\n    { 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00},   // U+0050 (P)\n    { 0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00},   // U+0051 (Q)\n    { 0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00},   // U+0052 (R)\n    { 0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00},   // U+0053 (S)\n    { 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},   // U+0054 (T)\n    { 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00},   // U+0055 (U)\n    { 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00},   // U+0056 (V)\n    { 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00},   // U+0057 (W)\n    { 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00},   // U+0058 (X)\n    { 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00},   // U+0059 (Y)\n    { 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00},   // U+005A (Z)\n    { 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00},   // U+0061 (a)\n    //{ 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00},   // U+0062 (b)\n    { 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00},   // U+006E (n) // n in place of b\n    { 0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00},   // U+0063 (c)\n    { 0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00},   // U+0064 (d)\n    { 0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00},   // U+0065 (e)\n    //{ 0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00},   // U+0066 (f)\n    { 0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00},   // U+0072 (r) // r in place of f\n    //{ 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F},   // U+0067 (g)\n    { 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F},   // U+0079 (y) // y in place of g\n    //{ 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00},   // U+0068 (h)\n    { 0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00},   // U+0074 (t) // t in place of h\n    { 0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},   // U+0069 (i)\n    { 0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E},   // U+006A (j)\n    { 0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00},   // U+006B (k)\n    \n/*\n    { 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},   // U+006C (l)  \n    { 0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00},   // U+006D (m)\n    { 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00},   // U+006E (n)\n    { 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00},   // U+006F (o)\n    { 0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F},   // U+0070 (p)\n    { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78},   // U+0071 (q)\n    { 0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00},   // U+0072 (r)\n    { 0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00},   // U+0073 (s)\n    { 0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00},   // U+0074 (t)\n    { 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00},   // U+0075 (u)\n    { 0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00},   // U+0076 (v)\n    { 0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00},   // U+0077 (w)\n    { 0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00},   // U+0078 (x)\n    { 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F},   // U+0079 (y)\n    { 0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00},   // U+007A (z)\n*/\n};\n\n\n// ----------------------------------------------------------------------------\n\r\n"
  },
  {
    "path": "UFO_Breakout_Arduino/UFO_Breakout_Arduino.ino",
    "content": "/* 2015 / 2016\n * UFO and Breakout games by Ilya Titov. Find building instructions on http://webboggles.com/\n * The code that does not fall under the licenses of sources listed below can be used non commercially with attribution.\n *\n * Modified by andy jackson to allow two games to fit into a single ATTiny85 at the same time.\n * Additional features:\n *  - To play UFO - press and release left button\n *  - To play Breakout - with the right button held, press and release left button \n *  - To turn sound on and off - press and HOLD left button\n *  - To reset high scores to zero - whilst HOLDING the right button, press and HOLD the left button\n * \n * If you have problems uploading this sketch, this is probably due to sketch size - you need to update ld.exe in arduino\\hardware\\tools\\avr\\avr\\bin\n * https://github.com/TCWORLD/ATTinyCore/tree/master/PCREL%20Patch%20for%20GCC\n *\n * This sketch is using the screen control and font functions written by Neven Boyanov for the http://tinusaur.wordpress.com/ project\n * Source code and font files available at: https://bitbucket.org/tinusaur/ssd1306xled\n * **Note that this highly size-optimised version requires modified library functions (which are in this source code file) \n * and a modified font header\n * \n * Sleep code is based on this blog post by Matthew Little:\n * http://www.re-innovation.co.uk/web12/index.php/en/blog-75/306-sleep-modes-on-attiny85\n*/\n#include <EEPROM.h>\n#include \"font6x8AJ.h\"\n#include <avr/sleep.h>\n#include <avr/interrupt.h> // needed for the additional interrupt\n\n#define DIGITAL_WRITE_HIGH(PORT) PORTB |= (1 << PORT)\n#define DIGITAL_WRITE_LOW(PORT) PORTB &= ~(1 << PORT)\n\n// Routines to set and clear bits (used in the sleep code)\n#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))\n#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))\n\n// Defines for OLED output\n#define SSD1306XLED_H\n#define SSD1306_SCL   PORTB3  // SCL, Pin 3 on SSD1306 Board\n#define SSD1306_SDA   PORTB4  // SDA, Pin 4 on SSD1306 Board\n#define SSD1306_SA    0x78  // Slave address\n\n// Function prototypes for UFO\nvoid beep(int,int);\nvoid playUFO(void);\n\n// Function prototypes for Breakout\nvoid collision(void);\nvoid drawPlatform(void);\nvoid sendBlock(boolean);\nvoid playBreakout(void);\n\n// Other function prototypes - for both\nvoid doNumber (int x, int y, int value);\nvoid ssd1306_init(void);\nvoid ssd1306_xfer_start(void);\nvoid ssd1306_xfer_stop(void);\nvoid ssd1306_send_byte(uint8_t byte);\nvoid ssd1306_send_command(uint8_t command);\nvoid ssd1306_send_data_start(void);\nvoid ssd1306_send_data_stop(void);\nvoid ssd1306_setpos(uint8_t x, uint8_t y);\nvoid ssd1306_fillscreen(uint8_t fill_Data);\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]);\nvoid ssd1306_draw_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t bitmap[]);\n\n// for UFO\nint topScoreU = 0;\nboolean isBreakout = 0;\nbyte maxObstacles = 1; // this defines the max number of in game obstacles\nbyte obstacleStep = 2; // pixel step of obstacles per frame\nint obstacle[9] = {-50,-50,-50,-50,-50,-50,-50,-50,-50}; // x offset of the obstacle default position, out of view\nbyte gapOffset[9] = {0,0,0,0,0,0,0,0,0}; // y offset of the fly-through gap\nint gapSize[9]; // y height of the gap\nbyte maxGap = 60; // max height of the gap\nint stepsSinceLastObstacle = 0; // so obstacles are not too close\nbyte gapBlock[9] = {0,0,0,0,0,0,0,0,0}; // if the fly-through gap is closed\nbyte blockChance = 0; // this higher value decreases the likelihood of gap being closed \nboolean fire = 0; // set to 1 when the fire interrupt is triggered\nbyte fireCount = 0; // the shot is persistent for several frames\nbyte playerOffset = 0; // y offset of the top of the player\nbyte flames = 0; // this is set to 1 when the move up interrupt is triggered\nbyte flameMask[2]={B00111111,B11111111}; // this is used to only show the flame part of the icon when moving up\nvoid doDrawLS(long, byte);\nvoid doDrawRS(long, byte);\n\n// For Breakout\nint topScoreB = 0;\nvolatile byte player = 0; //0 to 128-platformWidth  - this is the position of the bounce platform\nbyte platformWidth = 16; \nbyte ballx = 62; // coordinate of the ball\nbyte bally = 50; // coordinate of the ball\nint vdir = -1; // vertical direction and step  distance\nint hdir = -1; // horizontal direction and step distance\nlong lastFrame = 0; // time since the screen was updated last\nboolean row[3][16]; // on-off array of blocks\n\n// For both\nboolean stopAnimate = 0; // this is set to 1 when a collision is detected\nboolean mute = 0;\nboolean newHigh = 0;\nint score = 0; // score - this affects the difficulty of the game\nint top = 0;\n\n// Interrupt handlers\nISR(PCINT0_vect){ // PB0 pin button interrupt           \n   if ( (player >0) && (isBreakout) ) {player--;} \n   return;\n}\nvoid playerIncUFO(){ // PB2 pin button interrupt\n   fire = 1;\n   fireCount = 5; // number of frames the shot will persist\n}\nvoid playerIncBreakOut(){ // PB2 pin button interrupt\n  if (player <128-platformWidth){player++;}\n}\n\n// Arduino stuff - setup\nvoid setup() {\n  DDRB = 0b00000010;    // set PB1 as output (for the speaker)\n  PCMSK = 0b00000001; // pin change mask: listen to portb bit 1\n  GIMSK |= 0b00100000;  // enable PCINT interrupt \n  sei();          // enable all interrupts\n}\n\n// Arduino stuff - loop\nvoid loop() { \n  isBreakout = 0;\n  \n  if (digitalRead(2) == HIGH) isBreakout = 1;\n  \n  interrupts();\n  ssd1306_init();\n  ssd1306_fillscreen(0x00);\n  \n  for (byte s = 0; s<30; s++){ // generate stars\n     ssd1306_setpos((uint8_t)(random(0,127)),(uint8_t)(random(0,7)) );\n     ssd1306_send_data_start();\n     ssd1306_send_byte(B10000000>>random(0,7)); \n     ssd1306_send_data_stop();\n     //beep(10+s,600);    \n  }\n\n  if (isBreakout) {\n    ssd1306_char_f6x8(16, 2, \"B R E A K O U T\");\n  } else {\n    ssd1306_char_f6x8(14, 2, \"U F O  C H A O S\");\n  }\n  // The lower case character set is seriously compromised because I've had to truncate the ASCII table\n  // to release space for executable code - hence lower case y and w are remapped to h and / respectively.\n  // There is no z in the table (or h!) as these aren't used anywhere in the text here and most of the \n  // symbols are also missing for the same reason (see my hacked version of font6x8.h - font6x8AJ.h for more detail)\n  ssd1306_char_f6x8(3, 4, \"mods bh andh jackson\"); // see comments above !\n  ssd1306_char_f6x8(22, 6, \"game design bh\");  // see comments above !\n  ssd1306_char_f6x8(22, 7, \"/ebboggles.com\");  // see comments above !\n\n  long startT = millis();\n  long nowT =0;\n  boolean sChange = 0;\n  while(digitalRead(0) == HIGH) {\n    nowT = millis();\n    if (nowT - startT > 2000) {\n      sChange = 1;     \n      if (digitalRead(2) == HIGH) {\n        EEPROM.write(0,0);\n        EEPROM.write(1,0);\n        EEPROM.write(2,0);\n        EEPROM.write(3,0);      \n        ssd1306_char_f6x8(8, 1, \"-HIGH SCORE RESET-\");  \n      } else if (mute == 0) { mute = 1; ssd1306_char_f6x8(32, 1, \"-- MUTE --\"); } else { mute = 0; ssd1306_char_f6x8(23, 1, \"-- SOUND ON --\");  }    \n      break;\n    }\n    if (sChange == 1) break;\n  }  \n  while(digitalRead(0) == HIGH);\n\n  if (sChange == 0) {\n    delay(2600);\n    noInterrupts();  \n    ssd1306_init();\n    ssd1306_fillscreen(0x00);\n    stopAnimate = 0;\n    score = 0;\n    \n    if (isBreakout) { playBreakout(); top=topScoreB;} else { playUFO(); top=topScoreU;}\n    \n    ssd1306_fillscreen(0x00);\n    ssd1306_char_f6x8(11, 1, \"----------------\");\n    ssd1306_char_f6x8(11, 2, \"G A M E  O V E R\");\n    ssd1306_char_f6x8(11, 3, \"----------------\");\n    ssd1306_char_f6x8(37, 5, \"SCORE:\");\n    doNumber(75, 5, score);\n    if (!newHigh) {\n      ssd1306_char_f6x8(21, 7, \"HIGH SCORE:\");\n      doNumber(88, 7, top);\n    }\n    for (int i = 0; i<1000; i = i+ 50){\n      beep(50,i);\n    }\n    delay(2000);\n    if (newHigh) {\n      ssd1306_fillscreen(0x00);\n      ssd1306_char_f6x8(10, 1, \"----------------\");\n      ssd1306_char_f6x8(10, 3,  \" NEW HIGH SCORE \");\n      ssd1306_char_f6x8(10, 7, \"----------------\");\n      doNumber(50,5,top);\n      for (int i = 700; i>200; i = i - 50){\n      beep(30,i);\n      }\n      newHigh = 0;\n      delay(2700);    \n    } \n  }\n  system_sleep();\n  noInterrupts();  \n}\n\nvoid doNumber (int x, int y, int value) {\n    char temp[10] = {0,0,0,0,0,0,0,0,0,0};\n    itoa(value,temp,10);\n    ssd1306_char_f6x8(x, y, temp);\n}\n\nvoid ssd1306_init(void){\n  DDRB |= (1 << SSD1306_SDA); // Set port as output\n  DDRB |= (1 << SSD1306_SCL); // Set port as output\n\n  ssd1306_send_command(0xAE); // display off\n  ssd1306_send_command(0x00); // Set Memory Addressing Mode\n  ssd1306_send_command(0x10); // 00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid\n  ssd1306_send_command(0x40); // Set Page Start Address for Page Addressing Mode,0-7\n  ssd1306_send_command(0x81); // Set COM Output Scan Direction\n  ssd1306_send_command(0xCF); // ---set low column address\n  ssd1306_send_command(0xA1); // ---set high column address\n  ssd1306_send_command(0xC8); // --set start line address\n  ssd1306_send_command(0xA6); // --set contrast control register\n  ssd1306_send_command(0xA8);\n  ssd1306_send_command(0x3F); // --set segment re-map 0 to 127\n  ssd1306_send_command(0xD3); // --set normal display\n  ssd1306_send_command(0x00); // --set multiplex ratio(1 to 64)\n  ssd1306_send_command(0xD5); // \n  ssd1306_send_command(0x80); // 0xa4,Output follows RAM content;0xa5,Output ignores RAM content\n  ssd1306_send_command(0xD9); // -set display offset\n  ssd1306_send_command(0xF1); // -not offset\n  ssd1306_send_command(0xDA); // --set display clock divide ratio/oscillator frequency\n  ssd1306_send_command(0x12); // --set divide ratio\n  ssd1306_send_command(0xDB); // --set pre-charge period\n  ssd1306_send_command(0x40); // \n  ssd1306_send_command(0x20); // --set com pins hardware configuration\n  ssd1306_send_command(0x02);\n  ssd1306_send_command(0x8D); // --set vcomh\n  ssd1306_send_command(0x14); // 0x20,0.77xVcc\n  ssd1306_send_command(0xA4); // --set DC-DC enable\n  ssd1306_send_command(0xA6); // \n  ssd1306_send_command(0xAF); // --turn on oled panel \n}\n\nvoid ssd1306_xfer_start(void){\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n}\n\nvoid ssd1306_xfer_stop(void){\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n}\n\nvoid ssd1306_send_byte(uint8_t byte){\n  uint8_t i;\n  for(i=0; i<8; i++)\n  {\n    if((byte << i) & 0x80)\n      DIGITAL_WRITE_HIGH(SSD1306_SDA);\n    else\n      DIGITAL_WRITE_LOW(SSD1306_SDA);\n    \n    DIGITAL_WRITE_HIGH(SSD1306_SCL);\n    DIGITAL_WRITE_LOW(SSD1306_SCL);\n  }\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);\n  DIGITAL_WRITE_LOW(SSD1306_SCL);\n}\n\nvoid ssd1306_send_command(uint8_t command){\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  // Slave address, SA0=0\n  ssd1306_send_byte(0x00);  // write command\n  ssd1306_send_byte(command);\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_send_data_start(void){\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);\n  ssd1306_send_byte(0x40);  //write data\n}\n\nvoid ssd1306_send_data_stop(void){\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_setpos(uint8_t x, uint8_t y)\n{\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  //Slave address,SA0=0\n  ssd1306_send_byte(0x00);  //write command\n\n  ssd1306_send_byte(0xb0+y);\n  ssd1306_send_byte(((x&0xf0)>>4)|0x10); // |0x10\n  ssd1306_send_byte((x&0x0f)|0x01); // |0x01\n\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_fillscreen(uint8_t fill_Data){\n  uint8_t m,n;\n  for(m=0;m<8;m++)\n  {\n    ssd1306_send_command(0xb0+m); //page0-page1\n    ssd1306_send_command(0x00);   //low column start address\n    ssd1306_send_command(0x10);   //high column start address\n    ssd1306_send_data_start();\n    for(n=0;n<128;n++)\n    {\n      ssd1306_send_byte(fill_Data);\n    }\n    ssd1306_send_data_stop();\n  }\n}\n\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]){\n  uint8_t c,i,j=0;\n  while(ch[j] != '\\0')\n  {\n    c = ch[j] - 32;\n    if (c >0) c = c - 12;\n    if (c >15) c = c - 6;\n    if (c>40) c=c-9;\n    if(x>126)\n    {\n      x=0;\n      y++;\n    }\n    ssd1306_setpos(x,y);\n    ssd1306_send_data_start();\n    for(i=0;i<6;i++)\n    {\n      ssd1306_send_byte(pgm_read_byte(&ssd1306xled_font6x8[c*6+i]));\n    }\n    ssd1306_send_data_stop();\n    x += 6;\n    j++;\n  }\n}\n\nvoid system_sleep() {\n  ssd1306_fillscreen(0x00);\n  ssd1306_send_command(0xAE);\n  cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF\n  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here\n  sleep_enable();\n  sleep_mode();                        // System actually sleeps here\n  sleep_disable();                     // System continues execution here when watchdog timed out \n  sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON  \n  ssd1306_send_command(0xAF);\n}\n\nvoid beep(int bCount,int bDelay){\n  if (mute) return;\n  for (int i = 0; i<=bCount; i++){digitalWrite(1,HIGH);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}digitalWrite(1,LOW);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}}\n}\n\n/* ------------------------\n *  UFO Code\n */\n\nvoid playUFO(void) {\n  fire = 0;\n  maxObstacles = 3;\n  obstacleStep = 2;\n  for (byte i = 0; i<9; i++){\n    obstacle[i] = -50;\n    gapOffset[i]=0;\n  }\n  stepsSinceLastObstacle = 0;\n  playerOffset = 0; // y offset of the top of the player\n  \n  while (stopAnimate == 0) {\n\n  attachInterrupt(0,playerIncUFO,RISING);\n     \n  //update game vars to make it harder to play\n  if (score < 500){blockChance = 11-score/50; if (maxObstacles<5){maxObstacles=(score+40)/70+1;} delayMicroseconds(16000/maxObstacles);}\n  \n  if (score < 2000){maxGap = 60-score/100;}\n  if (fire == 1){score--;}\n  if (fireCount>0){fireCount--;}\n\n  for (int boo = 0; boo<3;boo++) {\n    if (digitalRead(0)==1){\n      if (playerOffset >0){\n        playerOffset--; \n        flames = 1; // move player up\n        for (int i = 0; i<2; i++){\n          beep(1,random(0,i*2));\n        }\n      }\n    }\n  }\n  \n  stepsSinceLastObstacle += obstacleStep;\n  for (byte i = 0; i<maxObstacles;i++){ // fly obstacles\n  if (obstacle[i] >= 0 && obstacle[i] <= 128){\n  obstacle[i] -= obstacleStep;\n  if (gapBlock[i]>0 && obstacle[i] < 36  && playerOffset>gapOffset[i] && playerOffset+5<gapOffset[i]+gapSize[i] && fireCount > 0){//\n   gapBlock[i] = 0;\n   score += 5; \n   for (byte cp = 400; cp>0; cp--){\n     beep(1,cp);\n   }\n  }\n  } \n  \n  if (obstacle[i]<=4 && stepsSinceLastObstacle>=random(30,100)){ // generate new obstacles\n  obstacle[i] = 123;\n  gapSize[i] = random(25,maxGap);\n  gapOffset[i] = random(0,64-gapSize[i]);\n  if (random(0,blockChance)==0){gapBlock[i] = 1;}else {gapBlock[i] = 0;}\n  stepsSinceLastObstacle = 0;\n  score+=1;\n  }\n  }\n  \n  if ( (fireCount == 0) && (playerOffset < 56) ){playerOffset++;} // player gravit\n  \n  // update what's on the screen\n  // erase player\n  for (byte r=0; r<8; r++){\n  if (r<playerOffset/8 | r >= playerOffset/8+1) {\n    ssd1306_setpos(0,r);\n    ssd1306_send_data_start();\n    sendBlock(0);\n    sendBlock(0);\n    ssd1306_send_data_stop();\n    }\n  }\n  \n  //erase fire\n  ssd1306_setpos(16,playerOffset/8);\n  ssd1306_send_data_start();\n  if (fireCount == 0){\n            for (byte f = 0; f<=30; f++){\n                ssd1306_send_byte(B00000000);\n            }\n  }\n  ssd1306_send_data_stop();\n  \n  // Send Obstacle\n  for (byte i = 0; i<maxObstacles;i++){\n  if (obstacle[i] >= -5 && obstacle[i] <= 128){ // only deal with visible obstacles\n  if (obstacle[i] > 8 && obstacle[i] <16){ // look for collision if obstacle is near the player\n    if (playerOffset < gapOffset[i] || playerOffset+5 > gapOffset[i]+gapSize[i] || gapBlock[i] != 0){\n      // collision - stop looping\n      stopAnimate = 1; \n    }\n  }                      \n  \n  for (byte row = 0; row <8; row++){\n      ssd1306_setpos(obstacle[i],row);\n      ssd1306_send_data_start();\n      \n      if (obstacle[i]>0&&obstacle[i] < 128){\n         \n         if ((row+1)*8 - gapOffset[i] <= 8){ // generate obstacle : top and transition\n            byte temp = B11111111>>((row+1)*8 - gapOffset[i]); \n            byte tempB = B00000000; \n            if (gapBlock[i]>0){tempB=B10101010;}\n            ssd1306_send_byte(temp);\n            ssd1306_send_byte(temp|tempB>>1);\n            ssd1306_send_byte(temp|tempB);\n            ssd1306_send_byte(temp);\n            \n         }else if (row*8>=gapOffset[i] && (row+1)*8<=gapOffset[i]+gapSize[i]){ // middle gap\n            byte tempB = B00000000; \n            if (gapBlock[i]>0){tempB=B10101010;}\n            ssd1306_send_byte(B00000000);\n            ssd1306_send_byte(B00000000|tempB>>1);\n            ssd1306_send_byte(B00000000|tempB);\n            ssd1306_send_byte(B00000000);\n  \n         }else if ((gapOffset[i] +gapSize[i]) >= row*8 && (gapOffset[i] +gapSize[i]) <= (row+1)*8){ // bottom transition\n            //}else if ((gapOffset[i] +gapSize[i]) >= row*8 && (gapOffset[i] +gapSize[i]) <= (row+1)*8){ // bottom transition\n            //byte temp = B11111111<<((gapOffset[i] + gapSize[i])%8); \n            \n            byte temp = B11111111<<((gapOffset[i] + gapSize[i])%8); \n            byte tempB = B00000000; \n            if (gapBlock[i]>0){tempB=B10101010;}\n            ssd1306_send_byte(temp);\n            ssd1306_send_byte(temp|tempB>>1);\n            ssd1306_send_byte(temp|tempB);\n            ssd1306_send_byte(temp);\n            \n         }else { // fill rest of obstacle\n            ssd1306_send_byte(B11111111);\n            ssd1306_send_byte(B11111111);\n            ssd1306_send_byte(B11111111);\n            ssd1306_send_byte(B11111111);\n         }\n         \n         ssd1306_send_byte(B00000000);\n         ssd1306_send_byte(B00000000);\n         \n      ssd1306_send_data_stop();\n      }\n    }\n  \n  }\n  }\n   \n  if (playerOffset%8!=0){\n    ssd1306_setpos(8,playerOffset/8);\n    ssd1306_send_data_start();\n    doDrawLS(0,playerOffset%8);\n    ssd1306_send_data_stop();\n    \n    ssd1306_setpos(8,playerOffset/8+1);\n    ssd1306_send_data_start();\n    doDrawRS(0,8-playerOffset%8);\n    ssd1306_send_data_stop();\n  } else {\n    ssd1306_setpos(8,playerOffset/8);\n    ssd1306_send_data_start();\n    doDrawLS(0,0);\n    ssd1306_send_data_stop();\n  }\n\n  // Display score in the screen corner\n  doNumber(92, 0, score);\n  \n  flames = 0;\n  interrupts();\n  } // while stopanimate == 0\n\n  topScoreU = EEPROM.read(0);\n  topScoreU = topScoreU << 8;\n  topScoreU = topScoreU |  EEPROM.read(1);\n  \n  if (score > topScoreU) {\n    topScoreU = score;\n    EEPROM.write(1,score & 0xFF); \n    EEPROM.write(0,(score>>8) & 0xFF); \n    newHigh = 1;\n  }\n}\n\n// Drawing routine for the player and fire - with right-shifts\nvoid doDrawRS(long P1, byte P2) {\n  ssd1306_send_byte((B00001100&flameMask[flames] | P1)>>P2);\n  ssd1306_send_byte((B01011110&flameMask[flames] | P1)>>P2);\n  ssd1306_send_byte((B10010111&flameMask[flames] | P1)>>P2);\n  ssd1306_send_byte((B01010011&flameMask[flames] | P1)>>P2);\n  ssd1306_send_byte((B01010011&flameMask[flames] | P1)>>P2);\n  ssd1306_send_byte((B10010111&flameMask[flames] | P1)>>P2);\n  ssd1306_send_byte((B01011110&flameMask[flames] | P1)>>P2);\n  ssd1306_send_byte((B00001100&flameMask[flames] | P1)>>P2);  \n  \n  if (fireCount >0) {\n        for (byte f = 0; f<=24; f++){\n            ssd1306_send_byte(B00000100>>P2);\n        }\n        ssd1306_send_byte(B00010101>>P2);\n        //ssd1306_send_byte(B00001010>>P2);\n        ssd1306_send_byte(B00010101>>P2);\n        if (fire==1){beep(50,100);}\n        fire = 0;\n  } \n}\n\n// Drawing routine for the player and fire - with left-shifts\nvoid doDrawLS(long P1, byte P2) {\n  ssd1306_send_byte((B00001100&flameMask[flames] | P1)<<P2);\n  ssd1306_send_byte((B01011110&flameMask[flames] | P1)<<P2);\n  ssd1306_send_byte((B10010111&flameMask[flames] | P1)<<P2);\n  ssd1306_send_byte((B01010011&flameMask[flames] | P1)<<P2);\n  ssd1306_send_byte((B01010011&flameMask[flames] | P1)<<P2);\n  ssd1306_send_byte((B10010111&flameMask[flames] | P1)<<P2);\n  ssd1306_send_byte((B01011110&flameMask[flames] | P1)<<P2);\n  ssd1306_send_byte((B00001100&flameMask[flames] | P1)<<P2);  \n  \n  if (fireCount >0) {\n        for (byte f = 0; f<=24; f++){\n            ssd1306_send_byte(B00000100<<P2);\n        }\n        ssd1306_send_byte(B00010101<<P2);\n        //ssd1306_send_byte(B00001010<<P2);\n        ssd1306_send_byte(B00010101<<P2);\n        if (fire==1){beep(50,100);}\n        fire = 0;\n  }   \n}\n\n/* ------------------------\n *  Breakout Code\n */\nvoid playBreakout() {\n\n  lastFrame = millis();\n\n  for (byte i =0; i<16;i++){ // reset blocks\n    row[0][i]=1; row[1][i]=1; row[2][i]=1;\n  } \n  \n  platformWidth = 16;\n  ballx = 64;\n  bally = 50;\n  hdir = -1;\n  vdir = -1;\n  score = 0;\n  player = random(0,128-platformWidth);\n  ballx = player+platformWidth/2;\n  attachInterrupt(0,playerIncBreakOut,CHANGE);\n\n  while (stopAnimate == 0) {\n   delay(40);\n\n    while (1==1) {\n                // continue moving after the interrupt\n                if (digitalRead(2)==1){if (player <128-platformWidth){player++;} if (player <128-platformWidth){player++;} if (player <128-platformWidth){player++;}}\n                if (digitalRead(0)==1){if (player >0){player--;} if (player >0){player--;} if (player >0){player--;}}\n                \n                // bounce off the sides of the screen\n                if ((bally+vdir<54&&vdir==1)||(bally-vdir>1&&vdir==-1)){bally+=vdir;}else {vdir = vdir*-1;}\n                if ((ballx+hdir<127&&hdir==1)||(ballx-hdir>1&&hdir==-1)){ballx+=hdir;}else {hdir = hdir*-1;}\n                \n                // frame actions\n                if (lastFrame+10<millis()){\n                  if(bally>10&&bally+vdir>=54&&(ballx<player||ballx>player+platformWidth)){ // game over if the ball misses the platform\n   \n                    stopAnimate = 1;\n                    break;\n                  }else if (ballx<player+platformWidth/2&&bally>10&&bally+vdir>=54){ // if the ball hits left of the platform bounce left\n                    hdir=-1; beep(20,600);\n                  }else if (ballx>player+platformWidth/2&&bally>10&&bally+vdir>=54){  // if the ball hits right of the platform bounce right\n                    hdir=1; beep(20,600);\n                  }else if (bally+vdir>=54){\n                    hdir=1; beep(20,600);\n                  }\n                  \n                  collisionCheck: // go back to here if a collision was detected to prevent flying through a rigid\n                  if (floor((bally+vdir)/8)==2){\n                    if (row[2][ballx/8]==1){row[2][ballx/8]=0; score++;  \n                        collision(); goto collisionCheck; // check collision for the new direction to prevent flying through a rigid\n                    }\n                  }else if (floor((bally+vdir)/8)==1){\n                    if (row[1][ballx/8]==1){row[1][ballx/8]=0; score++; \n                        collision(); goto collisionCheck;\n                    }\n                  }else if (floor((bally+vdir)/8)==0){\n                    if (row[0][ballx/8]==1){row[0][ballx/8]=0; score++;\n                        collision(); goto collisionCheck;\n                    }\n                  }\n                  \n                  // reset blocks if all have been hit\n                  if (score%48==0){ \n                    for (byte i =0; i<16;i++){\n                     row[0][i]=1; row[1][i]=1; row[2][i]=1;\n                    } \n                  }\n                }\n                 \n                // update whats on the screen\n                noInterrupts();\n                \n                // blocks\n                for (int inc = 0; inc <3; inc ++) {\n                  ssd1306_setpos(0,inc);\n                  ssd1306_send_data_start();\n                  for (int bl = 0; bl <16; bl++){\n                    if(row[inc][bl]==1){\n                      sendBlock(1);\n                    }else {\n                      sendBlock(0);\n                    }\n                   }   \n                  ssd1306_send_data_stop();\n                }\n                \n                // clear area below the blocks\n                \n                for (int kl = 3;kl <8;kl++) {\n                  ssd1306_setpos(0,kl);\n                  ssd1306_send_data_start();\n                  for (byte i =0; i<128; i++){\n                     ssd1306_send_byte(B00000000);\n                  }\n                  ssd1306_send_data_stop();\n                }\n                // draw ball\n                ssd1306_setpos(ballx,bally/8);\n                uint8_t temp = B00000001;\n                ssd1306_send_data_start();\n                temp = temp << bally%8+1;\n                ssd1306_send_byte(temp);  \n                ssd1306_send_data_stop();\n                \n                drawPlatform();\n            interrupts();\n    }\n }\n  interrupts();\n\n  topScoreB = EEPROM.read(2);\n  topScoreB = topScoreB << 8;\n  topScoreB = topScoreB |  EEPROM.read(3);\n\n  if (score > topScoreB) { \n    topScoreB = score;\n    EEPROM.write(3,score & 0xFF); \n    EEPROM.write(2,(score>>8) & 0xFF); \n    newHigh = 1;\n    }\n  }\n\nvoid collision(){ // the collsision check is actually done befor this is called, this code works out where the ball will bounce\n  if ((bally+vdir)%8==7&&(ballx+hdir)%8==7){ // bottom right corner\n      if (vdir==1){hdir=1;}else if(vdir==-1&&hdir==1){vdir=1;}else {hdir=1;vdir=1;}\n    }else if ((bally+vdir)%8==7&&(ballx+hdir)%8==0){ // bottom left corner\n      if (vdir==1){hdir=-1;}else if(vdir==-1&&hdir==-1){vdir=1;}else {hdir=-1;vdir=1;}\n    }else if ((bally+vdir)%8==0&&(ballx+hdir)%8==0){ // top left corner\n      if (vdir==-1){hdir=-1;}else if(vdir==1&&hdir==-1){vdir=-1;}else {hdir=-1;vdir=-1;}\n    }else if ((bally+vdir)%8==0&&(ballx+hdir)%8==7){ // top right corner\n      if (vdir==-1){hdir=1;}else if(vdir==1&&hdir==1){vdir=-1;}else {hdir=1;vdir=-1;}\n    }else if ((bally+vdir)%8==7){ // bottom side\n      vdir = 1;\n    }else if ((bally+vdir)%8==0){ // top side\n      vdir = -1;\n    }else if ((ballx+hdir)%8==7){ // right side\n      hdir = 1;\n    }else if ((ballx+hdir)%8==0){ // left side\n      hdir = -1;\n    }else {\n      hdir = hdir*-1; vdir = vdir*-1;\n  }\n  beep(30,300);\n}\n\nvoid drawPlatform(){\n noInterrupts();\n ssd1306_setpos(player,7);\n ssd1306_send_data_start();\n for (byte pw = 1; pw <platformWidth; pw++){ssd1306_send_byte(B00000011);}                \n ssd1306_send_data_stop();  \n interrupts(); \n}\n\nvoid sendBlock(boolean fill){\n  if (fill==1){\n   ssd1306_send_byte(B00000000);\n   for (int inc = 0; inc < 6; inc++) ssd1306_send_byte(B01111110);\n   ssd1306_send_byte(B00000000);\n  }else {\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n  } \n}\n"
  },
  {
    "path": "UFO_Breakout_Arduino/font6x8AJ.h",
    "content": "/*\n * SSD1306xLED - Drivers for SSD1306 controlled dot matrix OLED/PLED 128x64 displays\n *\n * @file: font6x8.h\n * @created: 2014-08-12\n * @author: Neven Boyanov\n * \n * Hacked by andy jackson to allow two games (originally by webboggles.com) to \n * fit onto an ATTiny85 at the same time - hence several characters are missing\n * and a couple have been moved to limit the amount of software remapping required\n * to map ASCII values onto locations in this array.\n *\n * Source code available at: https://bitbucket.org/tinusaur/ssd1306xled\n *\n */\n\n// ----------------------------------------------------------------------------\n\n#include <avr/pgmspace.h>\n\n// ----------------------------------------------------------------------------\n\n/* Standard ASCII 6x8 font */\nstatic const uint8_t ssd1306xled_font6x8 [] PROGMEM = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sp\n/*\n  0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // !\n  0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // \"\n  0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // #\n  0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $\n  0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // %\n  0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // &\n  0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // '\n  0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // (\n  0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // )\n  0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // *\n  0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // +\n  0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // ,\n  */\n  0x00, 0x08, 0x08, 0x08, 0x08, 0x08, // -\n  0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // .\n  0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w in place of /\n  //0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // /\n  0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0\n  0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, // 1\n  0x00, 0x42, 0x61, 0x51, 0x49, 0x46, // 2\n  0x00, 0x21, 0x41, 0x45, 0x4B, 0x31, // 3\n  0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, // 4\n  0x00, 0x27, 0x45, 0x45, 0x45, 0x39, // 5\n  0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6\n  0x00, 0x01, 0x71, 0x09, 0x05, 0x03, // 7\n  0x00, 0x36, 0x49, 0x49, 0x49, 0x36, // 8\n  0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, // 9\n  0x00, 0x00, 0x36, 0x36, 0x00, 0x00, // :\n/*\n  0x00, 0x00, 0x56, 0x36, 0x00, 0x00, // ;\n  0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // <\n  0x00, 0x14, 0x14, 0x14, 0x14, 0x14, // =\n  0x00, 0x00, 0x41, 0x22, 0x14, 0x08, // >\n  0x00, 0x02, 0x01, 0x51, 0x09, 0x06, // ?\n  0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, // @\n */\n  0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, // B\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, // C\n  0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, // D\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, // E\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, // F\n  0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, // G\n  0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, // H\n  0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, // I\n  0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, // J\n  0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, // K\n  0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, // L\n  0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M\n  0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, // N\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, // O\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, // P\n  0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q\n  0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, // R\n  0x00, 0x46, 0x49, 0x49, 0x49, 0x31, // S\n  0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, // T\n  0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, // U\n  0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, // V\n  0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, // W\n/*\n  0x00, 0x63, 0x14, 0x08, 0x14, 0x63, // X\n  0x00, 0x07, 0x08, 0x70, 0x08, 0x07, // Y\n  0x00, 0x61, 0x51, 0x49, 0x45, 0x43, // Z\n  0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, // [\n  0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55, // 55\n  0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, // ]\n  0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^\n  0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _\n  0x00, 0x00, 0x01, 0x02, 0x04, 0x00, // '\n*/\n  0x00, 0x20, 0x54, 0x54, 0x54, 0x78, // a\n  0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, // b\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x20, // c\n  0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, // d\n  0x00, 0x38, 0x54, 0x54, 0x54, 0x18, // e\n  0x00, 0x08, 0x7E, 0x09, 0x01, 0x02, // f\n  0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g\n  0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C, // y (in place of h)\n  //0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h\n  0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, // i\n  0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, // j\n  0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, // k\n  0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, // l\n  0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, // m\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, // n\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x38, // o\n  0x00, 0xFC, 0x24, 0x24, 0x24, 0x18, // p\n  0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, // q\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, // r\n  0x00, 0x48, 0x54, 0x54, 0x54, 0x20, // s\n  0x00, 0x04, 0x3F, 0x44, 0x40, 0x20, // t\n  0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, // u\n  0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, // v\n // 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w\n // 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, // x\n // 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C // y\n};\n\n// ----------------------------------------------------------------------------\n\r\n"
  },
  {
    "path": "UFO_Stacker_Attiny/UFO_Stacker_Attiny.ino",
    "content": "/* 2015 / 2016 / 2017\n * Stacker game by Andy Jackson @andyhighnumber\n * UFO game by Ilya Titov. Find building instructions on http://webboggles.com/\n * \n * The code that does not fall under the licenses of sources listed below can be used non commercially with attribution.\n *\n * Modified by andy jackson to allow two games to fit into a single ATTiny85 at the same time.\n * Additional features:\n *  - To play Stacker - press and release left button\n *  - To play UFO - with the right button held, press and release left button \n *  - To turn sound on and off - press and HOLD left button\n *  - To reset high scores to zero - whilst HOLDING the right button, press and HOLD the left button\n * \n * If you have problems uploading this sketch, this is probably due to sketch size - you need to update ld.exe in arduino\\hardware\\tools\\avr\\avr\\bin\n * https://github.com/TCWORLD/ATTinyCore/tree/master/PCREL%20Patch%20for%20GCC\n *\n * This sketch is using the screen control and font functions written by Neven Boyanov for the http://tinusaur.wordpress.com/ project\n * Source code and font files available at: https://bitbucket.org/tinusaur/ssd1306xled\n * **Note that this highly size-optimised version requires modified library functions (which are in this source code file) \n * and a modified font header\n * \n * Sleep code is based on this blog post by Matthew Little:\n * http://www.re-innovation.co.uk/web12/index.php/en/blog-75/306-sleep-modes-on-attiny85\n*/\n#include <EEPROM.h>\n#include \"font6x8AJ.h\"\n#include <avr/sleep.h>\n#include <avr/interrupt.h> // needed for the additional interrupt\n\n#define DIGITAL_WRITE_HIGH(PORT) PORTB |= (1 << PORT)\n#define DIGITAL_WRITE_LOW(PORT) PORTB &= ~(1 << PORT)\n\n// Routines to set and clear bits (used in the sleep code)\n#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))\n#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))\n\n// Defines for OLED output\n#define SSD1306XLED_H\n#define SSD1306_SCL   PORTB4  // SCL, Pin 3 on SSD1306 Board\n#define SSD1306_SDA   PORTB3  // SDA, Pin 4 on SSD1306 Board\n#define SSD1306_SA    0x78  // Slave address\n\n// Function prototypes for UFO\nvoid beep(int,int);\nvoid playUFO(void);\n\n// Function prototypes for Stacker\nvoid resetBlocks(void);\nvoid drawRow(int thisRow, int location);\nvoid sendBlock(boolean);\nvoid playStacker(void);\nvoid beep(int,int);\nvoid levelUp(int);\n\n// Other function prototypes - for both\nvoid doNumber (int x, int y, int value);\nvoid ssd1306_init(void);\nvoid ssd1306_xfer_start(void);\nvoid ssd1306_xfer_stop(void);\nvoid ssd1306_send_byte(uint8_t byte);\nvoid ssd1306_send_command(uint8_t command);\nvoid ssd1306_send_data_start(void);\nvoid ssd1306_send_data_stop(void);\nvoid ssd1306_setpos(uint8_t x, uint8_t y);\nvoid ssd1306_fillscreen(uint8_t fill_Data);\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]);\nvoid ssd1306_draw_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t bitmap[]);\n\n// for UFO\nint obstacle[9] = {-50,-50,-50,-50,-50,-50,-50,-50,-50}; // x offset of the obstacle default position, out of view\nbyte gapOffset[9] = {0,0,0,0,0,0,0,0,0}; // y offset of the fly-through gap\nint gapSize[9]; // y height of the gap\nbyte maxGap = 60; // max height of the gap\nint stepsSinceLastObstacle = 0; // so obstacles are not too close\nbyte gapBlock[9] = {0,0,0,0,0,0,0,0,0}; // if the fly-through gap is closed\nint topScoreU = 0;\nboolean isStacker = 0;\nbyte maxObstacles = 1; // this defines the max number of in game obstacles\nbyte obstacleStep = 2; // pixel step of obstacles per frame\nbyte blockChance = 0; // this higher value decreases the likelihood of gap being closed \nbyte fireCount = 0; // the shot is persistent for several frames\nbyte playerOffset = 0; // y offset of the top of the player\nbyte flames = 0; // this is set to 1 when the move up interrupt is triggered\nbyte flameMask[2]={B00111111,B11111111}; // this is used to only show the flame part of the icon when moving up\nvoid doDrawLS(long, byte);\nvoid doDrawRS(long, byte);\n\n\n// For Stacker\nboolean perfect = 1;\nint runCounter = 0;\nboolean fireLock = 0;\nboolean fireCounterActive = 0;\nint fireCounter = 0;\nint level = 1; // Game level - incremented every time you clear the screen\nboolean blockDirection = 1; // current direction of travel for blocks - 1 is right 0 is left\nint stackRow = 0; // which row are we considering\nint movecounter = 0; // timer for movement\nint matchCount = 6;\nboolean row[2][16]; // on-off array of blocks - building up from the bottom\n\nboolean fire = 0;\nint topScoreB = 0;\nvolatile int player = 0; //0 to 128-platformWidth  - this is the position of the player\n\n// For both\nboolean stopAnimate = 0; // this is set to 1 when a collision is detected\nboolean mute = 0;\nboolean newHigh = 0;\nint score = 0; // score - this affects the difficulty of the game\nint top = 0;\n\n// Interrupt handlers\nISR(PCINT0_vect){ // PB0 pin button interrupt           \n}\nvoid playerIncUFO(){ // PB2 pin button interrupt\n   fire = 1;\n   fireCount = 5; // number of frames the shot will persist\n}\nvoid playerIncStacker(){ // PB2 pin button interrupt\n  \n}\n\n// Arduino stuff - setup\nvoid setup() {\n  DDRB = 0b00000010;    // set PB1 as output (for the speaker)\n  PCMSK = 0b00000001; // pin change mask: listen to portb bit 1\n  GIMSK |= 0b00100000;  // enable PCINT interrupt \n  sei();          // enable all interrupts\n}\n\n// Arduino stuff - loop\nvoid loop() { \n  isStacker = 1;\n  \n  if (digitalRead(2) == HIGH) isStacker = 0;\n  \n  //interrupts();\n  ssd1306_init();\n  ssd1306_fillscreen(0x00);\n  \n  if (isStacker) {\n    for (int j = 0;j<16;j++) {\n      row[0][j] = 0;\n    }\n    for (int i= 14;i<15;i++) {\n      row[0][i] = 1;\n    }\n    drawRow(0,2);\n  \n    for (int i= 13;i<15;i++) {\n      row[0][i] = 1;\n    }\n    drawRow(0,3);\n  \n    for (int i= 13;i<16;i++) {\n      row[0][i] = 1;\n    }\n    drawRow(0,4);\n  \n    for (int i= 13;i<16;i++) {\n      row[0][i] = 1;\n    }\n    drawRow(0,5);\n  \n    for (int i= 12;i<16;i++) {\n      row[0][i] = 1;\n    }\n    drawRow(0,6);\n  \n    for (int i= 12;i<16;i++) {\n      row[0][i] = 1;\n    }\n    drawRow(0,7);  \n\n    ssd1306_char_f6x8(0, 2, \"S T A C K E R\");\n    ssd1306_char_f6x8(0, 4, \"andh jackson\"); // see comments above !\n    ssd1306_char_f6x8(0, 6, \"inspired bh\");  // see comments above !\n    ssd1306_char_f6x8(0, 7, \"/ebboggles.com\");  // see comments above !\n  } else {\n    for (byte s = 0; s<30; s++){ // generate stars\n       ssd1306_setpos((uint8_t)(random(0,127)),(uint8_t)(random(0,7)) );\n       ssd1306_send_data_start();\n       ssd1306_send_byte(B10000000>>random(0,7)); \n       ssd1306_send_data_stop();\n    }\n    ssd1306_char_f6x8(14, 2, \"U F O  C H A O S\");\n    // The lower case character set is seriously compromised because I've had to truncate the ASCII table\n    // to release space for executable code - hence lower case y and w are remapped to h and / respectively.\n    // There is no z in the table (or h!) as these aren't used anywhere in the text here and most of the \n    // symbols are also missing for the same reason (see my hacked version of font6x8.h - font6x8AJ.h for more detail)\n    ssd1306_char_f6x8(3, 4, \"mods bh andh jackson\"); // see comments above !\n    ssd1306_char_f6x8(17, 6, \"original game bh\");  // see comments above !\n    ssd1306_char_f6x8(22, 7, \"/ebboggles.com\");  // see comments above !\n  }\n\n\n  long startT = millis();\n  long nowT =0;\n  boolean sChange = 0;\n  while(digitalRead(0) == HIGH) {\n    nowT = millis();\n    if (nowT - startT > 2000) {\n      sChange = 1;     \n      if (digitalRead(2) == HIGH) {\n        EEPROM.write(0,0);\n        EEPROM.write(1,0);\n        EEPROM.write(2,0);\n        EEPROM.write(3,0);      \n        ssd1306_char_f6x8(8, 0, \"-HIGH SCORE RESET-\");  \n      } else if (mute == 0) { mute = 1; ssd1306_char_f6x8(32, 0, \"-- MUTE --\"); } else { mute = 0; ssd1306_char_f6x8(23, 0, \"-- SOUND ON --\");  }    \n      break;\n    }\n    if (sChange == 1) break;\n  }  \n  while(digitalRead(0) == HIGH);\n\n  if (sChange == 0) {\n    delay(2600);\n    //noInterrupts();  \n    ssd1306_init();\n    ssd1306_fillscreen(0x00);\n    stopAnimate = 0;\n    score = 0;\n    \n    if (isStacker) { playStacker(); top=topScoreB;} else { playUFO(); top=topScoreU;}\n    \n    ssd1306_fillscreen(0x00);\n    ssd1306_char_f6x8(11, 1, \"----------------\");\n    ssd1306_char_f6x8(11, 2, \"G A M E  O V E R\");\n    ssd1306_char_f6x8(11, 3, \"----------------\");\n    ssd1306_char_f6x8(37, 5, \"SCORE:\");\n    doNumber(75, 5, score);\n    if (!newHigh) {\n      ssd1306_char_f6x8(21, 7, \"HIGH SCORE:\");\n      doNumber(88, 7, top);\n    }\n    for (int i = 0; i<1000; i = i+ 50){\n      beep(50,i);\n    }\n    delay(2000);\n    if (newHigh) {\n      ssd1306_fillscreen(0x00);\n      ssd1306_char_f6x8(10, 1, \"----------------\");\n      ssd1306_char_f6x8(10, 3,  \" NEW HIGH SCORE \");\n      ssd1306_char_f6x8(10, 7, \"----------------\");\n      doNumber(50,5,top);\n      for (int i = 700; i>200; i = i - 50){\n      beep(30,i);\n      }\n      newHigh = 0;\n      delay(2700);    \n    } \n  }\n  system_sleep();\n  //noInterrupts();  \n}\n\nvoid doNumber (int x, int y, int value) {\n    char temp[10] = {0,0,0,0,0,0,0,0,0,0};\n    itoa(value,temp,10);\n    ssd1306_char_f6x8(x, y, temp);\n}\n\nvoid ssd1306_init(void){\n  DDRB |= (1 << SSD1306_SDA); // Set port as output\n  DDRB |= (1 << SSD1306_SCL); // Set port as output\n\n  ssd1306_send_command(0xAE); // display off\n  ssd1306_send_command(0x00); // Set Memory Addressing Mode\n  ssd1306_send_command(0x10); // 00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid\n  ssd1306_send_command(0x40); // Set Page Start Address for Page Addressing Mode,0-7\n  ssd1306_send_command(0x81); // Set COM Output Scan Direction\n  ssd1306_send_command(0xCF); // ---set low column address\n  ssd1306_send_command(0xA1); // ---set high column address\n  ssd1306_send_command(0xC8); // --set start line address\n  ssd1306_send_command(0xA6); // --set contrast control register\n  ssd1306_send_command(0xA8);\n  ssd1306_send_command(0x3F); // --set segment re-map 0 to 127\n  ssd1306_send_command(0xD3); // --set normal display\n  ssd1306_send_command(0x00); // --set multiplex ratio(1 to 64)\n  ssd1306_send_command(0xD5); // \n  ssd1306_send_command(0x80); // 0xa4,Output follows RAM content;0xa5,Output ignores RAM content\n  ssd1306_send_command(0xD9); // -set display offset\n  ssd1306_send_command(0xF1); // -not offset\n  ssd1306_send_command(0xDA); // --set display clock divide ratio/oscillator frequency\n  ssd1306_send_command(0x12); // --set divide ratio\n  ssd1306_send_command(0xDB); // --set pre-charge period\n  ssd1306_send_command(0x40); // \n  ssd1306_send_command(0x20); // --set com pins hardware configuration\n  ssd1306_send_command(0x02);\n  ssd1306_send_command(0x8D); // --set vcomh\n  ssd1306_send_command(0x14); // 0x20,0.77xVcc\n  ssd1306_send_command(0xA4); // --set DC-DC enable\n  ssd1306_send_command(0xA6); // \n  ssd1306_send_command(0xAF); // --turn on oled panel \n}\n\nvoid ssd1306_xfer_start(void){\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n}\n\nvoid ssd1306_xfer_stop(void){\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n}\n\nvoid ssd1306_send_byte(uint8_t byte){\n  uint8_t i;\n  for(i=0; i<8; i++)\n  {\n    if((byte << i) & 0x80)\n      DIGITAL_WRITE_HIGH(SSD1306_SDA);\n    else\n      DIGITAL_WRITE_LOW(SSD1306_SDA);\n    \n    DIGITAL_WRITE_HIGH(SSD1306_SCL);\n    DIGITAL_WRITE_LOW(SSD1306_SCL);\n  }\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);\n  DIGITAL_WRITE_LOW(SSD1306_SCL);\n}\n\nvoid ssd1306_send_command(uint8_t command){\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  // Slave address, SA0=0\n  ssd1306_send_byte(0x00);  // write command\n  ssd1306_send_byte(command);\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_send_data_start(void){\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);\n  ssd1306_send_byte(0x40);  //write data\n}\n\nvoid ssd1306_send_data_stop(void){\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_setpos(uint8_t x, uint8_t y)\n{\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  //Slave address,SA0=0\n  ssd1306_send_byte(0x00);  //write command\n\n  ssd1306_send_byte(0xb0+y);\n  ssd1306_send_byte(((x&0xf0)>>4)|0x10); // |0x10\n  ssd1306_send_byte((x&0x0f)|0x01); // |0x01\n\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_fillscreen(uint8_t fill_Data){\n  uint8_t m,n;\n  for(m=0;m<8;m++)\n  {\n    ssd1306_send_command(0xb0+m); //page0-page1\n    ssd1306_send_command(0x00);   //low column start address\n    ssd1306_send_command(0x10);   //high column start address\n    ssd1306_send_data_start();\n    for(n=0;n<128;n++)\n    {\n      ssd1306_send_byte(fill_Data);\n    }\n    ssd1306_send_data_stop();\n  }\n}\n\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]){\n  uint8_t c,i,j=0;\n  while(ch[j] != '\\0')\n  {\n    c = ch[j] - 32;\n    if (c >0) c = c - 12;\n    if (c >15) c = c - 6;\n    if (c>40) c=c-9;\n    if(x>126)\n    {\n      x=0;\n      y++;\n    }\n    ssd1306_setpos(x,y);\n    ssd1306_send_data_start();\n    for(i=0;i<6;i++)\n    {\n      ssd1306_send_byte(pgm_read_byte(&ssd1306xled_font6x8[c*6+i]));\n    }\n    ssd1306_send_data_stop();\n    x += 6;\n    j++;\n  }\n}\n\nvoid system_sleep() {\n  ssd1306_fillscreen(0x00);\n  ssd1306_send_command(0xAE);\n  cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF\n  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here\n  sleep_enable();\n  sleep_mode();                        // System actually sleeps here\n  sleep_disable();                     // System continues execution here when watchdog timed out \n  sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON  \n  ssd1306_send_command(0xAF);\n}\n\nvoid beep(int bCount,int bDelay){\n  if (mute) return;\n  for (int i = 0; i<=bCount; i++){digitalWrite(1,HIGH);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}digitalWrite(1,LOW);for(int i2=0; i2<bDelay; i2++){__asm__(\"nop\\n\\t\");}}\n}\n\n/* ------------------------\n *  UFO Code\n */\n\nvoid playUFO(void) {\n  int fireLock = 0;\n  fire = 0;\n  maxObstacles = 3;\n  obstacleStep = 2;\n  for (byte i = 0; i<9; i++){\n    obstacle[i] = -50;\n    gapOffset[i]=0;\n  }\n  stepsSinceLastObstacle = 0;\n  playerOffset = 0; // y offset of the top of the player\n  fireLock = 0;\n  \n  while (stopAnimate == 0) {\n\n  // deal with inputs\n  if(analogRead(0) < 940) { \n    if (fireLock == 0) {\n      fire =1; fireCount = 5;\n      fireLock = 1;\n    } \n  } else fireLock = 0;\n\n\n  attachInterrupt(0,playerIncUFO,RISING);\n     \n  //update game vars to make it harder to play\n  if (score < 500){blockChance = 11-score/50; if (maxObstacles<5){maxObstacles=(score+40)/70+1;} delayMicroseconds(16000/maxObstacles);}\n  \n  if (score < 2000){maxGap = 60-score/100;}\n  if (fire == 1){score--;}\n  if (fireCount>0){fireCount--;}\n\n  for (int boo = 0; boo<3;boo++) {\n    if (digitalRead(0)==1){\n      if (playerOffset >0){\n        playerOffset--; \n        flames = 1; // move player up\n        for (int i = 0; i<2; i++){\n          beep(1,random(0,i*2));\n        }\n      }\n    }\n  }\n  \n  stepsSinceLastObstacle += obstacleStep;\n  for (byte i = 0; i<maxObstacles;i++){ // fly obstacles\n  if (obstacle[i] >= 0 && obstacle[i] <= 128){\n  obstacle[i] -= obstacleStep;\n  if (gapBlock[i]>0 && obstacle[i] < 36  && playerOffset>gapOffset[i] && playerOffset+5<gapOffset[i]+gapSize[i] && fireCount > 0){//\n   gapBlock[i] = 0;\n   score += 5; \n   for (byte cp = 400; cp>0; cp--){\n     beep(1,cp);\n   }\n  }\n  } \n  \n  if (obstacle[i]<=4 && stepsSinceLastObstacle>=random(30,100)){ // generate new obstacles\n  obstacle[i] = 123;\n  gapSize[i] = random(25,maxGap);\n  gapOffset[i] = random(0,64-gapSize[i]);\n  if (random(0,blockChance)==0){gapBlock[i] = 1;}else {gapBlock[i] = 0;}\n  stepsSinceLastObstacle = 0;\n  score+=1;\n  }\n  }\n  \n  if ( (fireCount == 0) && (playerOffset < 56) ){playerOffset++;} // player gravit\n  \n  // update what's on the screen\n  // erase player\n  for (byte r=0; r<8; r++){\n  if (r<playerOffset/8 | r >= playerOffset/8+1) {\n    ssd1306_setpos(0,r);\n    ssd1306_send_data_start();\n    sendBlock(0);\n    sendBlock(0);\n    ssd1306_send_data_stop();\n    }\n  }\n  \n  //erase fire\n  ssd1306_setpos(16,playerOffset/8);\n  ssd1306_send_data_start();\n  if (fireCount == 0){\n            for (byte f = 0; f<=30; f++){\n                ssd1306_send_byte(B00000000);\n            }\n  }\n  ssd1306_send_data_stop();\n  \n  // Send Obstacle\n  for (byte i = 0; i<maxObstacles;i++){\n  if (obstacle[i] >= -5 && obstacle[i] <= 128){ // only deal with visible obstacles\n  if (obstacle[i] > 8 && obstacle[i] <16){ // look for collision if obstacle is near the player\n    if (playerOffset < gapOffset[i] || playerOffset+5 > gapOffset[i]+gapSize[i] || gapBlock[i] != 0){\n      // collision - stop looping\n      stopAnimate = 1; \n    }\n  }                      \n  \n  for (byte row = 0; row <8; row++){\n      ssd1306_setpos(obstacle[i],row);\n      ssd1306_send_data_start();\n      \n      if (obstacle[i]>0&&obstacle[i] < 128){\n         \n         if ((row+1)*8 - gapOffset[i] <= 8){ // generate obstacle : top and transition\n            byte temp = B11111111>>((row+1)*8 - gapOffset[i]); \n            byte tempB = B00000000; \n            if (gapBlock[i]>0){tempB=B10101010;}\n            ssd1306_send_byte(temp);\n            ssd1306_send_byte(temp|tempB>>1);\n            ssd1306_send_byte(temp|tempB);\n            ssd1306_send_byte(temp);\n            \n         }else if (row*8>=gapOffset[i] && (row+1)*8<=gapOffset[i]+gapSize[i]){ // middle gap\n            byte tempB = B00000000; \n            if (gapBlock[i]>0){tempB=B10101010;}\n            ssd1306_send_byte(B00000000);\n            ssd1306_send_byte(B00000000|tempB>>1);\n            ssd1306_send_byte(B00000000|tempB);\n            ssd1306_send_byte(B00000000);\n  \n         }else if ((gapOffset[i] +gapSize[i]) >= row*8 && (gapOffset[i] +gapSize[i]) <= (row+1)*8){ // bottom transition\n            //}else if ((gapOffset[i] +gapSize[i]) >= row*8 && (gapOffset[i] +gapSize[i]) <= (row+1)*8){ // bottom transition\n            //byte temp = B11111111<<((gapOffset[i] + gapSize[i])%8); \n            \n            byte temp = B11111111<<((gapOffset[i] + gapSize[i])%8); \n            byte tempB = B00000000; \n            if (gapBlock[i]>0){tempB=B10101010;}\n            ssd1306_send_byte(temp);\n            ssd1306_send_byte(temp|tempB>>1);\n            ssd1306_send_byte(temp|tempB);\n            ssd1306_send_byte(temp);\n            \n         }else { // fill rest of obstacle\n            ssd1306_send_byte(B11111111);\n            ssd1306_send_byte(B11111111);\n            ssd1306_send_byte(B11111111);\n            ssd1306_send_byte(B11111111);\n         }\n         \n         ssd1306_send_byte(B00000000);\n         ssd1306_send_byte(B00000000);\n         \n      ssd1306_send_data_stop();\n      }\n    }\n  \n  }\n  }\n   \n  if (playerOffset%8!=0){\n    ssd1306_setpos(8,playerOffset/8);\n    ssd1306_send_data_start();\n    doDrawLS(0,playerOffset%8);\n    ssd1306_send_data_stop();\n    \n    ssd1306_setpos(8,playerOffset/8+1);\n    ssd1306_send_data_start();\n    doDrawRS(0,8-playerOffset%8);\n    ssd1306_send_data_stop();\n  } else {\n    ssd1306_setpos(8,playerOffset/8);\n    ssd1306_send_data_start();\n    doDrawLS(0,0);\n    ssd1306_send_data_stop();\n  }\n\n  // Display score in the screen corner\n  doNumber(92, 0, score);\n  \n  flames = 0;\n  //interrupts();\n  } // while stopanimate == 0\n\n  topScoreU = EEPROM.read(0);\n  topScoreU = topScoreU << 8;\n  topScoreU = topScoreU |  EEPROM.read(1);\n  \n  if (score > topScoreU) {\n    topScoreU = score;\n    EEPROM.write(1,score & 0xFF); \n    EEPROM.write(0,(score>>8) & 0xFF); \n    newHigh = 1;\n  }\n}\n\n// Drawing routine for the player and fire - with right-shifts\nvoid doDrawRS(long P1, byte P2) {\n  ssd1306_send_byte((B00001100&flameMask[flames] | P1)>>P2);\n  ssd1306_send_byte((B01011110&flameMask[flames] | P1)>>P2);\n  ssd1306_send_byte((B10010111&flameMask[flames] | P1)>>P2);\n  ssd1306_send_byte((B01010011&flameMask[flames] | P1)>>P2);\n  ssd1306_send_byte((B01010011&flameMask[flames] | P1)>>P2);\n  ssd1306_send_byte((B10010111&flameMask[flames] | P1)>>P2);\n  ssd1306_send_byte((B01011110&flameMask[flames] | P1)>>P2);\n  ssd1306_send_byte((B00001100&flameMask[flames] | P1)>>P2);  \n  \n  if (fireCount >0) {\n        for (byte f = 0; f<=24; f++){\n            ssd1306_send_byte(B00000100>>P2);\n        }\n        ssd1306_send_byte(B00010101>>P2);\n        //ssd1306_send_byte(B00001010>>P2);\n        ssd1306_send_byte(B00010101>>P2);\n        if (fire==1){beep(50,100);}\n        fire = 0;\n  } \n}\n\n// Drawing routine for the player and fire - with left-shifts\nvoid doDrawLS(long P1, byte P2) {\n  ssd1306_send_byte((B00001100&flameMask[flames] | P1)<<P2);\n  ssd1306_send_byte((B01011110&flameMask[flames] | P1)<<P2);\n  ssd1306_send_byte((B10010111&flameMask[flames] | P1)<<P2);\n  ssd1306_send_byte((B01010011&flameMask[flames] | P1)<<P2);\n  ssd1306_send_byte((B01010011&flameMask[flames] | P1)<<P2);\n  ssd1306_send_byte((B10010111&flameMask[flames] | P1)<<P2);\n  ssd1306_send_byte((B01011110&flameMask[flames] | P1)<<P2);\n  ssd1306_send_byte((B00001100&flameMask[flames] | P1)<<P2);  \n  \n  if (fireCount >0) {\n        for (byte f = 0; f<=24; f++){\n            ssd1306_send_byte(B00000100<<P2);\n        }\n        ssd1306_send_byte(B00010101<<P2);\n        //ssd1306_send_byte(B00001010<<P2);\n        ssd1306_send_byte(B00010101<<P2);\n        if (fire==1){beep(50,100);}\n        fire = 0;\n  }   \n}\n\n/* ------------------------\n *  Stacker Code\n */\nvoid playStacker() {\n  runCounter = 0;\n  movecounter = 0;\n  level = 1; // Game level - incremented every time you clear the screen\n  blockDirection = 1; // current direction of travel for blocks - 1 is right 0 is left\n  stackRow = 6; // what's the index of the current active row (0 is the top line, 7 is the bottom)?\n  topScoreB = 0; // highscore\n  fire = 0; // make sure no fire\n  score = 0; // obvious\n  matchCount = 6;\n  fireLock = 0;\n  fireCounterActive = 0;\n  fireCounter = 0;\n  perfect = 1;\n\n  resetBlocks();\n \n  //attachInterrupt(0,playerIncStacker,CHANGE);\n  \n  // draw base row\n  drawRow(1,7);\n\n  while (stopAnimate == 0) {\n    while(1) {\n    movecounter++;\n\n    doNumber(0,7,score);\n\n    // All this stuff is a complex debounce on the fire/trigger button\n    if (fireCounterActive) fireCounter++;\n    if ( (fireCounter >= 10) && fireCounterActive ) {\n      fireCounterActive = 0;\n      fireLock = 0;\n      fire = 0;\n    }\n        \n    if(digitalRead(2)==1) {\n      while(digitalRead(2)==1);\n      fire = 1;\n    }\n\n    if(digitalRead(0)==1){\n      while(digitalRead(0)==1);\n      fire = 1;\n    }\n\n    if(analogRead(0) < 940) {\n      while(analogRead(0) < 940);\n      fire = 1;\n    }\n\n    drawRow(0,stackRow);     \n\n\n    // Fire / stop the blocks!\n    if ( (fireLock == 0) && (fire == 1) ) { // fire has been pressed - do stuff - check for alignment, update the array and decrement active row\n      int matchTarget = matchCount;\n      runCounter = 0;\n      matchCount = 0;\n      for (int i = 0; i<16;i++) {\n        if (row[1][i] == 1) {\n          if (row[0][i] == 1) {\n            matchCount++;\n            row[1][i] = 1;\n          } else {\n            row[1][i] = 0;\n          }\n        }\n      }\n      if (matchCount < matchTarget) perfect = 0;\n\n      // draw stack row - now fixed\n      drawRow(1,stackRow);\n                                          \n      stackRow--;\n\n      if (matchCount>0 ) {\n        score+= (7-stackRow);\n        beep(50,300);\n      }\n      fireLock = 1; // lock fire until the button is lifted and the timeout is done\n      fire = 0;\n      fireCounter = 0;\n      fireCounterActive = 1;\n\n      // fill the next row (unless we're already at the top! - arduino hates attempts to access arrays with negative indices\n      if (stackRow >=0) {\n        for (int i=0;i<matchCount;i++) {\n          row[0][i] =1;\n        } \n        for (int i=matchCount; i<16;i++) {\n          row[0][i] =0;\n        }\n      }\n    } // end of fire routine\n   \n    // Move the blocks\n    int speedNow = 13-level;\n    if (speedNow < 4) speedNow = 4;\n    if (movecounter >= speedNow) {\n        movecounter = 0;\n      if(blockDirection) { // Moving right\n        if (row[0][15] == 1) { // we've hit the end\n          runCounter++;\n          if (runCounter > 20) { // runCounter kills the game if no activity for 20 cycles\n            stopAnimate = 1;     // this is to prevent the battery being drained if the game is accidentally started\n            break;\n          }\n\n          blockDirection = 0;\n        } else {\n          for(int i=15;i>0;i--) { // shuffle right\n            row[0][i] = row[0][i-1];\n          } \n          row[0][0] = 0;          \n        }\n      } else { // Moving left\n\n        if (row[0][0] == 1) { // we've hit the end\n          blockDirection = 1;\n        } else {\n          for(int i=0;i<15;i++) { // shuffle left\n            row[0][i] = row[0][i+1];\n          } \n          row[0][15] = 0;          \n        }\n      } \n    }\n\n    if(matchCount == 0) { // deal with failure here \n      stopAnimate = 1;\n      break;\n    }\n\n    // Level up\n    if (stackRow < 0) {\n      if (level <6) {\n        matchCount = 6;\n      } else if (level < 9) {\n        matchCount = 5;\n      } else if (level < 12) {\n        matchCount = 4;\n      } else if (level < 15) {\n        matchCount = 3;\n      } else {\n        matchCount = 2;\n      }\n      fireCounter = 0;\n      fireLock = 0;\n      fireCounterActive = 0;\n      movecounter=0;\n      stackRow = 6;\n      level++;\n      levelUp(level);\n      blockDirection = 1;\n      perfect = 1;\n      resetBlocks();\n      fire =0;\n      \n      // draw base row\n      drawRow(1,7);\n\n      for (int i = 700; i>100; i = i - 100){\n      beep(30,i);\n      }\n    }\n   }\n }\ndie:\n  topScoreB = EEPROM.read(2);\n  topScoreB = topScoreB << 8;\n  topScoreB = topScoreB |  EEPROM.read(3);\n\n  if (score > topScoreB) { \n    topScoreB = score;\n    EEPROM.write(3,score & 0xFF); \n    EEPROM.write(2,(score>>8) & 0xFF); \n    newHigh = 1;\n    }\n  }\n\nvoid levelUp(int number) {\n  ssd1306_fillscreen(0x00);\n  ssd1306_char_f6x8(16, 1, \"--------------\");\n  ssd1306_char_f6x8(16, 2, \" L E V E L \");\n  ssd1306_char_f6x8(16, 3, \"--------------\");\n  if (perfect) {\n     ssd1306_char_f6x8(25, 5, \"PERFECT LEVEL\");\n     ssd1306_char_f6x8(25, 7, \"  100 BONUS\");\n     score += 100;\n  }\n  doNumber(85,2,number);\n  for (int i = 800; i>200; i = i - 200){\n  beep(30,i);\n  }\n  delay(1500);    \n  ssd1306_fillscreen(0x00);\n}\n\nvoid resetBlocks(void) {\n  for (byte j = 0;j<16;j++) {\n    row[0][j] = 0;\n  }\n  for (byte j = 0;j<16;j++) {\n    row[1][j] = 0;\n  }\n\n  for (int i=6;i<6+matchCount;i++) {\n    row[1][i] = 1;\n  }\n  \n  for (int i=0;i<matchCount;i++) {\n    row[0][i] =1;\n  }\n}\n\n\nvoid drawRow(int thisRow, int location) {\n  if (thisRow <0) return;\n  if (thisRow>1) return;\n  ssd1306_setpos(0,location);\n  ssd1306_send_data_start();\n  for(int j=0;j<16;j++) {\n    if (row[thisRow][j] == 1) {\n      sendBlock(1);\n    } else {\n      sendBlock(0);\n    }\n  }\n  ssd1306_send_data_stop();                    \n}\n\n\nvoid sendBlock(boolean fill){\n  if (fill==1){\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B01111110);\n   ssd1306_send_byte(B01111110);\n   ssd1306_send_byte(B01111110);\n   ssd1306_send_byte(B01111110);\n   ssd1306_send_byte(B01111110);\n   ssd1306_send_byte(B01111110);\n   ssd1306_send_byte(B00000000);\n  }else {\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n   ssd1306_send_byte(B00000000);\n  } \n}\n\n\n\r\n"
  },
  {
    "path": "UFO_Stacker_Attiny/font6x8AJ.h",
    "content": "/*\n * SSD1306xLED - Drivers for SSD1306 controlled dot matrix OLED/PLED 128x64 displays\n *\n * @file: font6x8.h\n * @created: 2014-08-12\n * @author: Neven Boyanov\n * \n * Hacked by andy jackson to allow two games (originally by webboggles.com) to \n * fit onto an ATTiny85 at the same time - hence several characters are missing\n * and a couple have been moved to limit the amount of software remapping required\n * to map ASCII values onto locations in this array.\n *\n * Source code available at: https://bitbucket.org/tinusaur/ssd1306xled\n *\n */\n\n// ----------------------------------------------------------------------------\n\n#include <avr/pgmspace.h>\n\n// ----------------------------------------------------------------------------\n\n/* Standard ASCII 6x8 font */\nstatic const uint8_t ssd1306xled_font6x8 [] PROGMEM = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sp\n/*\n  0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // !\n  0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // \"\n  0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // #\n  0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $\n  0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // %\n  0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // &\n  0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // '\n  0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // (\n  0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // )\n  0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // *\n  0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // +\n  0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // ,\n  */\n  0x00, 0x08, 0x08, 0x08, 0x08, 0x08, // -\n  0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // .\n  0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w in place of /\n  //0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // /\n  0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0\n  0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, // 1\n  0x00, 0x42, 0x61, 0x51, 0x49, 0x46, // 2\n  0x00, 0x21, 0x41, 0x45, 0x4B, 0x31, // 3\n  0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, // 4\n  0x00, 0x27, 0x45, 0x45, 0x45, 0x39, // 5\n  0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6\n  0x00, 0x01, 0x71, 0x09, 0x05, 0x03, // 7\n  0x00, 0x36, 0x49, 0x49, 0x49, 0x36, // 8\n  0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, // 9\n  0x00, 0x00, 0x36, 0x36, 0x00, 0x00, // :\n/*\n  0x00, 0x00, 0x56, 0x36, 0x00, 0x00, // ;\n  0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // <\n  0x00, 0x14, 0x14, 0x14, 0x14, 0x14, // =\n  0x00, 0x00, 0x41, 0x22, 0x14, 0x08, // >\n  0x00, 0x02, 0x01, 0x51, 0x09, 0x06, // ?\n  0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, // @\n */\n  0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, // B\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, // C\n  0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, // D\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, // E\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, // F\n  0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, // G\n  0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, // H\n  0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, // I\n  0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, // J\n  0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, // K\n  0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, // L\n  0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M\n  0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, // N\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, // O\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, // P\n  0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q\n  0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, // R\n  0x00, 0x46, 0x49, 0x49, 0x49, 0x31, // S\n  0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, // T\n  0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, // U\n  0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, // V\n  0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, // W\n/*\n  0x00, 0x63, 0x14, 0x08, 0x14, 0x63, // X\n  0x00, 0x07, 0x08, 0x70, 0x08, 0x07, // Y\n  0x00, 0x61, 0x51, 0x49, 0x45, 0x43, // Z\n  0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, // [\n  0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55, // 55\n  0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, // ]\n  0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^\n  0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _\n  0x00, 0x00, 0x01, 0x02, 0x04, 0x00, // '\n*/\n  0x00, 0x20, 0x54, 0x54, 0x54, 0x78, // a\n  0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, // b\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x20, // c\n  0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, // d\n  0x00, 0x38, 0x54, 0x54, 0x54, 0x18, // e\n  //0x00, 0x08, 0x7E, 0x09, 0x01, 0x02, // f\n  0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h in place of f\n  0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g\n  0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C, // y (in place of h)\n  //0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h\n  0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, // i\n  0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, // j\n  0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, // k\n  0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, // l\n  0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, // m\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, // n\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x38, // o\n  0x00, 0xFC, 0x24, 0x24, 0x24, 0x18, // p\n  0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, // q\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, // r\n  0x00, 0x48, 0x54, 0x54, 0x54, 0x20, // s\n  0x00, 0x04, 0x3F, 0x44, 0x40, 0x20, // t\n  0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, // u\n  0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, // v\n // 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w\n // 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, // x\n // 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C // y\n};\n\n// ----------------------------------------------------------------------------\n\r\n"
  },
  {
    "path": "WrenRollercoasterAttinyArcade/WrenRollercoasterAttinyArcade.ino",
    "content": "/* 2015 / 2016 /2017\n   WREN ROLLERCOASTER game by Andy Jackson - Twitter @andyhighnumber\n        \n   Inspired by http://webboggles.com/ and includes some code from the #AttinyArcade games on that site\n   Also inspired by TinyWings(R) game for the iOS platform - if you like this (at all) you'll love that!\n   \n   The code that does not fall under the licenses of sources listed below can be used non commercially with attribution.\n\n   When the game is running :\n   LEFT BUTTON - Makes the bird stop flying (so it sinks - enabling slides in the valleys)\n   RIGHT BUTTON - Makes the bird flap (slightly) harder\n\n   Also, from standby....\n   Press and hold left button to toggle sound/mute\n   Press and hold both buttons together to reset high score\n\n   If you have problems uploading this sketch, this is probably due to sketch size - you need to update ld.exe in arduino\\hardware\\tools\\avr\\avr\\bin\n   https://github.com/TCWORLD/ATTinyCore/tree/master/PCREL%20Patch%20for%20GCC\n\n   This sketch is using the screen control and font functions written by Neven Boyanov for the http://tinusaur.wordpress.com/ project\n   Source code and font files available at: https://bitbucket.org/tinusaur/ssd1306xled    \n   **Note that this highly size-optimised version requires modified library functions (which are in this source code file) and a modified font header which you'll find in the same place you found this .ino file\n\n   Sleep code is based on this blog post by Matthew Little:\n   http://www.re-innovation.co.uk/web12/index.php/en/blog-75/306-sleep-modes-on-attiny85\n*/\n\n#include <EEPROM.h>\n#include <math.h>\n#include \"font6x8AJ.h\"\n#include <avr/sleep.h>\n#include <avr/interrupt.h> // needed for the additional interrupt\n\n#define DIGITAL_WRITE_HIGH(PORT) PORTB |= (1 << PORT)\n#define DIGITAL_WRITE_LOW(PORT) PORTB &= ~(1 << PORT)\n\n// Routines to set and clear bits (used in the sleep code)\n#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))\n#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))\n\n// Defines for OLED output\n#define SSD1306XLED_H\n#define SSD1306_SCL   PORTB4  // SCL, Pin 4 on SSD1306 Board - for webbogles board\n#define SSD1306_SDA   PORTB3  // SDA, Pin 3 on SSD1306 Board - for webbogles board\n#define SSD1306_SA    0x78  // Slave address\n\n#define WINSCORE 7\n\n// Function prototypes\nvoid sendBlock(int);\nvoid playBird(void);\nvoid beep(int, int);\nbyte doDrawLS(byte);\nbyte doDrawRS(byte);\nbyte doDrawLSP(byte, byte);\nbyte doDrawRSP(byte, byte);\nvoid drawBird(byte startRow, byte endRow);\nvoid drawLandscape(byte startRow, byte endRow);\n\nvoid doNumber (int x, int y, int value);\n\nvoid ssd1306_init(void);\nvoid ssd1306_xfer_start(void);\nvoid ssd1306_xfer_stop(void);\nvoid ssd1306_send_byte(uint8_t byte);\nvoid ssd1306_send_bit(void);\nvoid ssd1306_send_command(uint8_t command);\nvoid ssd1306_send_data_start(void);\nvoid ssd1306_send_data_stop(void);\nvoid ssd1306_setpos(uint8_t x, uint8_t y);\nvoid ssd1306_fillscreen(uint8_t fill_Data);\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]);\nvoid ssd1306_draw_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t bitmap[]);\nvoid drawPlayer(byte location);\nint playerOffset = 0; // y offset of the top of the player\n\n\nint score = 0;\nint top = 0;\n\nboolean newHigh = 0;\nboolean stopAnimate = 0; // this is set to 1 when a collision is detected\nboolean mute = 0;\n\nbyte landscape[128];\n\nbyte i;\nint totaldistance = 0;\nbyte interscore = 0;\nfloat incr;\nfloat start = 0.0;\nfloat si = 0.1;\nint gostep = 5;\nfloat height = 25.0;\nbyte lastPos = 0;\nint boost = 0;\nboolean onit = 0;\nint speedBoost = 0;\nboolean doneUpdate = 0;\n\n// Interrupt handlers\nISR(PCINT0_vect) { // PB0 pin button interrupt\n}\n\nvoid playerIncBird() { // PB2 pin button interrupt\n}\n\n// Arduino stuff - setup\nvoid setup() {\n  DDRB = 0b00000010;    // set PB1 as output (for the speaker)\n  PCMSK = 0b00000001; // pin change mask: listen to portb bit 1\n  GIMSK |= 0b00100000;  // enable PCINT interrupt\n  sei();          // enable all interrupts\n}\n\n// Arduino stuff - loop\nvoid loop() {\n  ssd1306_init();\n  ssd1306_fillscreen(0x00);\n\n  // The lower case character set is seriously compromised because I've had to truncate the ASCII table\n  // to release space for executable code - hence lower case y and w are remapped to h and / respectively.\n  // There is no z in the table (or h!) as these aren't used anywhere in the text here and most of the\n  // symbols are also missing for the same reason (see my hacked version of font6x8.h - font6x8AJ.h for more detail)\n  ssd1306_char_f6x8(8, 1, \"   --------------\");\n  ssd1306_char_f6x8(8, 2, \"    W R E N      \");\n  ssd1306_char_f6x8(8, 4, \"    ROLLERCOASTER\");\n  ssd1306_char_f6x8(8, 5, \"   --------------\");\n  ssd1306_char_f6x8(8, 7, \"    andh jackson \"); // see comments above !\n\n  long startT = millis();\n  long nowT =0;\n  boolean sChange = 0;\n  while(digitalRead(0) == HIGH) {\n    nowT = millis();\n    if (nowT - startT > 2000) {\n      sChange = 1;     \n      if (digitalRead(2) == HIGH) {\n        EEPROM.write(0,0);\n        EEPROM.write(1,0);\n        ssd1306_char_f6x8(8, 0, \"-HIGH SCORE RESET-\");  \n      } else if (mute == 0) { mute = 1; ssd1306_char_f6x8(32, 0, \"-- MUTE --\"); } else { mute = 0; ssd1306_char_f6x8(23, 0, \"-- SOUND ON --\");  }    \n      break;\n    }\n    if (sChange == 1) break;\n  }  \n  while(digitalRead(0) == HIGH);\n\n  if (sChange == 0) {\n    delay(400);\n\n    for (int k = 2; k>=0;k--){\n      for (playerOffset = 55; playerOffset>0+(k*10);playerOffset--) {\n        drawBird(0,8);\n        beep(2,200+playerOffset);\n        delay(2);\n      }\n      for (playerOffset = 0+(k*10); playerOffset<55;playerOffset++) {\n        drawBird(0,8);\n        beep(2,200+playerOffset);\n        delay(2);\n      }\n    }\n\n    delay(600);\n    ssd1306_init();\n    ssd1306_fillscreen(0x00);\n    stopAnimate = 0;\n\n    playBird();\n\n    ssd1306_fillscreen(0x00);\n    ssd1306_char_f6x8(11, 1, \"----------------\");\n    ssd1306_char_f6x8(11, 2, \"G A M E  O V E R\");\n    ssd1306_char_f6x8(11, 3, \"----------------\");\n    ssd1306_char_f6x8(37, 5, \"SCORE:\");\n    doNumber(75, 5, score);\n    for (int i = 700; i>200; i = i - 50){\n    beep(30,i);\n    };\n    if (!newHigh) {\n      ssd1306_char_f6x8(21, 7, \"HIGH SCORE:\");\n      doNumber(88, 7, top);\n    }\n    delay(2000);\n    if (newHigh) {\n      ssd1306_fillscreen(0x00);\n      ssd1306_char_f6x8(10, 1, \"----------------\");\n      ssd1306_char_f6x8(10, 3, \" NEW HIGH SCORE \");\n      ssd1306_char_f6x8(10, 7, \"----------------\");\n      doNumber(50,5,top);\n      for (int i = 700; i>200; i = i - 50){\n      beep(30,i);\n      }\n      newHigh = 0;\n      delay(2700);    \n    } \n  }\n  system_sleep();\n}\n\nvoid doNumber (int x, int y, int value) {\n  char temp[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\n  itoa(value, temp, 10);\n  ssd1306_char_f6x8(x, y, temp);\n}\n\nvoid ssd1306_init(void) {\n  DDRB |= (1 << SSD1306_SDA); // Set port as output\n  DDRB |= (1 << SSD1306_SCL); // Set port as output\n\n  ssd1306_send_command(0xAE); // display off\n  ssd1306_send_command(0x00); // Set Memory Addressing Mode\n  ssd1306_send_command(0x10); // 00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid\n  ssd1306_send_command(0x40); // Set Page Start Address for Page Addressing Mode,0-7\n  ssd1306_send_command(0x81); // Set COM Output Scan Direction\n  ssd1306_send_command(0xCF); // ---set low column address\n  ssd1306_send_command(0xA1); // ---set high column address\n  ssd1306_send_command(0xC8); // --set start line address\n  ssd1306_send_command(0xA6); // --set contrast control register\n  ssd1306_send_command(0xA8);\n  ssd1306_send_command(0x3F); // --set segment re-map 0 to 127\n  ssd1306_send_command(0xD3); // --set normal display\n  ssd1306_send_command(0x00); // --set multiplex ratio(1 to 64)\n  ssd1306_send_command(0xD5); //\n  ssd1306_send_command(0x80); // 0xa4,Output follows RAM content;0xa5,Output ignores RAM content\n  ssd1306_send_command(0xD9); // -set display offset\n  ssd1306_send_command(0xF1); // -not offset\n  ssd1306_send_command(0xDA); // --set display clock divide ratio/oscillator frequency\n  ssd1306_send_command(0x12); // --set divide ratio\n  ssd1306_send_command(0xDB); // --set pre-charge period\n  ssd1306_send_command(0x40); //\n  ssd1306_send_command(0x20); // --set com pins hardware configuration\n  ssd1306_send_command(0x02);\n  ssd1306_send_command(0x8D); // --set vcomh\n  ssd1306_send_command(0x14); // 0x20,0.77xVcc\n  ssd1306_send_command(0xA4); // --set DC-DC enable\n  ssd1306_send_command(0xA6); //\n  ssd1306_send_command(0xAF); // --turn on oled panel\n}\n\nvoid ssd1306_xfer_start(void) {\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n}\n\nvoid ssd1306_xfer_stop(void) {\n  DIGITAL_WRITE_LOW(SSD1306_SCL);   // Set to LOW\n  DIGITAL_WRITE_LOW(SSD1306_SDA);   // Set to LOW\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);  // Set to HIGH\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);  // Set to HIGH\n}\n\nvoid ssd1306_send_bit(boolean thisbit) {\n  if (thisbit) {\n    DIGITAL_WRITE_HIGH(SSD1306_SDA);\n  } else {\n    DIGITAL_WRITE_LOW(SSD1306_SDA);\n  }\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);\n  DIGITAL_WRITE_LOW(SSD1306_SCL);\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);\n  DIGITAL_WRITE_LOW(SSD1306_SCL);\n}\n\nvoid ssd1306_send_byte(uint8_t byte) {\n  uint8_t i;\n  for (i = 0; i < 8; i++)\n  {\n    if ((byte << i) & 0x80)\n      DIGITAL_WRITE_HIGH(SSD1306_SDA);\n    else\n      DIGITAL_WRITE_LOW(SSD1306_SDA);\n\n    DIGITAL_WRITE_HIGH(SSD1306_SCL);\n    DIGITAL_WRITE_LOW(SSD1306_SCL);\n  }\n  DIGITAL_WRITE_HIGH(SSD1306_SDA);\n  DIGITAL_WRITE_HIGH(SSD1306_SCL);\n  DIGITAL_WRITE_LOW(SSD1306_SCL);\n}\n\nvoid ssd1306_send_command(uint8_t command) {\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  // Slave address, SA0=0\n  ssd1306_send_byte(0x00);  // write command\n  ssd1306_send_byte(command);\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_send_data_start(void) {\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);\n  ssd1306_send_byte(0x40);  //write data\n}\n\nvoid ssd1306_send_data_stop(void) {\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_setpos(uint8_t x, uint8_t y)\n{\n  if (y > 7) return;\n  ssd1306_xfer_start();\n  ssd1306_send_byte(SSD1306_SA);  //Slave address,SA0=0\n  ssd1306_send_byte(0x00);  //write command\n\n  ssd1306_send_byte(0xb0 + y);\n  ssd1306_send_byte(((x & 0xf0) >> 4) | 0x10); // |0x10\n  ssd1306_send_byte((x & 0x0f) | 0x01); // |0x01\n\n  ssd1306_xfer_stop();\n}\n\nvoid ssd1306_fillscreen(uint8_t fill_Data) {\n  uint8_t m, n;\n  for (m = 0; m < 8; m++)\n  {\n    ssd1306_send_command(0xb0 + m); //page0-page1\n    ssd1306_send_command(0x00);   //low column start address\n    ssd1306_send_command(0x10);   //high column start address\n    ssd1306_send_data_start();\n    for (n = 0; n < 128; n++)\n    {\n      ssd1306_send_byte(fill_Data);\n    }\n    ssd1306_send_data_stop();\n  }\n}\n\nvoid ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]) {\n  uint8_t c, i, j = 0;\n  while (ch[j] != '\\0')\n  {\n    c = ch[j] - 32;\n    if (c > 0) c = c - 12;\n    if (c > 15) c = c - 6;\n    if (c > 40) c = c - 6;\n    if (x > 126)\n    {\n      x = 0;\n      y++;\n    }\n    ssd1306_setpos(x, y);\n    ssd1306_send_data_start();\n    for (i = 0; i < 6; i++)\n    {\n      ssd1306_send_byte(pgm_read_byte(&ssd1306xled_font6x8[c * 6 + i]));\n    }\n    ssd1306_send_data_stop();\n    x += 6;\n    j++;\n  }\n}\n\nvoid system_sleep() {\n  ssd1306_fillscreen(0x00);\n  ssd1306_send_command(0xAE);\n  cbi(ADCSRA, ADEN);                   // switch Analog to Digitalconverter OFF\n  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here\n  sleep_enable();\n  sleep_mode();                        // System actually sleeps here\n  sleep_disable();                     // System continues execution here when watchdog timed out\n  sbi(ADCSRA, ADEN);                   // switch Analog to Digitalconverter ON\n  ssd1306_send_command(0xAF);\n}\n\nvoid beep(int bCount, int bDelay) {\n  if (mute) return;\n  for (int i = 0; i <= bCount; i++) {\n    digitalWrite(1, HIGH);\n    for (int i2 = 0; i2 < bDelay; i2++) {\n      __asm__(\"nop\\n\\t\");\n    } digitalWrite(1, LOW);\n    for (int i2=0; i2<bDelay; i2++) {\n      __asm__(\"nop\\n\\t\");\n    }\n  }\n}\n\n\n/* ------------------------\n    Bird flying game code\n*/\nvoid playBird() {\n  \n  totaldistance = 0;\n  interscore = 0;\n  start = 3.14159265;\n  si = 0.05;\n  gostep = 5;\n  height = 20.0;\n  playerOffset = 0;\n  lastPos = 0;\n  boost = 0;\n  onit = 0;\n  speedBoost = 0;\n  doneUpdate = 0;\n  newHigh = 0;\n  score = 0;\n  totaldistance = 0;\n  int thisrun = 0;\n  \n  incr = start;\n  for (i = 0; i < 128; i++) {\n    float sinfactor = sin(incr);\n    landscape[i] = floor(62 - height + (height * sinfactor));\n    incr += si;\n  }\n  \n  randomSeed(0);\n  \n  while (stopAnimate == 0) {\n    // Total distance isn't really distance - it's a measure of how long the game's been running - used to stop the game\n    totaldistance++;\n\n    // Increment score every 10 cycles\n    interscore += gostep;\n    if (interscore >= 10) {\n      interscore = 0;\n      score++;\n    }\n\n    /*\n     * NORMAL BUTTON USE\n     */\n    // With the left button down - the bird falls and height (but not speed) boost is reduced faster than normal\n    if (digitalRead(0) == HIGH) {\n      thisrun++;\n      playerOffset += 2;\n      boost -=10;\n    } else {\n      thisrun = 0;\n    }\n    \n    if (onit && lastPos < playerOffset) {\n      speedBoost+=10;\n      boost+=7;\n      } else {\n      if (thisrun>30) {\n        boost-=thisrun;\n        speedBoost -= thisrun;\n      }\n      \n    }\n    lastPos = playerOffset;\n   \n\n    // With the right button pressed - the bird flaps (slightly slowing its descent)\n    if (digitalRead(2) == HIGH) {\n      playerOffset -= 1;\n    }\n\n    /*\n     *  HANDLING SLIDES AND OTHER ON-GROUND AND IN-AIR BEHAVIOUR\n     */\n    // Boost the speed and the height if you slide through the valleys\n    if ( (playerOffset > 45) && onit && digitalRead(0) == HIGH) {\n      boost +=75; // boost the flight\n      speedBoost+=100; // boost the speed\n      beep(1,350-speedBoost);\n    } else {\n      // The level of boost will keep the bird from falling (or even make it rise!)\n      playerOffset -= floor(boost / 40); // Apply boost whilst in the air\n    }\n    \n    // Cap speedboost!\n    if (speedBoost > 700) {\n      speedBoost = 700;\n    }\n\n    // Cap boost!\n    if (boost > 450) {\n      boost = 450;\n    }\n\n    // If you do nothing, the bird will gradually drop\n    playerOffset += 3;\n\n    // If you do nothing and you're in the air, the boost will drop\n    if ((boost > 0) && (onit != 1)) {\n      boost -=20;\n    }\n    if (boost < 0) boost = 0;\n\n    // If you do nothing, the speed boost will drop\n    if (speedBoost > 0) {\n      speedBoost -= 7;\n    }\n    if (speedBoost < 0) speedBoost = 0;\n\n    /*\n     * APPLY SPEEDBOOST TO THE SPEED \n     */\n    // This is the number of pixels the screen scrolls on each cycle of the game\n    gostep = floor(2+speedBoost/110);\n\n    // Detect whether the bird is on the ground\n    onit = 0;\n    if (playerOffset >= landscape[17] - 8) {\n      onit = 1;\n      playerOffset = landscape[17] - 8;\n    }\n    if (playerOffset <= 0) playerOffset = 0;\n\n    // Just keep iterating around between zero and 2pi (roughly)\n    if (incr >= 6.2831853) {\n      incr -= 6.2831853;\n    }\n\n    //shift landscape left gostep places\n    for (i = 0; i < 127 - gostep; i++) {\n      landscape[i] = landscape[i + gostep];\n    }\n\n    // fill in the rest of the landscape\n    for (i = 127 - gostep; i < 128; i++) {\n      float sinfactor = sin(incr);\n      if (sinfactor < -0.2) {\n        sinfactor = -0.2 - (-0.2-sinfactor)/2.0;\n      }\n      landscape[i] = floor(62 - height + (height * sinfactor));\n      if (sinfactor < 0.90) doneUpdate = 0;\n      if (sinfactor > 0.97) {\n        if (doneUpdate == 0) {\n          byte newheight = (random(7, 25));\n          while ( (newheight > height - 7) && (newheight < height + 7) ) newheight = (random(7, 25));\n          height = newheight;\n          si = (float)random(35,75)/1000.0;          \n          doneUpdate = 1;\n        }    \n      }\n\n      incr += si;\n    }\n\n    // Draw landscape and bird\n    drawLandscape(2,8);    \n    // Fill in the bird in the top couple of rows\n    drawBird(0,2);\n\n    /*\n     * Debug mode code for monitoring parameters \n     */\n     /*\n    ssd1306_char_f6x8(85, 0, \"    \");\n    ssd1306_char_f6x8(85, 1, \"    \");\n    doNumber(85, 0, speedBoost);\n    doNumber(85, 1, boost);\n    */\n\n    // Draw the score\n    doNumber(85, 0, score);\n\n    // Add time on to the game if the player is doing well\n    if (score == 950 && interscore == 0) {\n      totaldistance -=900;\n    } else if (score == 1450  && interscore == 0) {\n      totaldistance -=900;\n    } else if (score == 1950  && interscore == 0) {\n      totaldistance -=900;\n    } else if (score == 2400  && interscore == 0) {\n      totaldistance -=900;\n    }\n\n    if (totaldistance < 0) totaldistance = 0; // just in case - almost certainly would never happen!!\n\n    // Draw the bar indicating the time left\n    ssd1306_setpos(40, 0);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B11111111);\n    for (float sc = 1;sc < 0.016*(2000-totaldistance); sc += 1.0) {\n      ssd1306_send_byte(B10111101);\n    }\n    for (float sc = 0.016*(2000-totaldistance); sc<32; sc += 1.0) {\n      ssd1306_send_byte(B10000001);\n    }\n    ssd1306_send_byte(B11111111);    \n    ssd1306_send_data_stop();\n    ssd1306_setpos(56, 0);\n    ssd1306_send_data_start();\n    ssd1306_send_byte(B11111111);\n    ssd1306_send_data_stop();\n \n    if (totaldistance >= 2000) {\n\n      while (playerOffset < (landscape[17] - 8) ) {\n        drawBird(0,2);\n        drawLandscape(2,8);\n        playerOffset++;\n        delay(50);\n      }\n      \n      stopAnimate = 1;\n      delay(1000);\n    }\n  \n  }\n  delay(1500);\n  top = EEPROM.read(0);\n  top = top << 8;\n  top = top |  EEPROM.read(1);\n\n  if (score > top) { \n    top = score;\n    EEPROM.write(1,score & 0xFF); \n    EEPROM.write(0,(score>>8) & 0xFF); \n    newHigh = 1;\n    }\n}\n\nvoid sendBlock(int fill) {\n  ssd1306_send_byte(B00000000);\n  ssd1306_send_byte(B00000000);\n  ssd1306_send_byte(B00000000);\n  ssd1306_send_byte(B00000000);\n  ssd1306_send_byte(B00000000);\n  ssd1306_send_byte(B00000000);\n  ssd1306_send_byte(B00000000);\n  ssd1306_send_byte(B00000000);\n}\n\n\nbyte doDrawRS(byte P2) {\n  return(B00000011 >> P2);\n}\nbyte doDrawLS(byte P2) {\n  return(B00000011 << P2);\n}\n\n\nbyte doDrawRSP(byte column, byte P2) {\n  switch(column) {\n  case 0:\n  return((B00111111) >> P2);\n  break;\n  case 1:\n  return((B01111100) >> P2);\n  break;\n  case 2:\n  return((B11111110) >> P2);\n  break;\n  case 3:\n  return((B11100110) >> P2);\n  break;\n  case 4:\n  return((B01100110) >> P2);\n  break;\n  case 5:\n  return((B00111100) >> P2);\n  break;\n  case 6:\n  return((B00011000) >> P2);\n  break;\n  default:\n  return((B00010000) >> P2);\n  break;\n  }\n}\n\nbyte doDrawLSP(byte column, byte P2) {\n  switch(column) {\n  case 0:\n  return((B00111111) << P2);\n  break;\n  case 1:\n  return((B01111100) << P2);\n  break;\n  case 2:\n  return((B11111110) << P2);\n  break;\n  case 3:\n  return((B11100110) << P2);\n  break;\n  case 4:\n  return((B01100110) << P2);\n  break;\n  case 5:\n  return((B00111100) << P2);\n  break;\n  case 6:\n  return((B00011000) << P2);\n  break;\n  default:\n  return((B00010000) << P2);\n  break;\n  }\n}\n\nvoid drawBird(byte startRow, byte endRow) {\n    for (byte c = startRow; c < endRow; c++) {\n    ssd1306_setpos(8, c);\n    ssd1306_send_data_start();\n    for (byte r = 8; r<16; r++) {\n      int x = r;\n      // bird with LS only\n      if (c == playerOffset/8) {\n        ssd1306_send_byte(doDrawLSP(r-8, playerOffset % 8));\n      // bird with RS only\n      } else if (c == playerOffset/8 + 1) {\n        ssd1306_send_byte(doDrawRSP(r-8, 8- playerOffset % 8));\n      } else {\n        ssd1306_send_byte(B00000000);\n      }\n    }\n    ssd1306_send_data_stop();\n  }\n}\n\nvoid drawLandscape(byte startRow, byte endRow) {\n  // Draw the landscape and bird \n  for (byte c = startRow; c < endRow; c++) {\n    ssd1306_setpos(0, c);\n    ssd1306_send_data_start();\n    for (byte r = 0; r<127; r++) {\n      int x = r;\n      int y = landscape[r];\n      if (r<8 || r>15) {\n        if (c == y/8) {\n          ssd1306_send_byte(doDrawLS(y % 8));\n        } else if (c == y/8+1) {\n          ssd1306_send_byte(doDrawRS(8 - y % 8));\n        } else {\n          ssd1306_send_byte(B00000000);\n        }  \n      } else {\n        // landscape with LS only\n        if ( (c == y/8) && (c != playerOffset/8) && (c != playerOffset/8 + 1) ) {\n          ssd1306_send_byte(doDrawLS(y % 8));\n        // landscape with RS only  \n        } else if ( (c == y/8+1) && (c != playerOffset/8) && (c != playerOffset/8 + 1) ) {\n          ssd1306_send_byte(doDrawRS(8 - y % 8));\n        // bird with LS only  \n        } else if ( (c != y/8+1) && (c != y/8) && (c == playerOffset/8) ) {\n          ssd1306_send_byte(doDrawLSP(r-8, playerOffset % 8));\n        // bird with RS only\n        } else if ( (c != y/8+1) && (c != y/8) && (c == playerOffset/8 + 1) ) {\n          ssd1306_send_byte(doDrawRSP(r-8, 8- playerOffset % 8));\n        // both with LS\n        } else if ( (c == y/8) && (c == playerOffset/8) ) {\n          ssd1306_send_byte(doDrawLSP(r-8, playerOffset % 8) | doDrawLS(y % 8));            \n        // both with RS\n        } else if ( (c == y/8+1) && (c == playerOffset/8+1) ) {\n          ssd1306_send_byte(doDrawRSP(r-8, 8-playerOffset % 8) | doDrawRS(8- y % 8));            \n        // landscape left, bird right\n        } else if ( (c == y/8) && (c == playerOffset/8+1) ) {\n          ssd1306_send_byte(doDrawRSP(r-8, 8-playerOffset % 8) | doDrawLS(y % 8));            \n        // landscape right, bird left\n        } else if ( (c == y/8+1) && (c == playerOffset/8) ) {\n          ssd1306_send_byte(doDrawLSP(r-8, playerOffset % 8) | doDrawRS(8- y % 8));            \n        } else {\n          ssd1306_send_byte(B00000000);\n        }\n      }      \n    }\n    ssd1306_send_data_stop();\n  }\n\n}\n\r\n"
  },
  {
    "path": "WrenRollercoasterAttinyArcade/font6x8AJ.h",
    "content": "/*\n * SSD1306xLED - Drivers for SSD1306 controlled dot matrix OLED/PLED 128x64 displays\n *\n * @file: font6x8.h\n * @created: 2014-08-12\n * @author: Neven Boyanov\n * \n * Hacked by andy jackson to allow two games (originally by webboggles.com) to \n * fit onto an ATTiny85 at the same time - hence several characters are missing\n * and a couple have been moved to limit the amount of software remapping required\n * to map ASCII values onto locations in this array.\n *\n * Source code available at: https://bitbucket.org/tinusaur/ssd1306xled\n *\n */\n\n// ----------------------------------------------------------------------------\n\n#include <avr/pgmspace.h>\n\n// ----------------------------------------------------------------------------\n\n/* Standard ASCII 6x8 font */\nstatic const uint8_t ssd1306xled_font6x8 [] PROGMEM = {\n  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sp\n/*\n  0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // !\n  0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // \"\n  0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // #\n  0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $\n  0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // %\n  0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // &\n  0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // '\n  0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // (\n  0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // )\n  0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // *\n  0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // +\n  0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // ,\n  */\n  0x00, 0x08, 0x08, 0x08, 0x08, 0x08, // -\n  0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // .\n  0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w in place of /\n  //0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // /\n  0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0\n  0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, // 1\n  0x00, 0x42, 0x61, 0x51, 0x49, 0x46, // 2\n  0x00, 0x21, 0x41, 0x45, 0x4B, 0x31, // 3\n  0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, // 4\n  0x00, 0x27, 0x45, 0x45, 0x45, 0x39, // 5\n  0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6\n  0x00, 0x01, 0x71, 0x09, 0x05, 0x03, // 7\n  0x00, 0x36, 0x49, 0x49, 0x49, 0x36, // 8\n  0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, // 9\n  0x00, 0x00, 0x36, 0x36, 0x00, 0x00, // :\n/*\n  0x00, 0x00, 0x56, 0x36, 0x00, 0x00, // ;\n  0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // <\n  0x00, 0x14, 0x14, 0x14, 0x14, 0x14, // =\n  0x00, 0x00, 0x41, 0x22, 0x14, 0x08, // >\n  0x00, 0x02, 0x01, 0x51, 0x09, 0x06, // ?\n  0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, // @\n */\n  0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, // B\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, // C\n  0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, // D\n  0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, // E\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, // F\n  0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, // G\n  0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, // H\n  0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, // I\n  0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, // J\n  0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, // K\n  0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, // L\n  0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M\n  0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, // N\n  0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, // O\n  0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, // P\n  0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q\n  0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, // R\n  0x00, 0x46, 0x49, 0x49, 0x49, 0x31, // S\n  0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, // T\n  0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, // U\n  0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, // V\n  0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, // W\n  0x00, 0x63, 0x14, 0x08, 0x14, 0x63, // X\n  0x00, 0x07, 0x08, 0x70, 0x08, 0x07, // Y\n  0x00, 0x61, 0x51, 0x49, 0x45, 0x43, // Z\n  /*\n  0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, // [\n  0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55, // 55\n  0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, // ]\n  0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^\n  0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _\n  0x00, 0x00, 0x01, 0x02, 0x04, 0x00, // '\n*/\n  0x00, 0x20, 0x54, 0x54, 0x54, 0x78, // a\n  0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, // b\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x20, // c\n  0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, // d\n  0x00, 0x38, 0x54, 0x54, 0x54, 0x18, // e\n  0x00, 0x08, 0x7E, 0x09, 0x01, 0x02, // f\n  0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g\n  0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C, // y (in place of h)\n  //0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h\n  0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, // i\n  0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, // j\n  0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, // k\n  0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, // l\n  0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, // m\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, // n\n  0x00, 0x38, 0x44, 0x44, 0x44, 0x38, // o\n  0x00, 0xFC, 0x24, 0x24, 0x24, 0x18, // p\n  0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, // q\n  0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, // r\n  0x00, 0x48, 0x54, 0x54, 0x54, 0x20, // s\n  0x00, 0x04, 0x3F, 0x44, 0x40, 0x20, // t\n  0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, // u\n  0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, // v\n // 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w\n // 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, // x\n // 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C // y\n};\n\n// ----------------------------------------------------------------------------\n\r\n"
  }
]