Advertisement
radionactive

Halo Map Patcher Reference (Java)

Oct 27th, 2012
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 6.82 KB | None | 0 0
  1. package me.Zero2.filepatcher;
  2.  
  3. import java.awt.Font;
  4. import java.io.File;
  5. import java.io.RandomAccessFile;
  6.  
  7. import javax.swing.JButton;
  8. import javax.swing.JFileChooser;
  9. import javax.swing.JFrame;
  10.  
  11.  
  12. public class Main {
  13.     public static void patchFile(File file,boolean guiSuccess) { //the works
  14.         try {
  15.             System.out.print("Patching file \"" + file.getPath() + "\"...");
  16.             long indexOffset = readUnsignedInt32(0x10,file); //Let's first find the index offset. You'll find this at offset 0x10 from ALL Halo full maps.
  17.             long magic = readUnsignedInt32(indexOffset,file) - indexOffset - 0x28; //We go to the index offset, subtract 0x28 to get Magic, and then subtract Index Offset to get the Map Magic which is what we need.
  18.             long numberOfTags = readUnsignedInt32(indexOffset + 0xC,file); //Now we need to know how many tags there are. I don't know WHY it's a long since no unmodded map has that many tags.
  19.             long tagArrayOffset = indexOffset + 0x28; //Now we need to get to the tag array offset. It's 0x28 from the index offset.
  20.             boolean name = false;
  21.             boolean description = false;
  22.             for(int i=0;i<numberOfTags;i++) { //We need to analyze every tag's name, until we get to the tag we want.
  23.                 long currentLocation = 0x20*i + tagArrayOffset;
  24.                 long nameOffset = readUnsignedInt32(currentLocation + 0x10,file) - magic;
  25.                 if(read4ByteUTF8(currentLocation,file).equals("rtsu")) { //It's the correct type, but is it the correct name?
  26.                     if(readUTF8(nameOffset,file).equals("ui\\shell\\main_menu\\mp_map_list")) { //we've found the tag we want. Yay!
  27.                         long namesOffset = readUnsignedInt32(currentLocation + 0x14,file) - magic + 0x1B0;
  28.                         long boardingActionOffset = namesOffset + 0xB4;
  29.                         changeUTF16String(boardingActionOffset,file,"Barrier",15); //changeUTF16String(long offset,File file,String changeTo,int maximumLength);
  30.                         long chironOffset = boardingActionOffset + 0x48;
  31.                         changeUTF16String(chironOffset,file,"The Shaft",11);
  32.                         long gephyOffset = chironOffset + 0xA4;
  33.                         changeUTF16String(gephyOffset,file,"Modded",13);
  34.                         long infinityOffset = gephyOffset - 0x2C;
  35.                         changeUTF16String(infinityOffset,file,"Crossing",8);
  36.                         name = true;
  37.                     }
  38.                     if(readUTF8(nameOffset,file).equals("ui\\shell\\main_menu\\multiplayer_type_select\\mp_map_select\\map_data")) { //we've found the tag we want. Yay!
  39.                         long descriptionOffset = readUnsignedInt32(currentLocation + 0x14,file) - magic + 0x19C;
  40.                         long boardingActionOffset = descriptionOffset + 0x2BC;
  41.                         changeUTF16String(boardingActionOffset,file,"Trapped!\n\n6-12 players",0x24);
  42.                         long chironOffset = boardingActionOffset + 0x120;
  43.                         changeUTF16String(chironOffset,file,"Your deepest grave\n\n8-16 players",0x2E);
  44.                         long infinityOffset = chironOffset + 0x258;
  45.                         changeUTF16String(infinityOffset,file,"In space, no one\ncan hear you scream\n\n6-12 players",0x48);
  46.                         long gephyOffset = infinityOffset + 0x10C;
  47.                         changeUTF16String(gephyOffset,file,"",0x32);
  48.                         description = true;
  49.                     }
  50.                 }
  51.             }
  52.             if(name && description) {
  53.                 System.out.println("Done!");
  54.                 if(guiSuccess) notification("Done!");
  55.             }
  56.             if(!name && !description) {
  57.                 System.out.println("Name and description tag was not found! Is this map protected?");
  58.                 if(guiSuccess) notification("The name and description tags could not be found! Protected?");
  59.             }
  60.             if(!name) {
  61.                 System.out.println("Names tag not found!");
  62.                 if(guiSuccess) notification("The maps' names tag wasn't found.");
  63.             }
  64.             if(!description) {
  65.                 System.out.println("Descriptions tag was not found!");
  66.                 if(guiSuccess) notification("The maps' descriptions tag wasn't found.");
  67.             }
  68.         }
  69.         catch(Exception e) {
  70.             e.printStackTrace();
  71.             System.out.println("Error!");
  72.             if(guiSuccess) notification("The map could not be opened!");
  73.         }
  74.        
  75.     }
  76.     public static void changeUTF16String(long offset,File file,String text, int length) throws Exception { //change string, null remaining data based on Length.
  77.         RandomAccessFile raf = new RandomAccessFile(file, "rw");
  78.         int reduce = 0;
  79.         int i=0;
  80.         for(; i<length; i++) {
  81.             raf.seek(offset + i * 2);
  82.             if(i+reduce<text.length()) {
  83.                 if(text.toCharArray()[i + reduce] == (char)0xA) {
  84.                     raf.writeByte(0x0D);
  85.                     i++;
  86.                     if(i < length) {
  87.                         raf.seek(offset + i*2);
  88.                         raf.writeByte(0x0A);
  89.                     }
  90.                     reduce--;
  91.                 }
  92.                 else raf.writeByte(text.toCharArray()[i + reduce]);
  93.             } else {
  94.                 raf.seek(offset + i * 2);
  95.                 raf.writeByte(0);
  96.             }
  97.         }
  98.         raf.close();
  99.     }
  100.     public static long readUnsignedInt32(long offset, File file) throws Exception {
  101.         RandomAccessFile raf = new RandomAccessFile(file, "r"); //loads the file for reading
  102.         int[] b = new int[4];
  103.         for(int i=0;i<4;i++) {
  104.             raf.seek(offset+i);
  105.             b[i] = raf.readByte();
  106.             if(b[i] < 0) b[i] += Byte.MAX_VALUE*2+2;
  107.         }
  108.         raf.close(); //closes
  109.         long value = b[0]; //convert to big endian
  110.         value += b[1]*256;
  111.         value += b[2]*256*256;
  112.         value += b[3]*256*256*((long)256);
  113.         return value;
  114.     }
  115.     public static String readUTF8(long offset, File file) throws Exception { //reads a UTF-8 string until a terminating 0
  116.         RandomAccessFile raf = new RandomAccessFile(file, "r");
  117.         String returnValue = "";
  118.         boolean terminate = false;
  119.         for(int i=0;!terminate;i++) {
  120.             raf.seek(offset+i);
  121.             returnValue += (char)raf.readByte();
  122.             if(raf.readByte() == 0) terminate = true;
  123.         }
  124.         raf.close();
  125.         return returnValue;
  126.     }
  127.     public static String read4ByteUTF8(long offset, File file) throws Exception { //reads only 4 bytes for tag class
  128.         RandomAccessFile raf = new RandomAccessFile(file, "r"); //read only
  129.         String returnValue = "";
  130.         for(int i=0;i<4;i++) {
  131.             raf.seek(offset+i);
  132.             returnValue += (char)raf.readByte();
  133.         }
  134.         raf.close();
  135.         return returnValue;
  136.     }
  137.    
  138.    
  139.     public static void main(String[] args) {
  140.         if(args.length != 0) {
  141.             for(String string : args) patchFile(new File(string),false);
  142.             return;
  143.         }
  144.         JFileChooser dialogue = new JFileChooser();
  145.         dialogue.showOpenDialog(null);
  146.         try {
  147.             if(dialogue.getSelectedFile() == null) return;
  148.             patchFile(dialogue.getSelectedFile(),true);
  149.         } catch (Exception e) {
  150.             System.out.println("Failed.");
  151.         }
  152.     }
  153.     public static void notification(String message) {
  154.         final JFrame frame2 = new JFrame();
  155.         frame2.setBounds(100, 100, 250, 100);
  156.         frame2.setLocationRelativeTo(null);
  157.         frame2.setTitle("Result");
  158.         JButton label2 = new JButton(message);
  159.         label2.setFont(Font.getFont(Font.SANS_SERIF));
  160.         label2.addActionListener(new java.awt.event.ActionListener() {  
  161.             public void actionPerformed(java.awt.event.ActionEvent e) {  
  162.                 frame2.dispose();  
  163.             }  
  164.         });
  165.         frame2.add(label2);
  166.         frame2.setVisible(true);
  167.     }
  168. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement