#ifdef _WIN32
#define ENV_WIN
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#else
#define _FILE_OFFSET_BITS 64
#endif

int rev=1;

unsigned int char_arr_BE_to_uint(unsigned char* arr)
{
  return arr[3] + 256*(arr[2] + 256*(arr[1] + 256*arr[0]));
}

void help()
{
  puts("Simple check that a PS3 iso has been fully dumped");
  puts("Uses the cryptographic layer definition in sector 0 to get expected filesize");
  puts("Usage: PS3DumpCheck iso_1 iso_2 ...\n");
}

int main(int argc, char*argv[])
{
  FILE* iso;
  unsigned int expected;
  unsigned int actual;
  unsigned char* sec0;
  int i;
#ifdef ENV_WIN
  __int64 ftell_res;
#else
  off_t ftell_res;
#endif

  sec0=malloc(2048);

  printf("PS3DumpCheck r%d\n", rev);

  if(argc<=1)
  {
    help();
    return 1;
  }

  i=1;
  while(i<argc)
  {
    if( (iso=fopen(argv[i], "rb"))==NULL )
      printf("WARNING '%s': Open failed\n", argv[i]);
    else
    {
      if( fread(sec0, 1, 2048, iso)!=2048 )
        printf("WARNING '%s': Read failed\n", argv[i]);
      else
      {
        if( char_arr_BE_to_uint(sec0)>255 )
          printf("WARNING '%s': Last sector range supposedly defined beyond sector 0\n", argv[i]);
        else if( char_arr_BE_to_uint(sec0)==0)
          printf("WARNING '%s': No unencrypted sector ranges defined (there should be)\n", argv[i]);
        else
        {
          expected=char_arr_BE_to_uint(sec0+(char_arr_BE_to_uint(sec0)*8)+4)+1;
#ifdef ENV_WIN
          _fseeki64(iso, 0, SEEK_END);
          ftell_res=_ftelli64(iso);
#else
          fseeko(iso, 0, SEEK_END);
          ftell_res=ftell(iso);
#endif
          if(ftell_res%2048!=0)
            printf("WARNING '%s': Ends with a partial sector\n", argv[i]);
          else
          {
            actual=(unsigned int) (ftell_res/2048);
            if(expected==actual)
              printf("GOOD '%s': Has the expected number of sectors (%u)\n", argv[i], expected);
            else
              printf("BAD '%s': Doesn't have the expected number of sectors (expected=%u, actual=%u, possible %s)\n", argv[i], expected, actual, expected<actual?"overdump":"underdump");
          }
        }
      }
      fclose(iso);
    }
    ++i;
  }
  
  free(sec0);
  return 0;
}

