#include <nds.h>
#include "main.h"

#ifndef __BACKGROUNDS_H__
#define __BACKGROUNDS_H__

	// Backgrounds
#include "level1Ground_bin.h"
#include "level1GroundMap_bin.h"
#include "level1Down_bin.h"
#include "level1DownMap_bin.h"
#include "level1Pal_bin.h"
#include "level1Up_bin.h"
#include "level1UpMap_bin.h"
#include "level1ColMap_bin.h"
#include "level2Ground_bin.h"
#include "level2GroundMap_bin.h"
#include "level2Down_bin.h"
#include "level2DownMap_bin.h"
#include "level2Pal_bin.h"
#include "level2Up_bin.h"
#include "level2UpMap_bin.h"
#include "level2ColMap_bin.h"
#include "level3Ground_bin.h"
#include "level3GroundMap_bin.h"
#include "level3Down_bin.h"
#include "level3DownMap_bin.h"
#include "level3Pal_bin.h"
#include "level3Up_bin.h"
#include "level3UpMap_bin.h"
#include "level3ColMap_bin.h"
#include "level4Ground_bin.h"
#include "level4GroundMap_bin.h"
#include "level4Down_bin.h"
#include "level4DownMap_bin.h"
#include "level4Pal_bin.h"
#include "level4Up_bin.h"
#include "level4UpMap_bin.h"
#include "level4ColMap_bin.h"
#include "level5Ground_bin.h"
#include "level5GroundMap_bin.h"
#include "level5Down_bin.h"
#include "level5DownMap_bin.h"
#include "level5Pal_bin.h"
#include "level5Up_bin.h"
#include "level5UpMap_bin.h"
#include "level5ColMap_bin.h"
#include "level6Ground_bin.h"
#include "level6GroundMap_bin.h"
#include "level6Down_bin.h"
#include "level6DownMap_bin.h"
#include "level6Pal_bin.h"
#include "level6Up_bin.h"
#include "level6UpMap_bin.h"
#include "level6ColMap_bin.h"
#include "level7Ground_bin.h"
#include "level7GroundMap_bin.h"
#include "level7Down_bin.h"
#include "level7DownMap_bin.h"
#include "level7Pal_bin.h"
#include "level7Up_bin.h"
#include "level7UpMap_bin.h"
#include "level7ColMap_bin.h"
#include "level8Ground_bin.h"
#include "level8GroundMap_bin.h"
#include "level8Down_bin.h"
#include "level8DownMap_bin.h"
#include "level8Pal_bin.h"
#include "level8Up_bin.h"
#include "level8UpMap_bin.h"
#include "level8ColMap_bin.h"
#include "level9Ground_bin.h"
#include "level9GroundMap_bin.h"
#include "level9Down_bin.h"
#include "level9DownMap_bin.h"
#include "level9Pal_bin.h"
#include "level9Up_bin.h"
#include "level9UpMap_bin.h"
#include "level9ColMap_bin.h"
#include "level10Ground_bin.h"
#include "level10GroundMap_bin.h"
#include "level10Down_bin.h"
#include "level10DownMap_bin.h"
#include "level10Pal_bin.h"
#include "level10Up_bin.h"
#include "level10UpMap_bin.h"
#include "level10ColMap_bin.h"
#include "level11Ground_bin.h"
#include "level11GroundMap_bin.h"
#include "level11Down_bin.h"
#include "level11DownMap_bin.h"
#include "level11Pal_bin.h"
#include "level11Up_bin.h"
#include "level11UpMap_bin.h"
#include "level11ColMap_bin.h"
#include "level12Ground_bin.h"
#include "level12GroundMap_bin.h"
#include "level12Down_bin.h"
#include "level12DownMap_bin.h"
#include "level12Pal_bin.h"
#include "level12Up_bin.h"
#include "level12UpMap_bin.h"
#include "level12ColMap_bin.h"
#include "level13Ground_bin.h"
#include "level13GroundMap_bin.h"
#include "level13Down_bin.h"
#include "level13DownMap_bin.h"
#include "level13Pal_bin.h"
#include "level13Up_bin.h"
#include "level13UpMap_bin.h"
#include "level13ColMap_bin.h"
#include "level14Ground_bin.h"
#include "level14GroundMap_bin.h"
#include "level14Down_bin.h"
#include "level14DownMap_bin.h"
#include "level14Pal_bin.h"
#include "level14Up_bin.h"
#include "level14UpMap_bin.h"
#include "level14ColMap_bin.h"
#include "level15Ground_bin.h"
#include "level15GroundMap_bin.h"
#include "level15Down_bin.h"
#include "level15DownMap_bin.h"
#include "level15Pal_bin.h"
#include "level15Up_bin.h"
#include "level15UpMap_bin.h"
#include "level15ColMap_bin.h"
#include "level16Ground_bin.h"
#include "level16GroundMap_bin.h"
#include "level16Down_bin.h"
#include "level16DownMap_bin.h"
#include "level16Pal_bin.h"
#include "level16Up_bin.h"
#include "level16UpMap_bin.h"
#include "level16ColMap_bin.h"
#include "level17Ground_bin.h"
#include "level17GroundMap_bin.h"
#include "level17Down_bin.h"
#include "level17DownMap_bin.h"
#include "level17Pal_bin.h"
#include "level17Up_bin.h"
#include "level17UpMap_bin.h"
#include "level17ColMap_bin.h"
#include "level18Ground_bin.h"
#include "level18GroundMap_bin.h"
#include "level18Down_bin.h"
#include "level18DownMap_bin.h"
#include "level18Pal_bin.h"
#include "level18Up_bin.h"
#include "level18UpMap_bin.h"
#include "level18ColMap_bin.h"
		
#include "gameOver_bin.h"
#include "gameOverMap_bin.h"
		
#include "stamp1st_bin.h"
#include "splPal_bin.h"
#include "splSprPal_bin.h"
#include "splLayer1_bin.h"
#include "splLayer2_bin.h"
#include "splLayer3_bin.h"
		
#include "battleBeach_bin.h"
#include "battleBeachPal_bin.h"
#include "battleECastle_bin.h"
#include "battleECastlePal_bin.h"
#include "battleECave_bin.h"
#include "battleECavePal_bin.h"
#include "battleFCave_bin.h"
#include "battleFCavePal_bin.h"
#include "battleICave_bin.h"
#include "battleICavePal_bin.h"
#include "battleTown_bin.h"
#include "battleTownPal_bin.h"
#include "battleWoods_bin.h"
#include "battleWoodsPal_bin.h"
#include "battleCastle_bin.h"
#include "battleCastlePal_bin.h"
		
	// Defines
#define LEVEL_GND_TILES_ANIM(n,m)	(u8*)level##n##Ground##m##_bin
#define LEVEL_GND_TILES_ANIM_SIZE(n,m)level##n##Ground##m##_bin_size
#define LEVEL_GND_MAP_ANIM(n,m)  	(u8*)level##n##Ground##m##Map_bin
#define LEVEL_GND_MAP_ANIM_SIZE(n,m)level##n##Ground##m##Map_bin_size
#define LEVEL_GND_TILES(n)  		(u8*)level##n##Ground_bin
#define LEVEL_GND_TILES_SIZE(n)  	level##n##Ground_bin_size
#define LEVEL_GND_MAP(n)			(u8*)level##n##GroundMap_bin
#define LEVEL_GND_MAP_SIZE(n)		level##n##GroundMap_bin_size
#define LEVEL_UP_TILES(n)			(u8*)level##n##Up_bin
#define LEVEL_UP_TILES_SIZE(n)		level##n##Up_bin_size
#define LEVEL_UP_MAP(n)				(u8*)level##n##UpMap_bin
#define LEVEL_UP_MAP_SIZE(n)		level##n##UpMap_bin_size
#define LEVEL_DOWN_TILES(n)			(u8*)level##n##Down_bin
#define LEVEL_DOWN_TILES_SIZE(n)	level##n##Down_bin_size
#define LEVEL_DOWN_MAP(n)			(u8*)level##n##DownMap_bin
#define LEVEL_DOWN_MAP_SIZE(n)		level##n##DownMap_bin_size
#define levelPal(n) 				(u16*)level##n##Pal_bin
#define levelCollision(n) 			(u8*)level##n##ColMap_bin

#define levelData(n) {LEVEL_GND_TILES(n), LEVEL_GND_MAP(n), LEVEL_GND_TILES_SIZE(n), LEVEL_GND_MAP_SIZE(n)}, \
	{LEVEL_UP_TILES(n), LEVEL_UP_MAP(n), LEVEL_UP_TILES_SIZE(n), LEVEL_UP_MAP_SIZE(n)}, \
	{LEVEL_DOWN_TILES(n), LEVEL_DOWN_MAP(n), LEVEL_DOWN_TILES_SIZE(n), LEVEL_DOWN_MAP_SIZE(n)} \
		/*
#define NO_ANIMATION { }, { }, { }, { }
	
#define levelAnimation(n) 	levelMaps[(n-1)*3], \
	{ LEVEL_GND_TILES_ANIM(n,2), LEVEL_GND_MAP_ANIM(n,2), LEVEL_GND_TILES_ANIM_SIZE(n,2), LEVEL_GND_MAP_ANIM_SIZE(n,2) }, \
	{ LEVEL_GND_TILES_ANIM(n,3), LEVEL_GND_MAP_ANIM(n,3), LEVEL_GND_TILES_ANIM_SIZE(n,3), LEVEL_GND_MAP_ANIM_SIZE(n,3) }, \
	{ LEVEL_GND_TILES_ANIM(n,4), LEVEL_GND_MAP_ANIM(n,4), LEVEL_GND_TILES_ANIM_SIZE(n,4), LEVEL_GND_MAP_ANIM_SIZE(n,4) } \
*/
	// Types
typedef u8* mapTiles;
typedef u8* animMapTiles;
typedef u8* mapMap;
typedef u16* mapPalette;
		
typedef enum _gameMode_
{	
	LEVELMODE_SPLASH_FADEIN,
	LEVELMODE_SPLASH,
	LEVELMODE_SPLASH_FADEOUT,
	LEVELMODE_MENU_FADEIN,
	LEVELMODE_MENU_START,
	LEVELMODE_MENU_CHOICE,
	LEVELMODE_MENU_LOAD,
	LEVELMODE_INTRO,
	LEVELMODE_PLAY,
	LEVELMODE_INGAME_MENU,
	LEVELMODE_FADEOUT,
	LEVELMODE_SWITCHLEVEL,
	LEVELMODE_FADEIN,
	LEVELMODE_BATTLE_FADEIN,
	LEVELMODE_BATTLE_FADEOUT,
	LEVELMODE_BATTLE_FADEPAUSE,
	LEVELMODE_BATTLE,
	LEVELMODE_EXITBATTLE,
	LEVELMODE_GAMEOVER_FADEIN,
	LEVELMODE_GAMEOVER_FADEOUT,
	LEVELMODE_GAMEOVER,
	LEVELMODE_GAMEOVER_WHITEFADE,
		
} gameMode, *pGameMode;
		
typedef enum _battleMode_
{	
	BATTLE_GAUGESFILLS,
	BATTLE_PLAYERGAUGEFULL,
	BATTLE_MONSTERGAUGEFULL,
	BATTLE_PLAYERCHOICE,
	BATTLE_PLAYERCHOICE_MONSTER,
	BATTLE_PLAYERACTION,
	BATTLE_MONSTERACTION,
	BATTLE_SHOWRESULT_PLAYER,
	BATTLE_SHOWRESULT_MONSTER,
	BATTLE_ELIMINATEMONSTER,
	BATTLE_VICTORY,
	BATTLE_UPGRADESTATS,
	BATTLE_CHOOSEITEM,
	BATTLE_ITEMEFFECT,
		
} battleMode, *pBattleMode;
		
	// Map
typedef struct _Map_
{
	mapTiles tileData;
	mapMap mapData;
	u32 tileSize;
	u32 mapSize;
	
} Map, *pMap;
		
typedef enum _LEVELS_
{
	LEVEL1,
	LEVEL2,
	LEVEL3,
	LEVEL4,
	LEVEL5,
	LEVEL6,
	LEVEL7,
	LEVEL8,
	LEVEL9,
	LEVEL10,
	LEVEL11,
	LEVEL12,
	LEVEL13,
	LEVEL14,
	LEVEL15,
	LEVEL16,
	LEVEL17,
	LEVEL18,
		
	LEVEL_SIZE,
	NO_LEVEL,
		
} LEVELS;
		
typedef struct _levelLink_ {
	int startTile;
	int endTile;
	int posFix;
	LEVELS loadedLevel;
	Direction wallDir;
		
} levelLink, *pLevelLink;

typedef struct _doorLink_ {
	int startTileX, endTileX;
	int startTileY, endTileY;
	int posFixX, posFixY;
	Direction loadedDir;
	LEVELS loadedLevel;
		
} doorLink, *pDoorLink;
		
typedef struct _saveData_
{
	char saveName[256];
	int posX, posY;
	LEVELS curLevel;
	Attributes playerStats;
	int curEvent;
	int playerItems[DATABASE_SIZE];
	int equipedItems[ITEM_ATTR_SIZE];
	bool workingChests[25];
	u32 timePlayed;
	bool isLoaded;
		
} PACKED saveData, *pSaveData;
		
typedef struct _gameVars_
{
	gameMode curMode, lstMode;
	int fadeVal, tickVal, fadeHalt;
	bool isFade, isBattle, isInit;
	LEVELS loadedLevel;
	s32 flowerAngle, textZoom;
	int newPosX, newPosY;
	Direction newDir;
	int curEvent, curCutsceneIdx, eventSaveParam;
	pFigure lstTalkedFigure;
	saveData saveSlots[3];
	u32 timePlayed, lstCou, curCou;
	s32 usesGameSave;
	bool isFAT;
		
} gameVars, *pGameVars;
		
typedef struct _Gauge_
{
	int gTimer, gTick, gRate;
	int posX, posY;
	pSpriteEntry indSpr;
	int dataOffset;
	bool isFull, isHalt;
		
} Gauge, *pGauge;
		
typedef struct _battleVars_
{
	int posX, posY;
	Direction lstDir; 
	int lstLevel;
		
	bool isSet, isBoss;
	battleMode curMode;
	pSpriteEntry cursorSprite;
	Gauge playerG;
	Weapon activeWeapon;
	int animIdx, animTick, hpDec;
	int deltaLevel;
	Monster curMonster;
	Gauge mnsGuage;
	itemList battleItems;
	
} battleVars, *pBattleVars;
		
	// Level
typedef struct _Level_
{
	int dimX, dimY;
	int viewX, viewY;
	Map* upMap;
	Map* downMap;
	Map* groundMap;
	u8* colMap;
	mapPalette levelPal;
//	bool isAnimated;
//	Map* animData[4];
//	int animIndex;
	pLevelLink linkedLevels;
	pDoorLink linkedDoors;
	LEVELS levelIdx;
		
		// Battle vars
	u8 *battleTiles, *battlePal;
	int battleMon;
		
} Level, *pLevel;
		
typedef struct _NPC_
{
	pFigure Figure;
	int posX, posY;
	int moveX, moveY;
	LEVELS linkedLevel;
	Direction faceDir;
	u8* npcData;
	u16* npcPalette;
	const char* npcName;
	const char* npcText;
		
} NPC, *pNPC;
		
	// Protoypes
void initGame(void);
void updateView(void);
void backgroundUpdateView(u16* workMap, const u16* targetMap);
void initLevels(void);
void initMode(gameMode selMode);
void loadLevel(LEVELS lvlIdx);
void graphicInitGame(void);
void graphicInitSplash(void);
void graphicInitMainMenu(void);
void graphicInitBattle(void);
bool isCollisionDoor(pFigure Figure, pDoorLink doorLink);
void startBattle(int mnsIdx);
		
void initGauge(pGauge workGauge, int posX, int posY, int gRate);
void updateGauge(pGauge workGauge);
void resetGuage(pGauge workGauge);
		
	// Data
extern pLevel curLevel;
extern gameVars gameValues;
extern battleVars battleValues;
extern Map levelMaps[LEVEL_SIZE*3];
extern Level Levels[LEVEL_SIZE];
extern Level battleLevel;
extern const u32 levelSizes[LEVEL_SIZE*2];
extern const int levelStartPos[LEVEL_SIZE*2];
extern u16* levelPalettes[LEVEL_SIZE];
extern u8* levelCollisions[LEVEL_SIZE];
extern const bool levelAnimation[LEVEL_SIZE];
extern Map animLevelTiles[LEVEL_SIZE*4];
extern pLevelLink levelLinking[LEVEL_SIZE];
extern pDoorLink doorLinking[LEVEL_SIZE];
extern const NPC gameNPCs[];
extern const u8* bgMusic[LEVEL_SIZE];
extern const u8* battleMapsPals[LEVEL_SIZE*2];
		
	// Compression code
void decompressToVRAM(const void* source, void* dest);
		
	// Save/Load features
bool loadSavedGame(int saveSlot, pSaveData gameData);
void loadSave(pSaveData gameData);
bool saveGame(int saveSlot);
void fillSaves();
		
	// Level linkers
extern levelLink level1Link[];
extern levelLink level2Link[];
extern levelLink level3Link[];
extern levelLink level4Link[];
extern levelLink level5Link[];
extern levelLink level6Link[];
extern levelLink level7Link[];
extern levelLink level8Link[];
extern levelLink level9Link[];
extern levelLink level10Link[];
extern levelLink level11Link[];
extern levelLink level12Link[];
extern levelLink level13Link[];
extern levelLink level14Link[];
extern levelLink level15Link[];
extern levelLink level16Link[];
extern levelLink level17Link[];
extern levelLink level18Link[];
		
extern doorLink doorLink1[];
extern doorLink doorLink2[];
extern doorLink doorLink3[];
extern doorLink doorLink4[];
extern doorLink doorLink5[];
extern doorLink doorLink6[];
extern doorLink doorLink7[];
extern doorLink doorLink8[];
extern doorLink doorLink9[];
extern doorLink doorLink10[];
extern doorLink doorLink11[];
extern doorLink doorLink12[];
extern doorLink doorLink13[];
extern doorLink doorLink14[];
extern doorLink doorLink15[];
extern doorLink doorLink16[];
extern doorLink doorLink17[];
extern doorLink doorLink18[];
		
#endif
