nice puzzle game

Dependencies:   PokittoLib

main.cpp

Committer:
spinal
Date:
2018-11-18
Revision:
3:f6302af708a4
Parent:
0:3c929189abce

File content as of revision 3:f6302af708a4:


#include "Pokitto.h"
#include "sens_levs.h"
#include "gfx.h"
#include "Synth.h"
#include "sound.h"
#include "snd.h"
#include "tune.h"

Pokitto::Core game;
Pokitto::Sound snd_;

#define OFF_X 2
#define OFF_Y 42
#define LEVWIDTH 18
#define LEVHEIGHT 11
#define SCROLLHEIGHT 112
#define RUMBLEFRAMES 15
#define STEPSIZE 1
#define EXPLODESPRITES 15
#define EXPLODESPEED 5

byte oldLev[LEVWIDTH * LEVHEIGHT];
byte curLev[LEVWIDTH * LEVHEIGHT];
byte teleportMap[LEVWIDTH * LEVHEIGHT];
byte telArray[32];
char satTime = 0;
int numTiles;
int px,py,ps,pd;
int levelNum=0;
int maxLevels=sizeof(levels)/102;
int tileSize=12;
uint32_t frameNumber=0;
int score=0;
int hiscore=0;
bool stillExploding=0;
int telNum = 0;
byte gameMode;
unsigned int myInt=0;
byte scroller=0;
//char musicName[] = "sensitiv.snd";
int lives;

uint32_t myDelay;
uint32_t tempTime;

typedef struct{
    bool playSample;
    int soundPoint;
    const uint8_t *currentSound;
    int currentSoundSize;
    int volume;
    int speed;
    int repeat;
} sampletype;

sampletype snd[4]; // up to 4 sounds at once?
int oldQuart;

uint32_t nextBufferIndexToFill = 0;
uint32_t nextT = 0;
uint32_t oldBufIndex=0;

int currentLine=0;
int mytick=0;
int pattern=0; 
int oldBufNum = 0;

// explosion
uint8_t expX[EXPLODESPRITES], expY[EXPLODESPRITES], expF[EXPLODESPRITES], expU[EXPLODESPRITES];
uint8_t explode = 0;

void rumbleOn(){
    DigitalOut outPin(EXT0);
    //DigitalOut inPin(P0_11);
    //inPin=0;
    outPin=1;
}
void rumbleOff(){
    DigitalOut outPin(EXT0);
    //DigitalOut inPin(P0_11);
    //inPin=0;
    outPin=0;
}

/**************************************************************************/
#define HELD 0
#define NEW 1
#define RELEASE 2
byte CompletePad, ExPad, TempPad, myPad;
bool _A[3], _B[3], _C[3], _Up[3], _Down[3], _Left[3], _Right[3];

DigitalIn _aPin(P1_9);
DigitalIn _bPin(P1_4);
DigitalIn _cPin(P1_10);
DigitalIn _upPin(P1_13);
DigitalIn _downPin(P1_3);
DigitalIn _leftPin(P1_25);
DigitalIn _rightPin(P1_7);

void UPDATEPAD(int pad, int var) {
  _C[pad] = (var >> 1)&1;
  _B[pad] = (var >> 2)&1;
  _A[pad] = (var >> 3)&1;
  _Down[pad] = (var >> 4)&1;
  _Left[pad] = (var >> 5)&1;
  _Right[pad] = (var >> 6)&1;
  _Up[pad] = (var >> 7)&1;
}

void UpdatePad(int joy_code){
  ExPad = CompletePad;
  CompletePad = joy_code;
  UPDATEPAD(HELD, CompletePad); // held
  UPDATEPAD(RELEASE, (ExPad & (~CompletePad))); // released
  UPDATEPAD(NEW, (CompletePad & (~ExPad))); // newpress
}

byte updateButtons(byte var){
   var = 0;
   if (_cPin) var |= (1<<1);
   if (_bPin) var |= (1<<2);
   if (_aPin) var |= (1<<3); // P1_9 = A
   if (_downPin) var |= (1<<4);
   if (_leftPin) var |= (1<<5);
   if (_rightPin) var |= (1<<6);
   if (_upPin) var |= (1<<7);

   return var;
}

/**********[Sound]*********************************************************/


Ticker sounder;
Ticker sounder1;

// note_speed << octave. = speed to play sample
int note_speed[]={ 27,30,16,18,20,21,24,     29,0 ,17,19,0 ,23,25};
//                 A  B  C  D  E  F  G       A# B# C# D# E# F# G#


uint8_t playSound(int channel, const unsigned char *sound, uint16_t soundSize, int volume = 255, int speed=255, int repeat=0){

    snd[channel].currentSound = sound;
    snd[channel].currentSoundSize = (soundSize*255)/speed;
    snd[channel].soundPoint = 0;
    snd[channel].playSample = 1;
    snd[channel].volume = volume;
    snd[channel].speed = speed;
    snd[channel].repeat = repeat;

    return channel;
}

uint8_t mixSound(int samplePos)
{
    int temp = 0;
    int ss[4];

    for(int s=0; s<4; s++){
        ss[s] = (snd[s].currentSound[(snd[s].soundPoint*snd[s].speed)>>8]*snd[s].volume>>8) * snd[s].playSample;
        ++snd[s].soundPoint;
        if(snd[s].soundPoint >= snd[s].currentSoundSize){
            if(snd[s].repeat){
                snd[s].soundPoint=0;
            }else{
                snd[s].playSample=0;
                snd[s].soundPoint=0;
            }
        }
     }    


//    temp = (ss[0] + ss[1] + ss[2] + ss[3]) - (ss[0] * ss[1] * ss[2] * ss[3]);
    temp = ((127 - ss[0] + ss[1] + ss[2] + ss[3])/4)+127;
    
    return temp;
}

void update_tune(){

    char pat = my_pattern[pattern];

    for(int t=0; t<4; t++){
        char note =       tune[pat][currentLine][t][0];
        char octave =     tune[pat][currentLine][t][1];
        int volume =     tune[pat][currentLine][t][2] << 2;
        char instrument = tune[pat][currentLine][t][3];
                    
        if(note > 0){
            
            int speed = (note_speed[note-1] << octave) >> 2;
                        
            switch(instrument){
                case 1:
                    playSound(t, s_01, sizeof(s_01), volume, speed, sampleRepeat[0]);
                break;
                case 2:
                    playSound(t, s_02, sizeof(s_02), volume, speed, sampleRepeat[1]);
                break;
                case 3:
                    playSound(t, s_03, sizeof(s_03), volume, speed, sampleRepeat[2]);
                break;
                case 4:
                    playSound(t, s_04, sizeof(s_04), volume, speed, sampleRepeat[3]);
                break;
            }
        }
                            
        snd[t].volume = volume;
                
    }
 
    if(currentLine++==63){
        currentLine=0;
        if(pattern++==sizeof(my_pattern))pattern=0;
    }
}

/**************************************************************************/


void new2BitTile(int x1, int y1, int wide, int high, int tile, const uint16_t *gfx, int palNumber){
// for drawing level tiles
    uint16_t tileBuffer[wide*high];

    uint8_t pix;
    uint8_t quartWide=wide/4;
    uint8_t pic;

    int palNo = palLookup[palNumber]*4;
    for(int y=0; y<high; y++){
        for(int x=0; x<quartWide; x++){
            pic = gfx[(tile*quartWide*high)+(x+quartWide*y)];
            pix = (pic >> 6)&3; tileBuffer[y*high+(  x*4)]=_pal[_miniPal[palNo+pix]];
            pix = (pic >> 4)&3; tileBuffer[y*high+(1+x*4)]=_pal[_miniPal[palNo+pix]];
            pix = (pic >> 2)&3; tileBuffer[y*high+(2+x*4)]=_pal[_miniPal[palNo+pix]];
            pix = pic &3;       tileBuffer[y*high+(3+x*4)]=_pal[_miniPal[palNo+pix]];
        }
    }

    game.display.directTile(x1, y1, x1+wide, y1+high, tileBuffer);
}

void new4BitTile(int x1, int y1, int wide, int high, int tile, int transparentColor, const uint8_t *gfx){
    uint16_t tileBuffer[wide*high];
    int pix1,pix2;
    int halfWide=wide/2;
    for(int y=0; y<high; y++){
        for(int x=0; x<halfWide; x++){
            pix1 = gfx[(tile*halfWide*high)+(x+halfWide*y)]>>4;
            pix2 = gfx[(tile*halfWide*high)+(x+halfWide*y)]&15;
            tileBuffer[y+high*(  x*2)]=_pal[pix1];
            tileBuffer[y+high*(1+x*2)]=_pal[pix2];
        }
    }
    game.display.directTile(x1, y1, x1+wide, y1+high, tileBuffer);
}


/**************************************************************************/
/**************************************************************************/


int RandMinMax(int min, int max){
    return rand() % max + min;
}

void refreshDisplay(){
    // place holder to replace a simulator command.
}

void draw4BitTile(int x1, int y1, int wide, int high, int tile, int transparentColor, const uint8_t *gfx){
    int pix1,pix2;
    int halfWide=wide/2;
    for(int y=0; y<high; y++){
        for(int x=0; x<halfWide; x++){
            pix1 = gfx[(tile*halfWide*high)+(x+halfWide*y)]>>4;
            pix2 = gfx[(tile*halfWide*high)+(x+halfWide*y)]&15;
            if(pix1 != transparentColor){game.display.directPixel(x1+(x*2),y1+y,_pal[pix1]);}
            if(pix2 != transparentColor){game.display.directPixel(1+x1+(x*2),y1+y,_pal[pix2]);}
        }
    }
}

void draw2BitTile(int x1, int y1, int wide, int high, int tile, int transparentColor, const uint8_t *gfx, int palNumber, int palReplace = -1){
    uint8_t pix;
    uint8_t quartWide=wide/4;
    uint8_t pic;

    int palNo = palLookup[palNumber]*4;
    for(int y=0; y<high; y++){
        for(int x=0; x<quartWide; x++){
            pic = gfx[(tile*quartWide*high)+(x+quartWide*y)];
            pix = (pic >> 6)&3; if(pix != transparentColor){game.display.directPixel(  x1+(x*4),y1+y,_pal[_miniPal[palNo+pix]]);}
            pix = (pic >> 4)&3; if(pix != transparentColor){game.display.directPixel(1+x1+(x*4),y1+y,_pal[_miniPal[palNo+pix]]);}
            pix = (pic >> 2)&3; if(pix != transparentColor){game.display.directPixel(2+x1+(x*4),y1+y,_pal[_miniPal[palNo+pix]]);}
            pix = pic &3;       if(pix != transparentColor){game.display.directPixel(3+x1+(x*4),y1+y,_pal[_miniPal[palNo+pix]]);}
        }
    }
}


void drawFont(int x1, int y1, int wide, int high, int tile, int transparentColor, const uint8_t *gfx, int palReplace = -1){
    uint16_t tileBuffer[(wide+1)*(high+1)];

    uint8_t pix;
    uint8_t quartWide=wide/4;
    uint8_t pic;

    for(int y=0; y<high; y++){
        for(int x=0; x<quartWide; x++){
            pic = gfx[(tile*quartWide*high)+(x+quartWide*y)];
            pix = (pic >> 6)&3; if(pix != transparentColor){tileBuffer[y*high+(  x*4)]=numbers_pal[pix];}else{tileBuffer[y*high+(  x*4)]=palReplace;}
            pix = (pic >> 4)&3; if(pix != transparentColor){tileBuffer[y*high+(1+x*4)]=numbers_pal[pix];}else{tileBuffer[y*high+(1+x*4)]=palReplace;}
            pix = (pic >> 2)&3; if(pix != transparentColor){tileBuffer[y*high+(2+x*4)]=numbers_pal[pix];}else{tileBuffer[y*high+(2+x*4)]=palReplace;}
            pix = pic &3;       if(pix != transparentColor){tileBuffer[y*high+(3+x*4)]=numbers_pal[pix];}else{tileBuffer[y*high+(3+x*4)]=palReplace;}
        }
    }

    game.display.directTile(x1, y1, x1+wide, y1+high, tileBuffer);

}

// print text
void print(uint16_t x, uint16_t y, const char* text, uint8_t bgCol, signed int repCol=-1){
    if(repCol==-1)repCol=bgCol;
    for(uint8_t t = 0; t < strlen(text); t++){
        uint8_t character = text[t]-32;
        drawFont(x, y, 8, 8, character, bgCol, myFont, repCol);
        x += 8;
    }
}



void loadLevel(int number) {
/*
    // store level number in file for testing
   FILE *fp;
   fp = fopen("test.txt", "w+");
   fwrite(&number, sizeof(int),1, fp);
   fclose(fp);
*/

  numTiles = 0;
  satTime = 0;
  int numTels = 0;

  int amount = (LEVWIDTH/2)*LEVHEIGHT;

  for (int t = amount-1; t >= 0; t--) {
    int s = pgm_read_byte(levels + t + ((amount+3) * number));
    curLev[t * 2] = pgm_read_byte(lookUpTile + (s >> 4));
    curLev[(t * 2) + 1] = pgm_read_byte(lookUpTile + (s & 15));
    s = t * 2;
    teleportMap[s] = 0;
    teleportMap[s+1] = 0;

    switch (curLev[s]) {
      case 1:
        numTiles++;
        break;
      case 2:
        numTiles += 2;
        break;
      case 4:
        curLev[s + 1] = 5;
        curLev[s + LEVWIDTH] = 6;
        curLev[s + LEVWIDTH+1] = 7;
        break;
      case 8:
        curLev[s + 1] = 9;
        break;
      case 10:
        curLev[s + 1] = 11;
        break;
      case 12:
        curLev[s + LEVWIDTH] = 13;
        break;
    }

    s = (t * 2) + 1;
    switch (curLev[s]) {
      case 1:
        numTiles++;
        break;
      case 2:
        numTiles += 2;
        break;
      case 4:
        curLev[s + 1] = 5;
        curLev[s + LEVWIDTH] = 6;
        curLev[s + LEVWIDTH+1] = 7;
        break;
      case 8:
        curLev[s + 1] = 9;
        break;
      case 10:
        curLev[s + 1] = 11;
        break;
      case 12:
        curLev[s + LEVWIDTH] = 13;
        break;
    }

  }


  px = pgm_read_byte(levels + amount + ((amount+3) * number))*tileSize;
  py = pgm_read_byte(levels + amount+1 + ((amount+3) * number))*tileSize;
  int telNumber = pgm_read_byte(levels + amount+2 + ((amount+3) * number));
  ps = 0; pd = 0;
  satTime = 0;

  for(int t=0; t<31; t++){
    telArray[t] = pgm_read_byte(telPath + t + (telNumber*32));
  }

    // teleport locations
    numTels=0;
    for (int y = 0; y <LEVHEIGHT; y++) {
      for (int x = 0; x <LEVWIDTH ; x++) {
        int tn = (y * LEVWIDTH) + x;
        if(curLev[tn]==16){
            teleportMap[tn] = numTels;
            numTels++;
        }
      }
    }


  // draw part of the screen here
  // bad practice I know, but so what!

    for(byte t=0; t<LEVWIDTH * LEVHEIGHT; t++){
        oldLev[t] = 255;
    }

    for (int x = LEVWIDTH-1; x >= 0 ; x--) {
        new2BitTile(OFF_X+x*tileSize, 42, tileSize, tileSize, 0, gbTiles, 0);
    }

    game.display.directRectangle(OFF_X,0,218,40,_pal[10]);
    game.display.directRectangle(OFF_X,0,218,1,_pal[4]);
    game.display.directRectangle(OFF_X,1,218,2,_pal[10]);
    game.display.directRectangle(OFF_X,2,218,3,_pal[15]);
    game.display.directRectangle(OFF_X,3,218,4,_pal[15]);
    game.display.directRectangle(OFF_X,4,218,5,_pal[10]);
    game.display.directRectangle(OFF_X,5,218,6,_pal[4]);
    game.display.directRectangle(OFF_X,36,218,37,_pal[4]);
    game.display.directRectangle(OFF_X,37,218,38,_pal[10]);
    game.display.directRectangle(OFF_X,38,218,39,_pal[15]);
    game.display.directRectangle(OFF_X,39,218,40,_pal[15]);
    game.display.directRectangle(OFF_X,40,218,41,_pal[10]);
    game.display.directRectangle(OFF_X,41,218,42,_pal[4]);


    // pause if any buttons held
    while(_Up[HELD] || _Down[HELD] || _Left[HELD] || _Right[HELD] || _A[HELD] || _B[HELD] || _C[HELD]){
      myPad = updateButtons(myPad);
      UpdatePad(myPad);
    }


}

void renderLevel(bool drawPlayer = 1, bool fullLevel=0){

    signed int xStart=(px / tileSize)+4;
    signed int yStart=(py / tileSize)+4;
    signed int xEnd=(px / tileSize)-4;
    signed int yEnd=(py / tileSize)-4;
    if(xEnd<0){xStart+=-xEnd; xEnd=0;}
    if(yEnd<0){yStart+=-yEnd; yEnd=0;}
    if(xStart>LEVWIDTH-1){xStart=LEVWIDTH-1; xEnd=xStart-9;}
    if(yStart>LEVHEIGHT-1){yStart=LEVHEIGHT-1; yEnd=yStart-9;}

//  if(fullLevel){
        xStart=LEVWIDTH-1;
        yStart=LEVHEIGHT-1;
        xEnd=0;
        yEnd=1;
//  }


//        oldLev[t] = curLev[t];


 //   int transp=-1;
    for (int y = yStart; y >= yEnd; y--) {
      for (int x = xStart; x >= xEnd; x--) {
        int tn = (y * LEVWIDTH) + x;
            if(oldLev[tn] != curLev[tn]){
                oldLev[tn] = curLev[tn];
                if(curLev[tn]==0){
                    // water tile with shaddow
                    uint8_t tile = 0;
                    if(y>0){
                        if(curLev[((y-1) * LEVWIDTH) + (x)]){ tile += 1; }
                        if(x>0){if(curLev[((y-1) * LEVWIDTH) + (x-1)]){ tile += 2; }}
                    }
                    if(x>0){if(curLev[((y) * LEVWIDTH) + (x-1)]){ tile += 4; }}
                    new2BitTile(OFF_X+x*tileSize, OFF_Y+y*tileSize, tileSize, tileSize, shaddow[tile], gbTiles, shaddow[tile]);

                    for (int t = 0; t < EXPLODESPRITES; t++) {
                        if (expU[t] == 1) {
                            if(expX[t]==x && expY[t]==y){
                                draw4BitTile(OFF_X+(expX[t]*tileSize), OFF_Y+expY[t]*tileSize, tileSize, tileSize, expF[t], 8, explode_tiles);
                            }
                        }
                    }

                }else{
                    // all other tiles
                    new2BitTile(OFF_X+x*tileSize, OFF_Y+y*tileSize, tileSize, tileSize, curLev[tn], gbTiles, curLev[tn]);
                }
            }

            // player sprite
            if(drawPlayer){
                if(x == px/tileSize){
                    if(y == py/tileSize){
                        uint16_t tileBuffer[10];
                        for(byte y1=0; y1<8; y1++){
                            int offX = ball[y1][0];
                            int wide = ball[y1][1];
                            for(byte x1=0; x1<wide; x1++){
                                tileBuffer[x1]=_pal[ball[y1][x1+2]];
                            }
                            game.display.directTile(OFF_X+px+offX+2, OFF_Y+py+y1+2, OFF_X+px+wide+offX+2, OFF_Y+py+3+y1 , tileBuffer);
                        }// y
                    }
                }

             }//drawplayer


      }
    }

        // explosions
        stillExploding=0;
        for (int t = 0; t < EXPLODESPRITES; t++) {
          if (expU[t] == 1) {
            oldLev[expX[t] + LEVWIDTH * expY[t]] = 255;

            stillExploding=1;
            if(expF[t]<=1){
//                new2BitTile(OFF_X+(expX[t]*tileSize), OFF_Y+expY[t]*tileSize, tileSize, tileSize, 1, gbTiles, 1);
            }
//            draw4BitTile(OFF_X+(expX[t]*tileSize), OFF_Y+expY[t]*tileSize, tileSize, tileSize, expF[t], 8, explode_tiles);
            if (frameNumber % EXPLODESPEED == 0) {
              expF[t]++;
              if (expF[t] == 8) {
                expU[t] = 0;
              }
            }
          }
        }


    print(8, 14, "SCORE  LEV LIVES  HISCORE",0,_pal[10]);
    char text[] = "      ";
    sprintf(text, "%05d",score);
    print(8, 24, text,0,_pal[10]);
    sprintf(text, "%03d",levelNum+1);
    print(64, 24, text,0,_pal[10]);
    sprintf(text, "%02d",lives);
    print(104, 24, text,0,_pal[10]);
    sprintf(text, "%05d",hiscore);
    print(160, 24, text,0,_pal[10]);

}

void explodeHere(){
    for (int t = 0; t < EXPLODESPRITES; t++) {
        if (expU[t] == 0) {
            expX[t] = px / tileSize;
            expY[t] = py / tileSize;
            expF[t] = 0;
            expU[t] = 1;
            score++;
            break;
        }
    }
}

void checkTile(int x, int y) {
  int t = curLev[x + LEVWIDTH * y];
  switch (t) {
    case 1:
      curLev[x + LEVWIDTH * y] = 0;
      oldLev[x + LEVWIDTH * y] = 255;
      oldLev[(x+1) + LEVWIDTH * y] = 255;
      oldLev[(x+1) + LEVWIDTH * (y+1)] = 255;
      oldLev[x + LEVWIDTH * (y+1)] = 255;
      numTiles--;
      explodeHere();
      break;
    case 2:
      curLev[x + LEVWIDTH * y] = 1;
      numTiles--;
      score++;
      break;
  }
  if(score > 9999) {
    score = 9999;
  }
  if(score > hiscore) {
    hiscore = score;
  }
}


void movePlayer() {
    char x = px/tileSize;
    char y = py/tileSize;
      oldLev[(x-1) + LEVWIDTH * y] = 255;
      oldLev[x + LEVWIDTH * y] = 255;
      oldLev[(x+1) + LEVWIDTH * y] = 255;
      oldLev[x + LEVWIDTH * (y+1)] = 255;

  if (ps == 0) { // not moving
    // sneeky exit check
    if (curLev[(px / tileSize) + LEVWIDTH * (py / tileSize)] == 10 || curLev[(px / tileSize) + LEVWIDTH * (py / tileSize)] == 11) {
      if (numTiles == 0) {
        levelNum++;
        if (levelNum >= maxLevels) {
          levelNum = 0;
        }
        // make sure explosions have finished :-)
        for (int t = 0; t < EXPLODESPRITES; t++){expU[t] = 0;}
        renderLevel(); refreshDisplay();
        loadLevel(levelNum);
        renderLevel(0,1);
      }
    }
    // sneeky water check
    int p = curLev[(px / tileSize) + LEVWIDTH * (py / tileSize)];
    if (p == 0 || (p>=24 && p<=32)) {
      lives--;
      rumbleOn();
      if (lives >= 0) {
        explodeHere();
        // make sure explosions have finished :-)
        for(frameNumber=0; frameNumber<30; frameNumber++){
            if(frameNumber>=RUMBLEFRAMES){rumbleOff();}
            renderLevel(0); // 0 to hide player
            refreshDisplay();
        }
        loadLevel(levelNum);
        renderLevel(0,1);
      } else {
        explodeHere();
        // make sure explosions have finished :-)
        for(frameNumber=0; frameNumber<30; frameNumber++){
            if(frameNumber>=RUMBLEFRAMES){rumbleOff();}
            renderLevel(0); // 0 to hide player
            refreshDisplay();
        }
        gameMode = 0; // titlescreen
      }
    }


    pd = 0;
//    if (!_B[HELD]) {
      if (_Up[HELD]) {
        if (curLev[(px / tileSize) + LEVWIDTH * (py / tileSize)] != 14 && curLev[(px / tileSize) + LEVWIDTH * ((py-tileSize) / tileSize)] != 14) {
          pd = 1;
          checkTile(px / tileSize, py / tileSize);
        }
      }
      if (_Down[HELD]) {
        if (curLev[(px / tileSize) + LEVWIDTH * (py / tileSize)] != 14 && curLev[(px / tileSize) + LEVWIDTH * (py / tileSize)] != 14) {
          pd = 2;
          checkTile(px / tileSize, py / tileSize);
        }
      }
      if (_Left[HELD]) {
        if (curLev[(px / tileSize) + LEVWIDTH * (py / tileSize)] != 15 && curLev[((px-tileSize) / tileSize) + LEVWIDTH * (py / tileSize)] != 15) {
          pd = 3;
          checkTile(px / tileSize, py / tileSize);
        }
      }
      if (_Right[HELD]) {
        if (curLev[(px / tileSize) + LEVWIDTH * (py / tileSize)] != 15 && curLev[((px+tileSize) / tileSize) + LEVWIDTH * (py / tileSize)] != 15) {
          pd = 4;
          checkTile(px / tileSize, py / tileSize);
        }
      }
      if (_A[NEW]) {
        if (curLev[(px / tileSize) + LEVWIDTH * (py / tileSize)] == 16) { // teleport
          int t = (px / tileSize) + LEVWIDTH * (py / tileSize);
          telNum = teleportMap[t];
          px = (telArray[telNum]%LEVWIDTH)*tileSize;
          py = (telArray[telNum]/LEVWIDTH)*tileSize;
          renderLevel(1,1);
        }
      }

  }

  switch (pd) {
    case 0:
      break;
    case 1:
      py-=STEPSIZE;
      ps+=STEPSIZE;
      break;
    case 2:
      py+=STEPSIZE;
      ps+=STEPSIZE;
      break;
    case 3:
      px-=STEPSIZE;
      ps+=STEPSIZE;
      break;
    case 4:
      px+=STEPSIZE;
      ps+=STEPSIZE;
      break;
  }
  if (ps == tileSize) {
    ps = 0; pd = 0;
    satTime = 0;
  }

}

void drawTitleScreen(){
    game.display.directRectangle(0,0,220,176,_pal[0]); // clear the screen
    draw4BitTile(4, 41, 212, 23, 0, -1, title);

    print(40, 80, "Remade for Pokitto",0,_pal[0]);
    print(40, 96, "    By Spinal",0,_pal[0]);

    print(8, 136, "    Original on C64 by",0,_pal[0]);
    print(8, 152, "   Oliva Kirwa (C) 1990",0,_pal[0]);

    for(int x=0; x<220; x++){
        game.display.directPixel(x,SCROLLHEIGHT,_pal[4]);
        game.display.directPixel(x,SCROLLHEIGHT+1,_pal[10]);
        game.display.directPixel(x,SCROLLHEIGHT+2,_pal[15]);
        game.display.directPixel(x,SCROLLHEIGHT+11,_pal[15]);
        game.display.directPixel(x,SCROLLHEIGHT+12,_pal[10]);
        game.display.directPixel(x,SCROLLHEIGHT+13,_pal[4]);
    }

    gameMode=1;
}

void titleScreen(){
    char text1[34];
    memcpy(text1, &text[myInt],33);
    text1[32]=0;
    //titleprint(-scroller, 6 , text1);
    print(-scroller, SCROLLHEIGHT+3, text1,0,_pal[14]);
    if(frameNumber%3==0){
        scroller++;
        if(scroller==8){
        scroller=0;
        myInt++;
        if(myInt==strlen(text)){myInt=0;}
        }
    }

    if(_A[NEW]){
        lives = 5;
        score = 0;
        levelNum = 0;
        gameMode = 10;
        game.display.directRectangle(0,0,220,176,0x0000); // clear the screen
    }

}

void playLevel(){

    movePlayer();

    // sit still too long at your peril!
    if (pd == 0) {
        satTime++;
        int t=curLev[(px / tileSize) + LEVWIDTH * (py / tileSize)];
        char satCount = 16;
        if(t==2) satCount = 8;

        if(satTime == satCount) {
            checkTile(px / tileSize, py / tileSize);
            satTime = 0;
        }
    }

    renderLevel();

}

void update_buffer(){
/*
    // Fill the next buffer if it is not used currently 
    if((uint32_t)currentBuffer != nextBufferIndexToFill) {

        for(uint32_t t=0; t<BUFFER_SIZE; t++){
            buffers[nextBufferIndexToFill][t] = mixSound(t);
        }
        if(++nextBufferIndexToFill > 3)
            nextBufferIndexToFill = 0;
        }
*/
    char sndOffset[]={2,3,0,1};

    if((uint32_t)currentBuffer != nextBufferIndexToFill) {
        for(uint32_t t=0; t<BUFFER_SIZE; t++){
            nextBufferIndexToFill = currentBuffer;
            buffers[sndOffset[nextBufferIndexToFill]][t] = mixSound(t);
        }
    }
        
}

int main(){


    rumbleOff(); // just in case

    game.begin();
    game.display.width = 220; // full size
    game.display.height = 174;
 
    // Set global audio variables
    currentBuffer = 0;
    currentPtr = buffers[currentBuffer];
    endPtr = currentPtr + BUFFER_SIZE;
 
    // Init audio stream.
    pokPlayStream(); // activate stream
    game.sound.ampEnable(true);
    game.sound.playMusicStream();


    gameMode = 0; // titleScreen
    tempTime = game.getTime();


    sounder.attach(&update_tune, 0.05);
    sounder1.attach(&update_buffer, 0.0075);

    while (game.isRunning()) {
        //update_buffer();
    
          // if it is time to update the screen
 //       if (game.update(true)){

            //game.sound.updateStream();

            myPad = updateButtons(myPad);
            UpdatePad(myPad);

            frameNumber++;

//            if(frameNumber %3 == 0) update_tune(); 

            
            //char oldMode = gameMode;
            switch(gameMode){
                case 0:
                    drawTitleScreen();
                    break;
                case 1:
                    levelNum = 0;
                    myDelay = 5;
                    titleScreen();
                    break;
                case 10:
                    // start new game.
                    loadLevel(levelNum);
                    renderLevel(0,1);
                    gameMode = 20;
                    break;
                case 20:
                    // play levels
                    myDelay = 15;
                    playLevel();
                    break;
            }

        // timing loop
        while(game.getTime()-tempTime < myDelay){
        };
        refreshDisplay();
        tempTime = game.getTime();
//  } // update
  }
    return 1;
}