MAZter[iddqd] -= WebMaster =- Doom Rate: 1.4 Posts quality: +148
Отправлено: 24.11.22 03:03:01 Приветствую!
Есть ли здесь программисты на Java? Надобно вытащить ресурсы из SimCity 2000 и запихнуть обратно в урезанном виде, чтобы файл занимал меньше места. Итоговая цель, не уверен, что реализуемая - заставить игру работать с 2 мегабайтами оперативки. К примеру на Sega Saturn с 2 мегабайтами оперативки игра работает, если вырезать музыку и звуки, авось запустится? Согласен квест так себе, есть желающие взяться?
Сам скрипт есть по ссылке ниже, но у меня не вышло разобраться, только с node.js скомпилировало какие-то два файла с классами, а дальше непонятно что с этим делать.
https://blog.krusher.net/en/2017/12/taking-sim-city-2000-into-pieces/
Скрытый текст:
package sce2000;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.io.FileUtils;
public class Sce2000 {
public static final String SC2000DAT = "sc2000.dat";
public static final int NUMFILES = 399;
public static class Filestrut implements Serializable {
private static final long serialVersionUID = 1L;
public String filename;
public int offset;
public int targetOffset;
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
if (args.length == 0) {
info();
} else if ("x".equals(args[0])) {
extract();
} else if ("c".equals(args[0])) {
create();
} else {
info();
}
}
public static void info() {
System.out.println("Usage: x to eXtract or c to Create (after eXtract) + sc2000.dat file");
}
public static void create() throws IOException, ClassNotFoundException {
File sc2000dat = new File(SC2000DAT);
File metafile = new File(SC2000DAT + "!/meta");
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(metafile));
List<Filestrut> files = (List<Filestrut>) ois.readObject();
List<Byte> targetFile = new ArrayList<Byte>();
for (Filestrut file : files) {
byte[] fileNameBytes = file.filename.getBytes(StandardCharsets.US_ASCII);
for (Byte myByte : fileNameBytes) {
targetFile.add(myByte);
}
for (int i = 0; i < 16 - fileNameBytes.length; i++) {
targetFile.add((byte) 0);
}
//sourceFile.length();
}
int i = 0;
for (Filestrut file : files) {
byte[] binary = Files.readAllBytes(Paths.get(SC2000DAT + "!/" + file.filename));
int fileOffset = targetFile.size();
for (Byte myByte : binary) {
targetFile.add(myByte);
}
int filePointer = 12 + (16 * i);
byte[] offsetBytes = fromInt(fileOffset);
targetFile.set(filePointer, offsetBytes[0]);
targetFile.set(filePointer + 1, offsetBytes[1]);
targetFile.set(filePointer + 2, offsetBytes[2]);
targetFile.set(filePointer + 3, offsetBytes[3]);
i++;
}
byte[] binaryFile = new byte[targetFile.size()];
for (i = 0; i < targetFile.size(); i++) {
binaryFile[i] = targetFile.get(i);
}
FileUtils.writeByteArrayToFile(sc2000dat, binaryFile);
System.out.println();
}
public static void extract() throws IOException {
Path sc2000dat = Paths.get(SC2000DAT);
byte[] data = Files.readAllBytes(sc2000dat);
int vector = 0;
List<Filestrut> files = new ArrayList<Filestrut>();
for (int i = 0; i < NUMFILES; i++) {
Filestrut currfile = new Filestrut();
currfile.filename = convertFilename(Arrays.copyOfRange(data, vector, vector + 12));
vector += 12;
currfile.offset = fromByteArray(Arrays.copyOfRange(data, vector, vector + 4));
vector += 4;
System.out.println("Found file " + currfile.filename + " at " + currfile.offset);
files.add(currfile);
}
File dir = new File(SC2000DAT + "!");
if (dir.exists()) {
FileUtils.deleteDirectory(dir);
}
dir.mkdir();
Iterator<Filestrut> fileIt = files.iterator();
Filestrut file = fileIt.next();
Filestrut fileNext = null;
boolean stop = false;
while (!stop) {
File extracted = new File(SC2000DAT + "!/" + file.filename);
int init = file.offset;
int end = -1;
if (fileIt.hasNext()) {
fileNext = fileIt.next();
end = fileNext.offset;
} else {
end = data.length;
stop = true;
}
System.out.println("Writing: " + extracted.getAbsolutePath());
FileUtils.writeByteArrayToFile(extracted, Arrays.copyOfRange(data, init, end));
file = fileNext;
}
File metafile = new File(SC2000DAT + "!/meta");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(metafile));
oos.writeObject(files);
oos.close();
System.out.println("OK!");
}
public static byte[] fromInt(int number) {
byte[] bytes = ByteBuffer.allocate(4).putInt(number).array();
swapEndianess(bytes);
return bytes;
}
public static void swapEndianess(byte [] bytes) {
byte temp1 = bytes[0];
byte temp2 = bytes[1];
bytes[0] = bytes[3];
bytes[1] = bytes[2];
bytes[2] = temp2;
bytes[3] = temp1;
}
public static int fromByteArray(byte[] bytes) {
// Change endianness
swapEndianess(bytes);
return ByteBuffer.wrap(bytes).getInt();
}
public static String convertFilename(byte[] data) {
StringBuilder sb = new StringBuilder(data.length);
for (int i = 0; i < data.length; ++ i) {
if (data[i] < 0) {
throw new IllegalArgumentException();
}
if (data[i] == 0) {
break;
}
sb.append((char) data[i]);
}
return sb.toString();
}
}
sc2000.dat
Добавлено спустя 1 час 23 минуты 40 секунд:
update:
нашел распаковщик срипт для QuickBMS, осталось найти запаковщик
https://gist.github.com/ccawley2011/d601d7873b14fa6f6121494a843a5141