/**********************************************************************************
 Nintendo Power Splitter
 
 Author:           sanni
 Date:             2016-05-02
 Version:          V1
 
 Compiled with Processing 3.0.2
 **********************************************************************************/

/******************************************
 Variables
 *****************************************/
// Define 4MB byte array that stores the file
byte[] NP = new byte[4194303];

// Define 12 byte array to store menu string
byte menuString[] = {0x4D, 0x45, 0x4E, 0x55, 0x20, 0x50, 0x52, 0x4F, 0x47, 0x52, 0x41, 0x4D};

// Menu variables
boolean npMenu = true;
byte numGames = 0;

// rom info arrays
char[][] romName = new char[8][21];
int[] romAddress = new int[8];
int[] romSize = new int[8];
char[][] romCode = new char[8][12];
boolean[] hirom = new boolean[8];

/******************************************
 Setup
 *****************************************/
void setup() {
  // Make 500x300 pixel window with black background
  size(500, 300);
  background(0);
  
  NP[4194302] = 0x66;
  
  // Write title
  text("Nintendo Power Splitter V1", 20, 20);

  // File open dialog
  selectInput("Select 4MB NP dump:", "fileSelected");
  noLoop();
}

/******************************************
 Helper Functions
 *****************************************/
// Loads selected file into byte array
void fileSelected(File selection) {
  if (selection != null) 
    NP = loadBytes(selection);
}

/******************************************
 Main function
 *****************************************/
void draw() {
  // Wait until array is filled with the 4MB file
  while (NP[4194302] == 0x66) {
    delay(200);
  }

  // Check if menu is present
  for (int i = 0; i < 12; i++) {
    if (menuString[i] != NP[0x7FC0+i]) {
      npMenu = false;
    }
  }
  if (npMenu) {
    // Count number of games
    for (int i = 0x60000; i < 0x6E000; i += 0x2000) {
      if (NP[i] == numGames )
        numGames++;
    }
    text("Number of games: " + (numGames), 20, 60);

    // Get game info
    for (int i = 0; i < numGames; i++) {

      // Read starting address and size
      romAddress[i] = NP[0x60000 + i*0x2000 + 0x01] * 0x80000;
      romSize[i] = NP[0x60000 + i*0x2000 + 0x03] * 131072;

      // Read game code
      for (int j = 0; j < 12; j++) {
        romCode[i][j] = char(NP[0x60000 + i*0x2000 + 0x07 + j]);
      }

      //check if hirom
      if (NP[romAddress[i]+0xFFD5] == 0x31) {
        hirom[i] = true;
      } else {
        hirom[i] = false;
      }

      // Read rom name
      for (int j = 0; j < 21; j++) {
        if (hirom[i]) {
          romName[i][j] = char(NP[romAddress[i]+0xFFC0+j]);
        } else {
          romName[i][j] = char(NP[romAddress[i]+0x7FC0+j]);
        }
      }
      // Convert char array to String to be printed
      String tempStr1 = new String(romName[i]);

      // Convert char array to String to be printed
      String tempStr2 = new String(romCode[i]);

      // Clean the Strings
      tempStr1 = tempStr1.trim();
      tempStr1 = tempStr1.replaceAll("-$", "");
      tempStr1 = tempStr1.trim(); 
      tempStr2 = tempStr2.trim();
      tempStr2 = tempStr2.replaceAll("-$", "");
      tempStr2 = tempStr2.trim(); 

      // Print all info
      text("Game" + i + ": " + tempStr1 + " " + tempStr2 +  " Addr: 0x" + hex(romAddress[i]) + " Size: " + romSize[i]/1024 + "KB", 20, 80+i*20);
    }

    // Split the rom
    for (int i = 0; i < numGames; i++) {
      byte[] OUT = new byte[romSize[i]];
      String fileName = new String(romCode[i]);

      // Clean the String
      fileName = fileName.trim();
      fileName = fileName.replaceAll("-$", "");
      fileName = fileName.trim(); 

      // Create the array to be written to a file
      for (int j = 0; j < romSize[i]; j++) {
        OUT[j] = NP[romAddress[i] + j];
      }
      // Write the file
      saveBytes(fileName + ".bin", OUT);
    }
  } else {
    text("NP menu not found.", 20, 60);
  }
}
//******************************************
// End of File
//******************************************