Пример #1
0
 BSA(String filePath, boolean load) throws FileNotFoundException, IOException, BadParameter {
   this.filePath = filePath;
   in.openFile(filePath);
   if (!in.extractString(0, 3).equals("BSA") || in.extractInt(1, 4) != 104) {
     throw new BadParameter("Was not a BSA file of version 104: " + filePath);
   }
   offset = in.extractInt(0, 4);
   archiveFlags = new LFlags(in.extract(0, 4));
   folderCount = in.extractInt(0, 4);
   folders = new HashMap<>(folderCount);
   fileCount = in.extractInt(0, 4);
   folderNameLength = in.extractInt(0, 4);
   fileNameLength = in.extractInt(0, 4);
   fileFlags = new LFlags(in.extract(0, 4));
   if (SPGlobal.debugBSAimport && SPGlobal.logging()) {
     SPGlobal.logSpecial(LogTypes.BSA, header, "|==================>");
     SPGlobal.logSpecial(LogTypes.BSA, header, "| Imported " + filePath);
     SPGlobal.logSpecial(
         LogTypes.BSA, header, "| Offset " + offset + ", archiveFlags: " + archiveFlags);
     SPGlobal.logSpecial(
         LogTypes.BSA,
         header,
         "| hasDirectoryNames: "
             + archiveFlags.get(0)
             + ", hasFileNames: "
             + archiveFlags.get(1)
             + ", compressed: "
             + archiveFlags.get(2));
     SPGlobal.logSpecial(
         LogTypes.BSA,
         header,
         "| FolderCount: "
             + Ln.prettyPrintHex(folderCount)
             + ", FileCount: "
             + Ln.prettyPrintHex(fileCount));
     SPGlobal.logSpecial(
         LogTypes.BSA,
         header,
         "| totalFolderNameLength: "
             + Ln.prettyPrintHex(folderNameLength)
             + ", totalFileNameLength: "
             + Ln.prettyPrintHex(fileNameLength));
     SPGlobal.logSpecial(LogTypes.BSA, header, "| fileFlags: " + fileFlags.toString());
     SPGlobal.logSpecial(LogTypes.BSA, header, "|==================>");
   }
   if (load) {
     loadFolders();
   }
 }
Пример #2
0
 static ArrayList<String> processINIline(String in) {
   if (SPGlobal.logging()) {
     SPGlobal.logSpecial(LogTypes.BSA, header, "Processing line: " + in);
   }
   ArrayList<String> out = new ArrayList<>();
   int index = in.indexOf("=");
   if (index != -1) {
     in = in.substring(index + 1);
     String[] split = in.split(",");
     for (String s : split) {
       s = s.trim();
       if (!s.isEmpty()) {
         out.add(s);
       }
     }
   }
   return out;
 }
Пример #3
0
  /**
   * Returns BSA object associated with modlisting, or null if there is none.
   *
   * @param m
   * @return
   */
  public static BSA getBSA(ModListing m) {
    if (pluginLoadOrder.containsKey(m)) {
      return pluginLoadOrder.get(m);
    }

    File bsaPath = new File(SPGlobal.pathToData + Ln.changeFileTypeTo(m.print(), "bsa"));
    if (bsaPath.exists()) {
      try {
        BSA bsa = new BSA(bsaPath, false);
        pluginLoadOrder.put(m, bsa);
        return bsa;
      } catch (IOException | BadParameter ex) {
        logBSAError(m.printNoSuffix() + ".bsa", ex);
        return null;
      }
    }

    if (SPGlobal.logging()) {
      SPGlobal.logSpecial(
          LogTypes.BSA, header, "  BSA skipped because it didn't exist: " + bsaPath);
    }
    return null;
  }
Пример #4
0
  static void loadPluginLoadOrder() {
    if (pluginsLoaded) {
      return;
    }
    if (SPGlobal.logging()) {
      SPGlobal.logSpecial(LogTypes.BSA, header, "Loading in active plugin BSA headers.");
    }
    try {
      ArrayList<ModListing> activeMods = SPImporter.getActiveModList();
      for (ModListing m : activeMods) {
        if (!pluginLoadOrder.containsKey(m)) {
          BSA bsa = getBSA(m);
          if (bsa != null) {
            pluginLoadOrder.put(m, bsa);
          }
        }
      }
    } catch (IOException ex) {
      SPGlobal.logException(ex);
    }

    pluginsLoaded = true;
  }
Пример #5
0
 /**
  * @param filePath File to query for.
  * @return The used file, which prioritizes loose files first, and then BSAs.<br>
  *     NOTE: Not fully sophisticated yet for prioritizing between BSAs.
  * @throws IOException
  * @throws DataFormatException
  */
 public static LShrinkArray getUsedFile(String filePath) throws IOException, DataFormatException {
   File outsideBSA = new File(SPGlobal.pathToData + filePath);
   if (outsideBSA.isFile()) {
     SPGlobal.logSpecial(LogTypes.BSA, header, "Loaded from loose files: " + outsideBSA.getPath());
     return new LShrinkArray(outsideBSA);
   } else {
     Iterator<BSA> bsas = BSA.iterator();
     BSA tmp, bsa = null;
     while (bsas.hasNext()) {
       tmp = bsas.next();
       if (tmp.hasFile(filePath)) {
         bsa = tmp;
       }
     }
     if (bsa != null) {
       if (SPGlobal.logging()) {
         SPGlobal.logSpecial(
             LogTypes.BSA, header, "Loaded from BSA " + bsa.getFilePath() + ": " + filePath);
       }
       return bsa.getFile(filePath);
     }
   }
   return null;
 }
Пример #6
0
  void loadHeader(LShrinkArray in) throws BadParameter {

    // Gamebryo header
    if (SPGlobal.debugNIFimport) {
      SPGlobal.logSync(header, "Loading nif file");
    }
    if (!in.getString(20).equals("Gamebryo File Format")) {
      byte first = in.extract(1)[0];
      if (!in.extractString((int) first, 20).equals("Gamebryo File Format")) {
        throw new BadParameter(fileName + " was not a NIF file.");
      }
    }

    in.extractLine();

    // BlockTypes
    numBlocks = in.extractInt(9, 4);
    if (SPGlobal.debugNIFimport && SPGlobal.logging()) {
      SPGlobal.logSync(header, "Num Blocks: " + numBlocks);
    }
    in.skip(in.extractInt(4, 1)); // Author name
    in.skip(in.extractInt(1)); // Export Info 1
    in.skip(in.extractInt(1)); // Export Info 2
    int numBlockTypes = in.extractInt(2);
    if (SPGlobal.debugNIFimport && SPGlobal.logging()) {
      SPGlobal.logSync(header, "Num Block Types: " + numBlockTypes);
    }
    blockTypes = new ArrayList<>(numBlockTypes);
    for (int i = 0; i < numBlockTypes; i++) {
      String blockType = in.extractString(in.extractInt(4));
      blockTypes.add(blockType);
      if (SPGlobal.debugNIFimport && SPGlobal.logging()) {
        SPGlobal.logSync(header, "  Added block type[" + i + "]: " + blockType);
      }
    }

    // Blocks list
    if (SPGlobal.debugNIFimport && SPGlobal.logging()) {
      SPGlobal.logSync(header, "Block Type list: ");
    }
    nodes = new ArrayList<>(numBlocks);
    for (int i = 0; i < numBlocks; i++) {
      int type = in.extractInt(2);
      Node n = new Node(NodeType.SPvalueOf(blockTypes.get(type)));
      n.number = i;
      nodes.add(n);
      if (SPGlobal.debugNIFimport && SPGlobal.logging()) {
        SPGlobal.logSync(
            header,
            "  Block list[" + i + "] has block type: " + type + ", " + blockTypes.get(type));
      }
    }

    // Block lengths
    for (int i = 0; i < numBlocks; i++) {
      nodes.get(i).size = in.extractInt(4);
    }

    if (SPGlobal.debugNIFimport && SPGlobal.logging()) {
      SPGlobal.logSync(header, "Block headers: ");
      for (int i = 0; i < numBlocks; i++) {
        SPGlobal.logSync(
            header,
            "  ["
                + i
                + "]: "
                + nodes.get(i).type
                + ", length: "
                + Ln.prettyPrintHex(nodes.get(i).size));
      }
    }

    // Strings
    if (SPGlobal.debugNIFimport && SPGlobal.logging()) {
      SPGlobal.logSync(header, "Block Titles: ");
    }
    int numStrings = in.extractInt(4);
    in.skip(4); // max Length string
    ArrayList<String> strings = new ArrayList<>(numStrings);
    for (int i = 0; i < numStrings; i++) {
      strings.add(in.extractString(in.extractInt(4)));
    }
    in.skip(4); // unknown int

    for (int i = 0; i < numBlocks; i++) {
      nodes.get(i).data = new LShrinkArray(in, nodes.get(i).size);
      in.skip(nodes.get(i).size);
    }

    // Set titles
    for (int i = 0; i < numBlocks; i++) {
      NodeType type = nodes.get(i).type;
      if (type == NodeType.NINODE
          || type == NodeType.NITRISHAPE
          || type == NodeType.BSINVMARKER
          || type == NodeType.BSBEHAVIORGRAPHEXTRADATA) {
        Node n = nodes.get(i);
        int stringIndex = n.data.getInts(0, 4)[0];
        n.title = strings.get(stringIndex);
        if (SPGlobal.debugNIFimport && SPGlobal.logging()) {
          SPGlobal.log(
              header, "  [" + i + "]: " + nodes.get(i).type + ", string: " + nodes.get(i).title);
        }
      }
    }
  }
Пример #7
0
  static void loadResourceLoadOrder() {
    if (resourceLoadOrder != null) {
      return;
    }
    try {
      ArrayList<String> resources = new ArrayList<>();
      boolean line1 = false, line2 = false;
      try {
        File ini = SPGlobal.getSkyrimINI();

        if (SPGlobal.logging()) {
          SPGlobal.logSpecial(LogTypes.BSA, header, "Loading in BSA list from Skyrim.ini: " + ini);
        }
        LInChannel input = new LInChannel(ini);

        String line = "";
        // First line
        while (input.available() > 0 && !line.toUpperCase().contains("SRESOURCEARCHIVELIST")) {
          line = input.extractLine();
        }
        if (line.toUpperCase().contains("SRESOURCEARCHIVELIST2")) {
          line2 = true;
          resources.addAll(processINIline(line));
        } else {
          line1 = true;
          resources.addAll(0, processINIline(line));
        }

        // Second line
        line = "";
        while (input.available() > 0 && !line.toUpperCase().contains("SRESOURCEARCHIVELIST")) {
          line = Ln.cleanLine(input.extractLine(), "#");
        }
        if (line.toUpperCase().contains("SRESOURCEARCHIVELIST2")) {
          line2 = true;
          resources.addAll(processINIline(line));
        } else {
          line1 = true;
          resources.addAll(0, processINIline(line));
        }
      } catch (IOException e) {
        SPGlobal.logException(e);
      }

      if (!line1 || !line2) {
        // Assume standard BSA listing
        if (!resources.contains("Skyrim - Misc.bsa")) {
          resources.add("Skyrim - Misc.bsa");
        }

        if (!resources.contains("Skyrim - Shaders.bsa")) {
          resources.add("Skyrim - Shaders.bsa");
        }

        if (!resources.contains("Skyrim - Textures.bsa")) {
          resources.add("Skyrim - Textures.bsa");
        }

        if (!resources.contains("Skyrim - Interface.bsa")) {
          resources.add("Skyrim - Interface.bsa");
        }

        if (!resources.contains("Skyrim - Animations.bsa")) {
          resources.add("Skyrim - Animations.bsa");
        }

        if (!resources.contains("Skyrim - Meshes.bsa")) {
          resources.add("Skyrim - Meshes.bsa");
        }

        if (!resources.contains("Skyrim - Sounds.bsa")) {
          resources.add("Skyrim - Sounds.bsa");
        }

        if (!resources.contains("Skyrim - Sounds.bsa")) {
          resources.add("Skyrim - Voices.bsa");
        }

        if (!resources.contains("Skyrim - Sounds.bsa")) {
          resources.add("Skyrim - VoicesExtra.bsa");
        }
      }

      if (SPGlobal.logging()) {
        SPGlobal.logSpecial(LogTypes.BSA, header, "BSA resource load order: ");
        for (String s : resources) {
          SPGlobal.logSpecial(LogTypes.BSA, header, "  " + s);
        }
        SPGlobal.logSpecial(LogTypes.BSA, header, "Loading in their headers.");
      }

      // Get BSAs loaded from all active pluging's plugin.ini files
      ArrayList<ModListing> activeMods = SPImporter.getActiveModList();
      for (ModListing m : activeMods) {
        File pluginIni = new File(SPGlobal.pathToData + Ln.changeFileTypeTo(m.print(), "ini"));
        if (pluginIni.exists()) {
          LInChannel input = new LInChannel(pluginIni);

          String line = "";
          // First line
          while (input.available() > 0 && !line.toUpperCase().contains("SRESOURCEARCHIVELIST")) {
            line = input.extractLine();
          }
          if (line.toUpperCase().contains("SRESOURCEARCHIVELIST2")) {
            resources.addAll(processINIline(line));
          } else {
            resources.addAll(0, processINIline(line));
          }

          // Second line
          line = "";
          while (input.available() > 0 && !line.toUpperCase().contains("SRESOURCEARCHIVELIST")) {
            line = Ln.cleanLine(input.extractLine(), "#");
          }
          if (line.toUpperCase().contains("SRESOURCEARCHIVELIST2")) {
            resources.addAll(processINIline(line));
          } else {
            resources.addAll(0, processINIline(line));
          }
        }
      }

      resourceLoadOrder = new ArrayList<>(resources.size());
      for (String s : resources) {
        File bsaPath = new File(SPGlobal.pathToData + s);
        if (bsaPath.exists()) {
          try {
            if (SPGlobal.logging()) {
              SPGlobal.logSpecial(LogTypes.BSA, header, "Loading: " + bsaPath);
            }
            BSA bsa = new BSA(bsaPath, false);
            resourceLoadOrder.add(bsa);
          } catch (BadParameter | FileNotFoundException ex) {
            logBSAError(s, ex);
          }
        } else if (SPGlobal.logging()) {
          SPGlobal.logSpecial(
              LogTypes.BSA, header, "  BSA skipped because it didn't exist: " + bsaPath);
        }
      }

    } catch (IOException ex) {
      SPGlobal.logException(ex);
    }
  }
Пример #8
0
 final void loadFolders() {
   if (loaded) {
     return;
   }
   loaded = true;
   if (SPGlobal.logging()) {
     SPGlobal.logSpecial(LogTypes.BSA, header, "|============================================");
     SPGlobal.logSpecial(LogTypes.BSA, header, "|============  Loading " + this + " ============");
     SPGlobal.logSpecial(LogTypes.BSA, header, "|============================================");
   }
   try {
     String fileName;
     int fileCounter = 0;
     in.pos(offset);
     LShrinkArray folderData = new LShrinkArray(in.extract(0, folderCount * 16));
     posAtFilenames();
     LShrinkArray fileNames = new LShrinkArray(in.extract(0, fileNameLength));
     for (int i = 0; i < folderCount; i++) {
       BSAFolder folder = new BSAFolder();
       folderData.skip(8); // Skip Hash
       folder.setFileCount(folderData.extractInt(4));
       folder.dataPos = folderData.extractInt(4);
       posAtFolder(folder);
       folder.name = in.extractString(0, in.read() - 1) + "\\";
       folder.name = folder.name.toUpperCase();
       in.skip(1);
       folders.put(folder.name, folder);
       if (SPGlobal.debugBSAimport && SPGlobal.logging()) {
         SPGlobal.logSpecial(LogTypes.BSA, header, "Loaded folder: " + folder.name);
       }
       for (int j = 0; j < folder.fileCount; j++) {
         BSAFileRef f = new BSAFileRef();
         f.size = in.extractInt(8, 3); // Skip Hash
         LFlags sizeFlag = new LFlags(in.extract(1));
         f.flippedCompression = sizeFlag.get(6);
         f.dataOffset = in.extractLong(0, 4);
         fileName = fileNames.extractString();
         folder.files.put(fileName.toUpperCase(), f);
         if (SPGlobal.logging()) {
           SPGlobal.logSpecial(
               LogTypes.BSA,
               header,
               "  "
                   + fileName
                   + ", size: "
                   + Ln.prettyPrintHex(f.size)
                   + ", offset: "
                   + Ln.prettyPrintHex(f.dataOffset));
           fileCounter++;
         }
       }
     }
     if (SPGlobal.logging()) {
       if (SPGlobal.debugBSAimport) {
         SPGlobal.logSpecial(LogTypes.BSA, header, "Loaded " + fileCounter + " files.");
       }
       SPGlobal.logSpecial(LogTypes.BSA, header, "Loaded BSA: " + getFilePath());
     }
   } catch (Exception e) {
     SPGlobal.logException(e);
     SPGlobal.logError("BSA", "Skipped BSA " + this);
     bad = true;
   }
 }