
#include "nx.h"
#include "profile.h"
#include "profile.fdh"
#include "libretro/libretro_shared.h"

#define PF_WEAPONS_OFFS		0x38
#define PF_CURWEAPON_OFFS	0x24
#define PF_INVENTORY_OFFS	0xD8
#define PF_TELEPORTER_OFFS	0x158
#define PF_FLAGS_OFFS		0x218

#define MAX_WPN_SLOTS		8
#define MAX_TELE_SLOTS		8

// load savefile #num into the given Profile structure.
bool profile_load(const char *pfname, Profile *file)
{
   int i, curweaponslot;
   FILE *fp = fopen(pfname, "rb");

   memset(file, 0, sizeof(Profile));

   if (!fp)
      return 1;

   if (!fverifystring(fp, "Do041220"))
      goto error;

   file->stage = fgetl(fp);
   file->songno = fgetl(fp);

   file->px = fgetl(fp);
   file->py = fgetl(fp);
   file->pdir = CVTDir(fgetl(fp));

   file->maxhp = fgeti(fp);
   file->num_whimstars = fgeti(fp);
   file->hp = fgeti(fp);

   fgeti(fp);						// unknown value
   curweaponslot = fgetl(fp);		// current weapon (slot, not number, converted below)
   fgetl(fp);						// unknown value
   file->equipmask = fgetl(fp);	// equipped items

   // load weapons
   fseek(fp, PF_WEAPONS_OFFS, SEEK_SET);
   for(i=0;i<MAX_WPN_SLOTS;i++)
   {
      int level, xp, maxammo, ammo;
      int type = fgetl(fp);
      if (!type)
         break;

      level   = fgetl(fp);
      xp      = fgetl(fp);
      maxammo = fgetl(fp);
      ammo    = fgetl(fp);

      file->weapons[type].hasWeapon = true;
      file->weapons[type].level = (level - 1);
      file->weapons[type].xp = xp;
      file->weapons[type].ammo = ammo;
      file->weapons[type].maxammo = maxammo;

      if (i == curweaponslot)
         file->curWeapon = type;
   }

   /* load inventory */
   file->ninventory = 0;
   fseek(fp, PF_INVENTORY_OFFS, SEEK_SET);
   for(i=0;i<MAX_INVENTORY;i++)
   {
      int item = fgetl(fp);
      if (!item)
         break;

      file->inventory[file->ninventory++] = item;
   }

   /* load teleporter slots */
   file->num_teleslots = 0;
   fseek(fp, PF_TELEPORTER_OFFS, SEEK_SET);

   for(i=0;i<NUM_TELEPORTER_SLOTS;i++)
   {
      int slotno   = fgetl(fp);
      int scriptno = fgetl(fp);
      if (slotno == 0)
         break;

      file->teleslots[file->num_teleslots].slotno = slotno;
      file->teleslots[file->num_teleslots].scriptno = scriptno;
      file->num_teleslots++;
   }

   /* load flags */
   fseek(fp, PF_FLAGS_OFFS, SEEK_SET);
   if (!fverifystring(fp, "FLAG"))
   {
      NX_ERR("profile_load: missing 'FLAG' marker\n");
      goto error;
   }

   fresetboolean();
   for(i=0;i<NUM_GAMEFLAGS;i++)
      file->flags[i] = fbooleanread(fp);

   fclose(fp);
   return 0;

error:
   fclose(fp);
   return 1;
}


bool profile_save(const char *pfname, Profile *file)
{
   int i, slotno = 0, curweaponslot = 0;
   FILE *fp = fopen(pfname, "wb");

   if (!fp)
      return 1;

   fputstringnonull("Do041220", fp);

   fputl(file->stage, fp);
   fputl(file->songno, fp);

   fputl(file->px, fp);
   fputl(file->py, fp);
   fputl((file->pdir == RIGHT) ? 2:0, fp);

   fputi(file->maxhp, fp);
   fputi(file->num_whimstars, fp);
   fputi(file->hp, fp);

   fseek(fp, 0x2C, SEEK_SET);
   fputi(file->equipmask, fp);

   /* save weapons */
   fseek(fp, PF_WEAPONS_OFFS, SEEK_SET);

   for(i = 0; i < WPN_COUNT; i++)
   {
      if (file->weapons[i].hasWeapon)
      {
         fputl(i, fp);
         fputl(file->weapons[i].level + 1, fp);
         fputl(file->weapons[i].xp, fp);
         fputl(file->weapons[i].maxammo, fp);
         fputl(file->weapons[i].ammo, fp);

         if (i == file->curWeapon)
            curweaponslot = slotno;

         slotno++;
         if (slotno >= MAX_WPN_SLOTS)
            break;
      }
   }

   if (slotno < MAX_WPN_SLOTS)
      fputl(0, fp);	// 0-type weapon: terminator

   /* go back and save slot no of current weapon */
   fseek(fp, PF_CURWEAPON_OFFS, SEEK_SET);
   fputl(curweaponslot, fp);

   /* save inventory */
   fseek(fp, PF_INVENTORY_OFFS, SEEK_SET);
   for(i=0;i<file->ninventory;i++)
      fputl(file->inventory[i], fp);

   fputl(0, fp);

   /* write teleporter slots */
   fseek(fp, PF_TELEPORTER_OFFS, SEEK_SET);
   for(i=0;i<MAX_TELE_SLOTS;i++)
   {
      if (i < file->num_teleslots)
      {
         fputl(file->teleslots[i].slotno, fp);
         fputl(file->teleslots[i].scriptno, fp);
      }
      else
      {
         fputl(0, fp);
         fputl(0, fp);
      }
   }

   /* write flags */
   fseek(fp, PF_FLAGS_OFFS, SEEK_SET);
   fputstringnonull("FLAG", fp);

   fresetboolean();
   for(i=0;i<NUM_GAMEFLAGS;i++)
      fbooleanwrite(file->flags[i], fp);

   fbooleanflush(fp);

   fclose(fp);
   return 0;
}


/*
void c------------------------------() {}
*/

// returns the filename for a save file given it's number
const char *GetProfileName(int num)
{
   static char pfname_tmp[1024];
   char profile_name[1024];
   const char* save_dir = retro_get_save_dir();

   if (num == 0)
      snprintf(profile_name, sizeof(profile_name), "profile.dat");
   else
      snprintf(profile_name, sizeof(profile_name), "profile%d.dat", num+1);

   retro_create_path_string(pfname_tmp, sizeof(pfname_tmp), save_dir, profile_name);
   return pfname_tmp;
}

// returns whether the given save file slot exists
bool ProfileExists(int num)
{
   return file_exists(GetProfileName(num));
}

bool AnyProfileExists(void)
{
   for(int i=0;i<MAX_SAVE_SLOTS;i++)
      if (ProfileExists(i))
         return true;

   return false;
}



