com.github.dabasan.jxm.properties.xops.EXEManipulator Maven / Gradle / Ivy
package com.github.dabasan.jxm.properties.xops;
import com.github.dabasan.jxm.properties.character.Character;
import com.github.dabasan.jxm.properties.character.xops.BINCharacterManipulator;
import com.github.dabasan.jxm.properties.weapon.Weapon;
import com.github.dabasan.jxm.properties.weapon.xops.BINWeaponManipulator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
/**
* EXE manipulator
*
* @author maeda6uiui
*/
public class EXEManipulator {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private XOPSVersion srcXOPSVersion;
private BINWeaponManipulator weaponManipulator;
private BINCharacterManipulator characterManipulator;
/**
* Creates an EXE manipulator.
*/
public EXEManipulator() {
weaponManipulator = new BINWeaponManipulator();
characterManipulator = new BINCharacterManipulator();
}
private void constructorBase(InputStream is) throws IOException {
byte[] bin = is.readAllBytes();
XOPSVersion version = XOPSFunctions.getXOPSVersion(bin);
int weaponDataStartPos = this.getWeaponDataStartPos(version);
int weaponNameStartPos = this.getWeaponNameStartPos(version);
int characterDataStartPos = this.getCharacterDataStartPos(version);
srcXOPSVersion = version;
weaponManipulator = new BINWeaponManipulator(bin, weaponDataStartPos, weaponNameStartPos);
characterManipulator = new BINCharacterManipulator(bin, characterDataStartPos);
}
/**
* Creates an EXE manipulator and loads an EXE.
*
* @param is input stream load an EXE from
* @throws IOException if it fails to load
*/
public EXEManipulator(InputStream is) throws IOException {
this.constructorBase(is);
}
/**
* Creates an EXE manipulator and loads an EXE.
*
* @param file file to load an EXE from
* @throws IOException if it fails to load
*/
public EXEManipulator(File file) throws IOException {
try (var bis = new BufferedInputStream(new FileInputStream(file))) {
this.constructorBase(bis);
}
}
/**
* Creates an EXE manipulator and loads an EXE.
*
* @param filepath filepath to load an EXE from
* @throws IOException if it fails to load
*/
public EXEManipulator(String filepath) throws IOException {
try (var bis = new BufferedInputStream(new FileInputStream(filepath))) {
this.constructorBase(bis);
}
}
private int getWeaponDataStartPos(XOPSVersion version) {
int weaponDataStartPos;
switch (version) {
case XOPS096:
weaponDataStartPos = 0x0005D32C;
break;
case XOPS096T:
weaponDataStartPos = 0x0005D32C;
break;
case XOPS097FT:
weaponDataStartPos = 0x0005E32C;
break;
case XOPS0975T:
weaponDataStartPos = 0x00077FB0;
break;
case XOPSOLT18F2:
weaponDataStartPos = 0x0006640C;
break;
case XOPSOLT19F2:
weaponDataStartPos = 0x000777E8;
break;
default:
weaponDataStartPos = 0x00000000;
break;
}
return weaponDataStartPos;
}
private int getWeaponNameStartPos(XOPSVersion version) {
int weaponNameStartPos;
switch (version) {
case XOPS096:
weaponNameStartPos = 0x000661E4;
break;
case XOPS096T:
weaponNameStartPos = 0x000661E4;
break;
case XOPS097FT:
weaponNameStartPos = 0x000671E4;
break;
case XOPS0975T:
weaponNameStartPos = 0x00079140;
break;
case XOPSOLT18F2:
weaponNameStartPos = 0x0006EF84;
break;
case XOPSOLT19F2:
weaponNameStartPos = 0x00077370;
break;
default:
weaponNameStartPos = 0x00000000;
break;
}
return weaponNameStartPos;
}
private int getCharacterDataStartPos(XOPSVersion version) {
int characterDataStartPos;
switch (version) {
case XOPS096:
characterDataStartPos = 0x0005D864;
break;
case XOPS096T:
characterDataStartPos = 0x0005D864;
break;
case XOPS097FT:
characterDataStartPos = 0x0005E864;
break;
case XOPS0975T:
characterDataStartPos = 0x000784E8;
break;
case XOPSOLT18F2:
characterDataStartPos = 0x00066944;
break;
case XOPSOLT19F2:
characterDataStartPos = 0x00077D20;
break;
default:
characterDataStartPos = 0x00000000;
break;
}
return characterDataStartPos;
}
/**
* Returns weapon data.
*
* @return array containing weapon data
*/
public Weapon[] getWeapons() {
return weaponManipulator.getWeapons();
}
/**
* Sets weapon data.
*
* @param weapons array containing weapon data
*/
public void setWeapons(Weapon[] weapons) {
weaponManipulator.setWeapons(weapons);
}
/**
* Returns character data.
*
* @return array containing character data
*/
public Character[] getCharacters() {
return characterManipulator.getCharacters();
}
/**
* Sets character data.
*
* @param characters array containing character data
*/
public void setCharacters(Character[] characters) {
characterManipulator.setCharacters(characters);
}
/**
* Returns the version of XOPS passed to the constructor.
*
* @return version of XOPS
*/
public XOPSVersion getSrcXOPSVersion() {
return srcXOPSVersion;
}
// Base method for write().
// Pass a non-null value to fileBackup to make a backup file before
// overwriting the file.
private void writeBase(File file, File fileBackup) throws IOException {
byte[] bin;
try (var bis = new BufferedInputStream(new FileInputStream(file))) {
bin = bis.readAllBytes();
}
// Make a backup file
if (fileBackup != null) {
try (var bosBackup = new BufferedOutputStream(new FileOutputStream(fileBackup))) {
bosBackup.write(bin);
}
}
XOPSVersion version = XOPSFunctions.getXOPSVersion(bin);
int weaponDataStartPos = this.getWeaponDataStartPos(version);
int weaponNameStartPos = this.getWeaponNameStartPos(version);
int characterDataStartPos = this.getCharacterDataStartPos(version);
weaponManipulator.write(bin, weaponDataStartPos, weaponNameStartPos);
characterManipulator.write(bin, characterDataStartPos);
// Overwrite an EXE file of XOPS
try (var bos = new BufferedOutputStream(new FileOutputStream(file))) {
bos.write(bin);
}
}
/**
* Writes data to an existing EXE. Pass a non-null value to the second
* argument if you want to make a backup file before overwriting the
* existing EXE.
*
* @param file file to write the data to
* @param fileBackup file for backup
* @throws IOException if it fails to write
*/
public void write(File file, File fileBackup) throws IOException {
if (file.exists() == false) {
logger.error("The file specified does not exist. filename={}", file.getName());
return;
}
this.writeBase(file, fileBackup);
}
/**
* Writes data to an existing EXE. Pass a non-null value to the second
* argument if you want to make a backup file before overwriting the
* existing EXE.
*
* @param filepath filepath to write the data to
* @param filepathBackup filepath for backup
* @throws IOException if it fails to write
*/
public void write(String filepath, String filepathBackup) throws IOException {
var file = new File(filepath);
if (file.exists() == false) {
logger.error("The file specified does not exist. filename={}", file.getName());
return;
}
File fileBackup = null;
if (filepathBackup != null) {
fileBackup = new File(filepathBackup);
}
this.writeBase(file, fileBackup);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy