SCT got me looking at the issue with Adding new shipname groups. I have been attempting to edit the file below from UE source code to read old and new file format correctly.
Here is what I think I have figured out. I will use line numbers for locations, you would need to add code to an editor to see line numbers.
line 48 "private final int StopSign = 996;"
is the stop sign for the index, this is set to new index max
line 56 "in.skip(248); // 62 * 4"
this is simple command to move in 248 bytes
this is where I need an "if" statement.
at this point I need code to read next 2 bytes.
if "FC 00" continue,
if not "in.skip(744);"
read next 2 bytes
if "E4 03" continue
I hope I was able to explain what I think I need. writing of file looks to work properly.
Code: Select all
/*
Ultimate Editor for Birth Of The Federation 1.02
Copyright (C) 2005-2007 Alan Podlesek
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
File: Shipname.java
Written by: Alan Podlesek <seqdcer@yahoo.com>
Last modified: 6.9.2007
*/
package ue.edit.res.stbof.bin;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Vector;
import ue.Language;
import ue.edit.InternalFile;
import ue.exception.CorruptedFile;
import ue.exception.InvalidArgumentsException;
import ue.util.Tools;
/**
* This class is a representation of shipname.bin
* which contains generic ship names devided between groups
*/
public class Shipname extends InternalFile
{
private final int StopSign = 996;
private ArrayList<ArrayList<String>> GROUP;
/**@param in the InputStream to read the file from*/
public Shipname(InputStream in) throws IOException, CorruptedFile
{
// skip group info
// number of entries in each group
in.skip(248); // 62 * 4
// read stop sign
in.skip(4);
// go thru all entries
// reading the index first, then shipname
// shipnames might be placed randomly, index must be checked
// when saved, indexes will go in an incrementing order
GROUP = new ArrayList<ArrayList<String>>();
byte[] b = new byte[2];
byte[] name = new byte[40];
String strName;
int index;
for (int i = 0; in.available() >= 44; i++)
{
// index
in.read(b);
index = Tools.toShort(b, true);
index = index & 0xFFFF;
if (index >= 248)
{
throw new CorruptedFile("Number of shipname groups exceeds 248.");
}
if (index < 0)
{
index = 0;
}
while (GROUP.size() <= index)
{
GROUP.add(new ArrayList<String>());
}
// ffff
in.skip(2);
// ship name
in.read(name);
strName = Tools.toASCII(name, 0, 40);
GROUP.get(index).add(strName);
}
}
/**used to save changes.
@param out the OutputStream to write the file to*/
@Override
public void save(OutputStream out) throws Exception
{
byte[] b;
int size;
ArrayList<String> arr;
// groups
size = GROUP.size();
if (size <= 62)
{
for (int i = 0; i < size; i++)
{
arr = GROUP.get(i);
b = Tools.toByte(arr.size(), true);
out.write(b);
}
for (int i = size; i < 62; i++)
{
b = Tools.toByte(0, true);
out.write(b);
}
}
else
{
for (int i = 0; i < size; i++)
{
arr = GROUP.get(i);
b = Tools.toByte(arr.size(), true);
out.write(b);
}
for (int i = size; i < 248; i++)
{
b = Tools.toByte(0, true);
out.write(b);
}
}
// stop sign
b = Tools.toByte(StopSign, true);
out.write(b);
// entries
for (short i = 0; i < GROUP.size(); i++)
{
arr = GROUP.get(i);
size = arr.size();
for (int j = 0; j < size; j++)
{
//index
out.write(Tools.toByte(i, true));
//separator
out.write(Tools.toByte((short)-1, true));
//name
String name = arr.get(j);
b = Tools.toByte(name, 40, 39);
out.write(b);
}
}
}
/**Used to get the uncompressed size of the file.**/
@Override
public long getSize()
{
long size = 4 * 63;
size += entries() * 44;
return size;
}
/**Used to get the number of ship names in file.
@return number of ship names*/
public long entries()
{
long ent = 0;
for (int i = 0; i < GROUP.size(); i++)
{
ent += GROUP.get(i).size();
}
return ent;
}
@Override
public Vector<String> check()
{
Vector<String> response = new Vector<String>();
String msg;
ArrayList<String> arr;
for (int i = 0; i < GROUP.size(); i++)
{
arr = GROUP.get(i);
if (arr.size() == 0)
{
msg = Language.getString("Shipname.0"); //$NON-NLS-1$
msg = msg.replace("%1", getName()); //$NON-NLS-1$
msg = msg.replace("%2", Integer.toString(i)); //$NON-NLS-1$
response.add(msg);
}
}
return response;
}
/**Adds a shipname to the specified group
@param group the group to add the name to
@param name the ship name to be added to the group
@throws InvalidArgumentsException if incorrect parameters are given*/
public void add(int group, String name) throws InvalidArgumentsException{
try
{
ArrayList<String> arr = GROUP.get(group);
if (arr.contains(name))
{
return;
}
if (name.length() > 39)
{
name = name.substring(0, 38);
}
arr.add(name);
Collections.sort(arr);
this.markChanged();
}
catch (Exception e)
{
String msg = Language.getString("Shipname.2"); //$NON-NLS-1$
msg = msg.replace("%1", getName()); //$NON-NLS-1$
msg = msg.replace("%2", Integer.toString(group)); //$NON-NLS-1$
throw new InvalidArgumentsException(msg);
}
}
/**Removes a shipname from the specified group
@param group the group from which the name should be removed
@param name the ship name to be removed
@throws InvalidArgumentsException if incorrect parameters are given*/
public void remove(int group, String name) throws InvalidArgumentsException{
try
{
ArrayList<String> arr = GROUP.get(group);
arr.remove(name);
Collections.sort(arr);
this.markChanged();
}
catch (Exception e)
{
String msg = Language.getString("Shipname.2"); //$NON-NLS-1$
msg = msg.replace("%1", getName()); //$NON-NLS-1$
msg = msg.replace("%2", Integer.toString(group)); //$NON-NLS-1$
throw new InvalidArgumentsException(msg);
}
}
/**Sets a shipname in the specified group.
@param group the group to be edited
@param oldName the old ship name to be changed
@param name the name to replace the old one
@return true if the name was changed, else false
@throws InvalidArgumentsException if incorrect parameters are given*/
public void set(int group, String oldName, String name) throws InvalidArgumentsException
{
try
{
if (name.length() > 39)
{
name = name.substring(0, 38);
}
ArrayList<String> arr = GROUP.get(group);
int i = arr.indexOf(oldName);
if (i < 0)
{
return;
}
arr.set(i, name);
Collections.sort(arr);
this.markChanged();
}
catch (Exception e)
{
String msg = Language.getString("Shipname.2"); //$NON-NLS-1$
msg = msg.replace("%1", getName()); //$NON-NLS-1$
msg = msg.replace("%2", Integer.toString(group)); //$NON-NLS-1$
throw new InvalidArgumentsException(msg);
}
}
/**Return a list of ship names.
@param group the group from which the shipname are to be returned
@return an array of Strings containing ship names from the specified group
@throws InvalidArgumentsException if incorrect parameters are given*/
public String[] getEntries(int group) throws InvalidArgumentsException
{
try
{
ArrayList<String> arr = GROUP.get(group);
Collections.sort(arr);
return arr.toArray(new String[0]);
}
catch (Exception e)
{
String msg = Language.getString("Shipname.2"); //$NON-NLS-1$
msg = msg.replace("%1", getName()); //$NON-NLS-1$
msg = msg.replace("%2", Integer.toString(group)); //$NON-NLS-1$
throw new InvalidArgumentsException(msg);
}
}
public int getNumberOfGroups()
{
return GROUP.size();
}
public void addGroup() throws Exception
{
if (GROUP.size() >= 248)
{
throw new Exception("Maximum number of name groups reached.");
}
GROUP.add(new ArrayList<String>());
this.markChanged();
}
public void removeGroup(int index)
{
GROUP.remove(index);
this.markChanged();
}
}