#include "sdkCommun.h"
#include "sdkConstants.h"

const unsigned short linescroll_script_greenhill[]=       {
    0, 128,
    32, 120,
    48, 112,
    64, 104,

    112, 140,

    152, 144,
    160, 160,
    168, 176,
    176, 192,
    184, 208,
    192, 224,
    200, 240,
    208, 256,
    216, 272,
    224, 288,
    232, 304,

    240, 304,
    248, 304,
    256, 304,
    272, 304,
    
    0x2000,0
};

ANIMATION GreenHill_anims[]=          {
    //Tournesols
    {0x10,0x190,4,1},
    {0x11,0x191,4,1},
    {0x16,0x192,4,1},
    {0x17,0x193,4,1},
    {0,0,0,0},
};

void GreenHill_rotationPalette(unsigned short *palette, int offset)          {
    int i;
    i=palette[offset];
    palette[offset]=palette[offset+1];
    palette[offset+1]=palette[offset+2];
    palette[offset+2]=palette[offset+3];
    palette[offset+3]=i;
}

void GreenHill_rotationPaletteInverse(unsigned short *palette, int offset)          {
    int i;
    i=palette[offset+3];
    palette[offset+3]=palette[offset+2];
    palette[offset+2]=palette[offset+1];
    palette[offset+1]=palette[offset];
    palette[offset]=i;
}

void GreenHillInit()       {
//   PaletteNormaleSauv[0]=RGB(0,0,0);
}

void GreenHillLoopStd()       {
    int i;
    //Rotations de palette
     if ((nTimer&3)==0)          {
         GreenHill_rotationPalette(PaletteNormale,0x9b);
         GreenHill_rotationPaletteInverse(PaletteNormale,0x19);
         //ENLEVER!
         GreenHill_rotationPalette(PaletteEau,0x9b);
         GreenHill_rotationPaletteInverse(PaletteEau,0x19);
     }
    //Animation de tiles
    if ((nFrame%8)==0)         {
        i=(nFrame/10)&31;
        if (i==0)
            ChangePlusieursTiles(0x1aa,0x1aa,6);
        else if (i==15)
            ChangePlusieursTiles(0x1b0,0x1aa,6);
        else if (i==16)
            ChangePlusieursTiles(0x1b6,0x1aa,6);
        else if (i==31)
            ChangePlusieursTiles(0x1b0,0x1aa,6);
    }
}

void GreenHillLoop()       {
    GreenHillLoopStd();
}

void GreenHillLoopAct1()       {
    GreenHillLoopStd();
    //Redéfinit le viewport pour l'acte 1
    if (EcrSprites->scrlX<368<<4)
        desiredViewportY1=TILE*(64+1);
    else
        desiredViewportY1=TILE*(TABLE_Y+1);
}

//Copie les palettes standard (objets)
void PalStandard()         {
/*    ChargePalette(Pal_0_palette, nPalObj(0), 16);
    ChargePalette(Pal_1_palette, nPalObj(1), 16);
    ChargePalette(Pal_2_palette, nPalObj(2), 16);
    ChargePalette(Pal_3_palette, nPalObj(3), 16);*/
//    ChargePalette(pal08_palette, nPalObj(8), 16);
}

//La palette doit être modifiée!
void GreenHillPalette()          {
    ChargePalette(GreenHill_01_palette, nPalBG(0), 64);
    ChargePalette(BG_GreenHill_palette, nPalBG(8), 32);
    PaletteNormale[0]=RGB(0,0,15);
    PalStandard();
}

void GreenHill_typesSpeciaux(SONIC *s, u32 i)          {
    if (i==0x1FD)
       goto _1fe;
    //FIN RAJOUT
    if (s->croche)          {
        if (i==0x1FE)        {
_1fe:
            if (s->vx>0)
                plan=1;
            else
                plan=0;
        }
    }
    if (i==0x1FF)        {
        if (s->vx>0)
            plan=0;
        else
            plan=1;
    }
    if (i==0x1FC)        {
        if (s->vy>0)
            plan=0;
        else
            plan=1;
    }
    if (i==0x1FB)        {
        if (s->vy>0)
            plan=1;
        else
            plan=0;
    }
}

/*

        AQUATIC RUIN ZONE

*/

/*const unsigned short AquaticRuin_linescroll_script[]=       {
    0, 128,
    0x2000,0
};*/

const unsigned short AquaticRuin_linescroll_script[]=       {
    0, 192,
    41*8, 128,
    54*8, 160,
    56*8, 168,
    58*8, 176,
    60*8, 184,
    62*8, 192,
    66*8, 192,
    72*8, 208,
    96*8, 216,
    0x2000,0
};

ANIMATION AquaticRuin_anims[]=          {
	{0, 0, 0, 0},
};

void AquaticRuin_Init()       {
}

void AquaticRuin_RotationPalette(u16 *palette)      {
	u32 i;
	i=palette[28];
	palette[28]=palette[27];
	palette[27]=palette[26];
	palette[26]=i;
}

void AquaticRuin_Loop()       {
	if ((nTimer&7)==0)      {
		GreenHill_rotationPaletteInverse(PaletteNormale,0x2);
	}
}

void AquaticRuin_typesSpeciaux(SONIC *s, u32 i)          {
	if (i==0x1FD)
		goto _1fe;
	//FIN RAJOUT
	if (s->croche)          {
		if (i==0x1FE)        {
_1fe:
			if (s->vx>0)
				plan=1;
			else
				plan=0;
		}
	}
	if (i==0x1FF)        {
		if (s->vx>0)
			plan=0;
		else
			plan=1;
	}
	if (i==0x1FC)        {
		if (s->vy>0)
			plan=0;
		else
			plan=1;
	}
	if (i==0x1FB)        {
		if (s->vy>0)
			plan=1;
		else
			plan=0;
	}
	if (i==0x1FA)       {
		if (s->croche)      {
			if (s->vx>0)
				plan=2;
			else
				plan=1;
		}
	}
	if (i==0x1F9)       {
		if (!s->croche)     {
			if (s->vy>0 && plan==2)
				plan=0;
		}
	}
	if (i==0x1F8)       {
		if (s->croche)      {
			if (s->vx>0 && plan==2)
				plan=0;
			else if (s->vx<0)       {
				plan=1;
			}
		}
	}
	if (i==0x1F7)
		plan=1;
	if (i==0x1F6)       {
		if (s->vx>=0)
			s->prio=3;
		else
			s->prio=2;
	}
	if (i==0x1F5)       {
		if (s->vx<0)
			s->prio=3;
		else
			s->prio=2;
	}
	if (i==0x1F4)
		plan=0;
	if (i==0x1F3)        {
		if (s->vx>0)
			plan=0;
		else
			plan=1;
	}
}

void AquaticRuin_Palette()          {
	ChargePalette(AquaticRuin_palette, nPalBG(0), 64);
	ChargePalette(BG_AquaticRuin_palette, nPalBG(8), 16);
//	ChargePalette(BG_AquaticRuin_palette, nPalBG(9), 16);
	PaletteNormale[0]=RVB(0,4,0);
	PalStandard();
}

void AquaticRuin_AfterPalette()     {
    AlphaBlendPalette(PaletteNormale + 9 * 16, BG_AquaticRuin_palette, 16, 0, 24);
    CopieDMA(PaletteNormale + 9 * 16, PaletteEau + 9 * 16, 16, DMA_16im);
}

void ARZ_CopieMapVerticale(unsigned short (*map)[32], void *map_src, int tailleX, int tailleY, int scrlX, int scrlY)           {
    int j, k, l;
    const unsigned short (*dst)[tailleX] = map_src;

	k=scrlY;
	//Le but est de faire un modulo tailleX, mais c'est trop lent
	while(k>=(tailleY<<6))              //Par étapes de 64*tailleX
		k-=tailleY<<6;
	while(k>=(tailleY<<3))              //Par étapes de 8*tailleX
		k-=tailleY<<3;
	while(k>=tailleY)
		k-=tailleY;

    l = scrlX % tailleX;

	for (j=0;j<=31;j++)     {
		map[(j+scrlY)&31][scrlX&31]=dst[k][l];
		k++;
		if (k>=tailleY)
			k-=tailleY;
	}
}

void ARZ_CopieMapHorizontale(unsigned short (*map)[32], void *map_src, int tailleX, int tailleY, int scrlX, int scrlY)           {
	int i, j, k;
	const unsigned short (*dst)[tailleX] = map_src;


	k=scrlX;
	//Le but est de faire un modulo tailleX, mais c'est trop lent
	while(k>=(tailleX<<6))              //Par étapes de 64*tailleX
		k-=tailleX<<6;
	while(k>=(tailleX<<3))              //Par étapes de 8*tailleX
		k-=tailleX<<3;
	while(k>=tailleX)
		k-=tailleX;

	j=scrlY%tailleY;

	for (i=0;i<=31;i++)      {
		map[scrlY&31][(scrlX+i)&31]=dst[j][k++];
		if (k>=tailleX)
			k-=tailleX;
	}
}

void AquaticRuin_Loop2()       {
    int i;
    static int lastX, lastY;
    int sX, sY;

    if ((nTimer&7)==0)      {
        GreenHill_rotationPaletteInverse(PaletteNormale,0x2);
    }

    sX=((36*scrlX)>>5)>>3, sY=((28*scrlY)>>5)>>3;
    if (nFrame==3)          {
/*        AlphaBlendPalette(PaletteNormale+9*16,PaletteNormaleSauv+9*16,16,0,28);
        AlphaBlendPalette(PaletteEau+9*16,PaletteEauSauv+9*16,16,0,24);
        AlphaBlendPalette(PaletteNormale+9*16,PaletteNormaleSauv+9*16,16,0,28);
        AlphaBlendPalette(PaletteEau+9*16,PaletteEauSauv+9*16,16,0,24);*/
//        AlphaBlendPalette(PaletteNormale+9*16,BG_AquaticRuin_palette,16,0,24);
//        CopieDMA(PaletteNormale+9*16,PaletteEau+9*16,16,DMA_16im);
    }
    if (premFois)           {
        for (i=0;i<=31;i++)
            ARZ_CopieMapVerticale((void*)SCREEN_BASE_BLOCK(28),(void*)BG_ARZ2_map,112,192,sX+i,sY);
    }
    else    {
        while (sX>lastX)        {
            lastX++;
            ARZ_CopieMapVerticale((void*)SCREEN_BASE_BLOCK(28),(void*)BG_ARZ2_map,112,192,lastX+31,lastY);
        }
        while (sX<lastX)        {
            lastX--;
            ARZ_CopieMapVerticale((void*)SCREEN_BASE_BLOCK(28),(void*)BG_ARZ2_map,112,192,lastX,lastY);
        }
        while (sY>lastY)        {
            lastY++;
            ARZ_CopieMapHorizontale((void*)SCREEN_BASE_BLOCK(28),(void*)BG_ARZ2_map,112,192,lastX,lastY+31);
        }
        while (sY<lastY)        {
            lastY--;
            ARZ_CopieMapHorizontale((void*)SCREEN_BASE_BLOCK(28),(void*)BG_ARZ2_map,112,192,lastX,lastY);
        }
    }
    lastX=sX, lastY=sY;
//    CopieDMA((void*)BG_ARZ2_tiles, (void*)CharBaseBlock(3), sizeof(BG_ARZ2_tiles)>>1, DMA_16im);
    REG_BG3CNT = BG_16_COLOR | BG_WRAP | SCREEN_BASE(28) | BG_PRIORITY(0) | CHAR_BASE(2);
    REG_BG3HOFS = (((36 * scrlX) >> 5) & 255);
    REG_BG3VOFS = (((28 * scrlY) >> 5) & 255);
}

const LEVEL_INFO ExtNiveaux[]=          {
    {
         1,0,"Green Hill",1,
         //Avant-plan
         {
            639, 79,
            9 * 16, 58 * 16,
            GreenHill_01_tiles,
            greenhill_acte1_gfx,
            greenhill_acte1_col,
            GreenHill_anims,
			// Tileset 8 bits, comme d'hab
			8, MAX_TILES_DEFAULT,
         },

		 //Eau
         0xffff, RGB(0,0,0), 31,

		 //Arrière-plan
         {
            BG_GreenHill_tiles, sizeof(BG_GreenHill_tiles),
            BG_GreenHill_palette, sizeof(BG_GreenHill_palette),
            BG_GreenHill_map, 128, 64,
            linescroll_script_greenhill,
            16
         },

		 //Liste de sprites
         {
            &greenhill_acte1_liste_nbEle,
            greenhill_acte1_liste
         },

		 // Autres
         {
             1,
             GreenHill_typesSpeciaux,
             false,
         },

		 // Divers
         "greenhill.bgm",
         GreenHillInit,
         GreenHillLoopAct1,
         GreenHillPalette,
         NULL,                          //AfterPalette
         NULL,                          //VBL
    },
/*    {
         //Indications
         1,0,"Green Hill",1,
         //Avant-plan
         {
            535,79,
            2*16,75*16,
            GreenHill_01_tiles,
//            patterns_nv1_palette, sizeof(patterns_nv1_palette),
            greenhill_acte2_gfx,
            greenhill_acte2_col,
            GreenHill_anims,
         },
         //Eau
         0xffff, RGB(0,0,0), 16,
         //Arrière-plan
         {
            BG_GreenHill_tiles, sizeof(BG_GreenHill_tiles),
            BG_GreenHill_palette, sizeof(BG_GreenHill_palette),
            BG_GreenHill_map, 128, 64,
            linescroll_script_greenhill,
            16
         },
         //Liste de sprites
         {
            &greenhill_02_liste_nbEle,
            greenhill_02_liste
         },
         {
             1,
             GreenHill_typesSpeciaux,
             0,
         },
         //Divers
         "greenhill.8ad",
         GreenHillInit,
         GreenHillLoop,
         GreenHillPalette
    },*/
    {
         //Indications
         2,0,"Green Hill",2,
         //Avant-plan
         {
            439,79,
            2*16,36*16,
            GreenHill_01_tiles,
            greenhill_acte3_gfx,
            greenhill_acte3_col,
            GreenHill_anims,
			// Tileset 8 bits, comme d'hab
			8, MAX_TILES_DEFAULT,
         },
         //Eau
         0xffff, RGB(0,0,0), 16,
         //Arrière-plan
         {
            BG_GreenHill_tiles, sizeof(BG_GreenHill_tiles),
            BG_GreenHill_palette, sizeof(BG_GreenHill_palette),
            BG_GreenHill_map, 128, 64,
            linescroll_script_greenhill,
            16
         },
         {
            &greenhill_acte3_liste_nbEle,
            greenhill_acte3_liste
         },
         {
             1,
             GreenHill_typesSpeciaux,
             0,
         },
         //Divers
         "greenhill.bgm",
         GreenHillInit,
         GreenHillLoop,
         GreenHillPalette,
         NULL,
         NULL,
    },
    {
         //Indications
         3,0,"Green Hill",3,
         //Avant-plan
         {
            700,79,
            2*16,19*16,
            GreenHill_01_tiles,
            greenhill_acte4_gfx,
            greenhill_acte4_col,
            GreenHill_anims,
			// Tileset 8 bits, comme d'hab
			8, MAX_TILES_DEFAULT,
         },
         //Eau
         0xffff, RGB(0,0,0), 16,
         //Arrière-plan
         {
            BG_GreenHill_tiles, sizeof(BG_GreenHill_tiles),
            BG_GreenHill_palette, sizeof(BG_GreenHill_palette),
            BG_GreenHill_map, 128, 64,
            linescroll_script_greenhill,
            16
         },
         {
            &greenhill_acte4_liste_nbEle,
            greenhill_acte4_liste
         },
         {
             1,
             GreenHill_typesSpeciaux,
             0,
         },
         //Divers
         "greenhill.bgm",
         GreenHillInit,
         GreenHillLoop,
         GreenHillPalette,
         NULL,
         NULL,
    },

    /*
        AQUATIC RUIN
    */

    {
         // Indications générales: "Level #4: Aquatic Ruins Zone Act 1"
         4, 0, "Aquatic Ruins", 1,

         // Infos sur l'avant-plan
         {
            667, 114,					// Taille de la map
            1*16, 51*16,				// Point de départ
            AquaticRuin_tiles,			// Tileset utilisé
            aquaticruin_acte1_gfx,		// Map graphique
            aquaticruin_acte1_col,		// Map de collisions
            AquaticRuin_anims,			// Animations de tiles
			8, MAX_TILES_DEFAULT,		// Paramètres avancés (profondeur de couleurs, nombre de tiles dynamiques)
         },

         // Infos sur l'eau: niveau, couleur, type de transparence
         16*60-1, RGB(8,2,10), 0x1000|0x4,

         // Infos sur l'arrière-plan
         {
			// Tileset
			BG_AquaticRuin_tiles, sizeof(BG_AquaticRuin_tiles),
			// Palette
			BG_AquaticRuin_palette, sizeof(BG_AquaticRuin_palette),
			// Map + taille
			BG_AquaticRuin_map, 112, 192,
			// Script de scrolling
			AquaticRuin_linescroll_script,
			// Facteur de scrolling vertical (256 = 1.0)
			192,
         },

		 // Infos sur les objets
         {
            &aquaticruin_01_liste_nbEle,
            aquaticruin_01_liste
         },

		 // Infos avancées pour le moteur
         {
             1,								// Blocage d'angle
             AquaticRuin_typesSpeciaux,		// Types de blocs spéciaux de la map de collision
             true,							// Utilisation personnelle du BG3
         },

         // Infos diverses
         "aquatic.bgm",						// Fichier de musique à utiliser
         AquaticRuin_Init,					// Fonction à appeler à l'initialisation
         NULL,								// Fonction à appeler à chaque frame
         AquaticRuin_Palette,				// Fonction à appeler pour la création des palettes
         AquaticRuin_AfterPalette,			// Fonction à appeler une fois les palettes créées
         AquaticRuin_Loop2,					// Fonction à appeler à chaque VBLANK
    },
    
	{
		//Indications
		5, 0, "Aquatic Ruins", 2,

		//Avant-plan
		{
			720,114,
//			287*16,56*16,
			1*16,48*16,
			AquaticRuin_tiles,
			aquaticruin_acte2_gfx,
			aquaticruin_acte2_col,
			AquaticRuin_anims,
			8, MAX_TILES_DEFAULT,
		},

		//Eau
		16*65-1, RGB(8,2,10), 0x1000|0x4,
//		1000, RGB(0,0,31), 16,

		//Arrière-plan
		{
			BG_AquaticRuin_tiles, sizeof(BG_AquaticRuin_tiles),
			BG_AquaticRuin_palette, sizeof(BG_AquaticRuin_palette),
			BG_AquaticRuin_map, 112, 192,
			AquaticRuin_linescroll_script,
			192,
		},

		{
			&aquaticruin_02_liste_nbEle,
			aquaticruin_02_liste
		},

		{
			1,
			AquaticRuin_typesSpeciaux,
			1,
		},

		//Divers
		"aquatic.bgm",
		AquaticRuin_Init,
		AquaticRuin_Loop2,
		AquaticRuin_Palette,
		AquaticRuin_AfterPalette,
	 },

	 {
		 //Indications
		 6,0,"Aquatic Ruins",3,
		 //Avant-plan
		 {
			395,50,
//			287*16,56*16,
			1*16,34*16,
			AquaticRuin_tiles,
//			patterns_nv1_palette, sizeof(patterns_nv1_palette),
			aquaticruin_acte3_gfx,
			aquaticruin_acte3_col,
			AquaticRuin_anims,
			8, MAX_TILES_DEFAULT,
		},

		//Eau
		16*65-1, RGB(8,2,10), 0x1000|0x4,
//		1000, RGB(0,0,31), 16,

		//Arrière-plan
		{
			BG_AquaticRuin_tiles, sizeof(BG_AquaticRuin_tiles),
			BG_AquaticRuin_palette, sizeof(BG_AquaticRuin_palette),
			BG_AquaticRuin_map, 112, 192,
			AquaticRuin_linescroll_script,
//			96,
//			112,
			192,
		},
		{
			&aquaticruin_03_liste_nbEle,
			aquaticruin_03_liste
		},
		{
			1,
			AquaticRuin_typesSpeciaux,
			1,
		},
		//Divers
		"aquatic.bgm",
		AquaticRuin_Init,
		AquaticRuin_Loop2,
		AquaticRuin_Palette,
		AquaticRuin_AfterPalette,
	}
};

const int ExtNbreNiveaux=sizeof(ExtNiveaux)/sizeof(ExtNiveaux[0]);


