Implemented Maskable and Switchable 2D Tables

This commit is contained in:
Robin K 2020-03-29 11:58:07 +02:00
parent 8338746442
commit c6ea31c986
8 changed files with 606 additions and 66 deletions

View File

@ -1,6 +1,14 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2017 RomRaider.com
<<<<<<< HEAD
<<<<<<< HEAD
* Copyright (C) 2006-2020 RomRaider.com
=======
* Copyright (C) 2006-2019 RomRaider.com
>>>>>>> Added XOR for single byte checksums. Added possibility of multiple checksums in file
=======
* Copyright (C) 2006-2020 RomRaider.com
>>>>>>> Updated copyright. Switched to checkboxes for presets. Allowed multiple selection. Fixed saving bug. CChanged table name to 2DMaskedSwitchable
*
* 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
@ -34,6 +42,7 @@ import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
@ -63,7 +72,7 @@ public class Rom extends DefaultMutableTreeNode implements Serializable {
private final Vector<TableTreeNode> tableNodes = new Vector<TableTreeNode>();
private byte[] binData;
private boolean isAbstract = false;
private ChecksumManager checksumManager;
private LinkedList<ChecksumManager> checksumManagers = new LinkedList<ChecksumManager>();
public Rom() {
tableNodes.clear();
@ -186,7 +195,8 @@ public class Rom extends DefaultMutableTreeNode implements Serializable {
Table table = tableNodes.get(i).getTable();
try {
// if storageaddress has not been set (or is set to 0) omit table
if (table.getStorageAddress() != 0) {
//Why can the address not be zero? - Changed
if (table.getStorageAddress() >= 0) {
try {
table.populateTable(binData, this.getRomID().getRamOffset());
TableUpdateHandler.getInstance().registerTable(table);
@ -422,34 +432,42 @@ public class Rom extends DefaultMutableTreeNode implements Serializable {
return (DefaultMutableTreeNode) super.getLastChild();
}
public void setChecksumManager(ChecksumManager checksumManager) {
this.checksumManager = checksumManager;
public void addChecksumManager(ChecksumManager checksumManager) {
this.checksumManagers.add(checksumManager);
}
public ChecksumManager getChecksumType() {
return checksumManager;
public ChecksumManager getChecksumType(int index) {
return checksumManagers.get(index);
}
public void validateChecksum() {
if (checksumManager != null) {
if (!checksumManagers.isEmpty()) {
final String message = String.format(
"Checksum is invalid.%n" +
"At least one Checksum is invalid.%n" +
"The ROM image may be corrupt or it has been " +
"hex edited manually.%n" +
"The checksum can be corrected when the ROM " +
"is saved if your trust it is not corrupt.");
if (!checksumManager.validate(binData)) {
showMessageDialog(null,
message,
"ERROR - Checksum Failed",
WARNING_MESSAGE);
boolean valid = true;
for(ChecksumManager cm: checksumManagers) {
if (!cm.validate(binData)) valid = false;
}
if(!valid)
showMessageDialog(null,
message,
"ERROR - At least one Checksum Failed",
WARNING_MESSAGE);
}
}
public void updateChecksum() {
if (checksumManager != null) {
checksumManager.update(binData);
if (!checksumManagers.isEmpty()) {
for(ChecksumManager cm: checksumManagers) {
cm.update(binData);
}
}
}
}

View File

@ -1,6 +1,6 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2018 RomRaider.com
* Copyright (C) 2006-2020 RomRaider.com
*
* 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
@ -778,7 +778,7 @@ public abstract class Table extends JPanel implements Serializable {
return JEPUtil.evaluate(getCurrentScale().getExpression(), getMinAllowedBin());
}
private void calcValueRange() {
protected void calcValueRange() {
if (getStorageType() != Settings.STORAGE_TYPE_FLOAT) {
if (isSignedData()) {
switch (getStorageType()) {
@ -820,34 +820,36 @@ public abstract class Table extends JPanel implements Serializable {
}
public void calcCellRanges() {
double binMax = data[0].getBinValue();
double binMin = data[0].getBinValue();
if(data.length > 0) {
double binMax = data[0].getBinValue();
double binMin = data[0].getBinValue();
double compareMax = data[0].getCompareValue();
double compareMin = data[0].getCompareValue();
double compareMax = data[0].getCompareValue();
double compareMin = data[0].getCompareValue();
for(DataCell cell : data) {
// Calc bin
if(binMax < cell.getBinValue()) {
binMax = cell.getBinValue();
}
if(binMin > cell.getBinValue()) {
binMin = cell.getBinValue();
}
for(DataCell cell : data) {
// Calc bin
if(binMax < cell.getBinValue()) {
binMax = cell.getBinValue();
}
if(binMin > cell.getBinValue()) {
binMin = cell.getBinValue();
}
// Calc compare
double compareValue = cell.getCompareValue();
if(compareMax < compareValue) {
compareMax = compareValue;
}
if(compareMin > compareValue) {
compareMin = compareValue;
}
}
setMaxBin(binMax);
setMinBin(binMin);
setMaxCompare(compareMax);
setMinCompare(compareMin);
// Calc compare
double compareValue = cell.getCompareValue();
if(compareMax < compareValue) {
compareMax = compareValue;
}
if(compareMin > compareValue) {
compareMin = compareValue;
}
}
setMaxBin(binMax);
setMinBin(binMin);
setMaxCompare(compareMax);
setMinCompare(compareMin);
}
}
public double getMaxBin() {
@ -1521,7 +1523,8 @@ public abstract class Table extends JPanel implements Serializable {
TABLE_3D(3),
X_AXIS(4),
Y_AXIS(5),
SWITCH(6);
SWITCH(6),
TABLE_2D_MASKED_SWITCHABLE(7);
private final int marshallingCode;
@ -1534,6 +1537,7 @@ public abstract class Table extends JPanel implements Serializable {
case TABLE_1D:
return 1;
case TABLE_2D:
case TABLE_2D_MASKED_SWITCHABLE:
return 2;
case TABLE_3D:
return 3;

View File

@ -1,6 +1,6 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2018 RomRaider.com
* Copyright (C) 2006-2020 RomRaider.com
*
* 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
@ -63,6 +63,14 @@ public class Table2D extends Table {
return axis;
}
public JLabel getAxisLabel() {
return axisLabel;
}
public void setAxisLabel(JLabel label) {
axisLabel = label;
}
public void setAxis(Table1D axis) {
this.axis = axis;
axis.setAxisParent(this);

View File

@ -0,0 +1,355 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2020 RomRaider.com
*
* 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.
*/
package com.romraider.maps;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import com.romraider.Settings;
import com.romraider.Settings.Endian;
import com.romraider.util.ByteUtil;
import com.romraider.xml.RomAttributeParser;
@SuppressWarnings("serial")
public class Table2DMaskedSwitchable extends Table2D {
private int bitMask;
private LinkedList<PresetEntry> defaultEntries = new LinkedList<PresetEntry>();
private final List<PresetButton> buttonGroup = new ArrayList<PresetButton>();
//Struct for saving Preset values
private class PresetEntry {
String name;
LinkedList<Integer> data;
}
public Table2DMaskedSwitchable() {
super();
}
public void setBitMask(int mask) {
//Clamp mask to max size
bitMask = (int) Math.min(mask, Math.pow(2,getStorageType()*8)-1);
calcValueRange();
}
public int getBitMask() {
return bitMask;
}
public void setStringMask(String stringMask) {
int mask = parseUnsignedInt(stringMask, 16);
setBitMask(mask);
}
public void setPredefinedOption(String name, String data) {
PresetEntry entry = new PresetEntry();
entry.data = new LinkedList<Integer>();
for (String s : data.split(",")) {
Integer i = parseUnsignedInt(s, 16);
if (getStorageType() > 1 && getEndian() == Endian.LITTLE)
{
if(getStorageType() == 2) {
i = Short.reverseBytes((short)(i&0xFFFF))&0xFFFF;
}
else if(getStorageType() == 4)
i = Integer.reverseBytes(i);
}
entry.data.add(i);
}
entry.name = name;
defaultEntries.add(entry);
}
@Override
public void populateTable(byte[] input, int romRamOffset) throws ArrayIndexOutOfBoundsException, IndexOutOfBoundsException {
super.populateTable(input, romRamOffset);
// temporarily remove lock
boolean tempLock = locked;
locked = false;
// Saves the masked value in dataCell
for (int i = 0; i < getDataSize(); i++) {
// populate data cells
if (storageType == Settings.STORAGE_TYPE_FLOAT) { // float storage type
LOGGER.error("Float is not supported for Table2DMaskedSwitchable!");
return;
} else if (storageType == Settings.STORAGE_TYPE_MOVI20 || storageType == Settings.STORAGE_TYPE_MOVI20S) {
LOGGER.error("MOVI20(S) is not supported for Table2DMaskedSwitchable!");
return;
} else {
double binValue = RomAttributeParser.parseByteValueMasked(input, endian, getStorageAddress() + i * storageType - ramOffset, storageType, signed, bitMask);
data[i].setBinValue(binValue);
}
// show locked cell
if (tempLock) {
data[i].setForeground(Color.GRAY);
}
}
JLabel axisLabel = getAxisLabel();
if(getAxis().isStaticDataTable()) {
axisLabel.setText(" " + axisLabel.getText() + " ");
Font f = axisLabel.getFont();
axisLabel.setFont(f.deriveFont(f.getStyle() | Font.BOLD));
}
JPanel radioPanel = new JPanel(new GridLayout(0, 1));
// Add presets
if(defaultEntries.size() > 0) {
JLabel optionLabel = new JLabel(" Presets");
Font f = optionLabel.getFont();
optionLabel.setFont(f.deriveFont(f.getStyle() | Font.BOLD));
radioPanel.add(optionLabel);
}
//Setup button for each preset
for (PresetEntry entry : defaultEntries) {
PresetButton button = new PresetButton();
button.setText(entry.name);
button.setPresetData(entry.data);
button.addActionListener(new PresetListener());
buttonGroup.add(button);
radioPanel.add(button);
}
add(radioPanel, BorderLayout.SOUTH);
// reset locked status
locked = tempLock;
calcValueRange();
calcCellRanges();
repaint();
}
//New values, check if any presets are active
@Override
public void repaint() {
super.repaint();
if (buttonGroup != null) {
for (PresetButton button: buttonGroup) {
button.checkIfActive();
}
}
}
@Override
protected void calcValueRange() {
if (getStorageType() != Settings.STORAGE_TYPE_FLOAT) {
if (!isSignedData()) {
maxAllowedBin =(int)(Math.pow(2,ByteUtil.lengthOfMask(bitMask)) - 1);
minAllowedBin = 0.0;
}
}
}
@Override
public byte[] saveFile(byte[] binData) {
if (userLevel <= getSettings().getUserLevel() && (userLevel < 5 || getSettings().isSaveDebugTables())) {
binData = getAxis().saveFile(binData);
for (int i = 0; i < data.length; i++) {
byte[] output = null;
if (this.isStaticDataTable() && storageType > 0) {
LOGGER.warn("Static data table: " + this.getName() + ", storageType: " + storageType);
}
if (storageType != Settings.STORAGE_TYPE_FLOAT) {
if (!this.isStaticDataTable() && storageType > 0) {
// Shift left again
int tempData = (int) data[i].getBinValue() << ByteUtil.firstOneOfMask(bitMask);
output = RomAttributeParser.parseIntegerValue(tempData, endian, storageType);
}
int byteLength = storageType;
int tempBitMask = 0;
for (int z = 0; z < byteLength; z++) { // insert into file
tempBitMask = bitMask;
//Trim mask depending on byte, from left to right
tempBitMask = (tempBitMask & (0xFF << 8 * (byteLength - 1 - z))) >> 8*(byteLength - 1 - z);
// Delete old bits
binData[i * byteLength + z + getStorageAddress() - ramOffset] &= ~tempBitMask;
// Overwrite
binData[i * byteLength + z + getStorageAddress() - ramOffset] |= output[z];
}
}
}
}
return binData;
}
@Override
public TableType getType() {
return Table.TableType.TABLE_2D_MASKED_SWITCHABLE;
}
@Override
public boolean equals(Object other) {
try {
if (null == other) {
return false;
}
if (other == this) {
return true;
}
if (!(other instanceof TableBitwiseSwitch)) {
return false;
}
Table2DMaskedSwitchable otherTable = (Table2DMaskedSwitchable) other;
if ((null == this.getName() && null == otherTable.getName())
|| (this.getName().isEmpty() && otherTable.getName().isEmpty())) {
;// Skip name compare if name is null or empty.
} else if (!this.getName().equalsIgnoreCase(otherTable.getName())) {
return false;
}
if (this.getDataSize() != otherTable.getDataSize()) {
return false;
}
if (this.bitMask == otherTable.bitMask) {
return true;
}
return false;
} catch (Exception ex) {
// TODO: Log Exception.
return false;
}
}
/*
* Custom Button and Actionlistener
*/
class PresetButton extends JCheckBox{
private static final long serialVersionUID = 1L;
LinkedList<Integer> values; //Pointer to PresetEntry.data
public void setPresetData(LinkedList<Integer> list) {
values = list;
}
public void checkIfActive() {
// Check if the radio button is current selected
boolean found = true;
if (values != null) {
for (int i = 0; i < getDataSize(); i++) {
if(getDataSize() == values.size()) {
if ((int) data[i].getBinValue() != values.get(i)) {
found = false;
break;
}
}
}
setSelected(found);
}
}
}
class PresetListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent event) {
PresetButton button = (PresetButton)event.getSource();
if(getDataSize() == button.values.size()) {
for (int i = 0; i < getDataSize(); i++) {
data[i].setBinValue(button.values.get(i));
}
}
calcCellRanges();
repaint();
}
}
//Java 9 Method
private static int parseUnsignedInt(String s, int radix) throws NumberFormatException {
if (s == null) {
throw new NumberFormatException("null");
}
int len = s.length();
if (len > 0) {
char firstChar = s.charAt(0);
if (firstChar == '-') {
throw new
NumberFormatException(String.format("Illegal leading minus sign " +
"on unsigned string %s.", s));
} else {
if (len <= 5 ||(radix == 10 && len <= 9) ) {
return Integer.parseInt(s, radix);
} else {
long ell = Long.parseLong(s, radix);
if ((ell & 0xffffffff00000000L) == 0) {
return (int) ell;
} else {
throw new
NumberFormatException(String.format("String value %s exceeds " + "range of unsigned int.", s));
}
}
}
} else {
throw new NumberFormatException(s);
}
}
}

View File

@ -0,0 +1,95 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
<<<<<<< HEAD
<<<<<<< HEAD
* Copyright (C) 2006-2020 RomRaider.com
=======
* Copyright (C) 2006-2019 RomRaider.com
>>>>>>> Added XOR for single byte checksums. Added possibility of multiple checksums in file
=======
* Copyright (C) 2006-2020 RomRaider.com
>>>>>>> Updated copyright. Switched to checkboxes for presets. Allowed multiple selection. Fixed saving bug. CChanged table name to 2DMaskedSwitchable
*
* 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.
*/
package com.romraider.maps.checksum;
import static com.romraider.xml.RomAttributeParser.parseByteValue;
import java.util.Map;
import com.romraider.Settings;
import com.romraider.util.HexUtil;
/**
* This class implements the XOR single byte checksum validation and calculations
* for some BMW non-engine ECU ROMs.
*/
public final class ChecksumBYTEXOR implements ChecksumManager {
private static final String START = "start";
private static final String END = "end";
private static final String XORLOC = "xorloc";
private int start;
private int end;
private int xorloc;
private byte xort;
private boolean configured = false;
public ChecksumBYTEXOR() {}
@Override
public void configure(Map<String, String> vars) {
this.start = HexUtil.hexToInt(vars.get(START));
this.end = HexUtil.hexToInt(vars.get(END));
this.xorloc = HexUtil.hexToInt(vars.get(XORLOC));
this.configured = true;
}
@Override
public boolean validate(byte[] binData) {
if(!configured) {
System.err.println("Checksum Manager was not configured before it was used for validating!");
return false;
}
else {
calculate(binData);
final boolean valid = (xort == (byte)parseByteValue(binData, Settings.Endian.BIG, xorloc, 1, false));
return valid;
}
}
@Override
public void update(byte[] binData) {
if(!configured)
System.err.println("Checksum Manager was not configured before it was used for updating!");
else {
calculate(binData);
binData[xorloc] = xort;
}
}
private void calculate(byte[] binData) {
xort = 0;
int dw = 0;
for (int i = start; i < end; i += 1) {
if ((i == xorloc)) continue;
dw = (byte)parseByteValue(binData, Settings.Endian.BIG, i, 1, false);
xort ^= dw;
}
}
}

View File

@ -1,6 +1,6 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2018 RomRaider.com
* Copyright (C) 2006-2020 RomRaider.com
*
* 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
@ -119,6 +119,31 @@ public final class ByteUtil {
return val;
}
public static byte firstOneOfMask(int mask) {
byte index = (byte) 0xFF;
for(byte i=0; i < 32; i++) {
if(((mask >> i) & 1) == 1) {
index = i;
break;
}
}
return index;
}
public static byte lengthOfMask(int mask) {
byte counter = 0;
for(byte i=0; i < 32; i++) {
if(((mask >> i) & 1) == 1) {
counter++;
}
}
return counter;
}
private static int[] computeFailure(byte[] pattern) {
int[] failure = new int[pattern.length];
int j = 0;
@ -134,4 +159,5 @@ public final class ByteUtil {
return failure;
}
}

View File

@ -1,6 +1,6 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2018 RomRaider.com
* Copyright (C) 2006-2020 RomRaider.com
*
* 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
@ -48,6 +48,7 @@ import com.romraider.maps.Table1D;
import com.romraider.maps.Table2D;
import com.romraider.maps.Table3D;
import com.romraider.maps.TableBitwiseSwitch;
import com.romraider.maps.Table2DMaskedSwitchable;
import com.romraider.maps.TableSwitch;
import com.romraider.maps.checksum.ChecksumFactory;
import com.romraider.maps.checksum.ChecksumManager;
@ -111,7 +112,7 @@ public final class DOMRomUnmarshaller {
output.getRomID().setRamOffset(
output.getRomID().getFileSize()
- input.length);
output.setChecksumManager(checksumManager);
//output.addChecksumManager(checksumManager);
return output;
}
}
@ -238,6 +239,7 @@ public final class DOMRomUnmarshaller {
} else if (n.getNodeName().equalsIgnoreCase("checksum")) {
rom.getRomID().setChecksum(unmarshallAttribute(n, "type", ""));
checksumManager = unmarshallChecksum(n);
rom.addChecksumManager(checksumManager);
} else { /* unexpected element in Rom (skip) */
}
@ -415,7 +417,10 @@ public final class DOMRomUnmarshaller {
} else if (unmarshallAttribute(tableNode, "type", "unknown")
.equalsIgnoreCase("BitwiseSwitch")) {
table = new TableBitwiseSwitch();
}
else if (unmarshallAttribute(tableNode, "type", "unknown")
.equalsIgnoreCase("2DMaskedSwitchable")) {
table = new Table2DMaskedSwitchable();
} else {
throw new XMLParseException("Error loading table, "
+ tableNode.getAttributes().getNamedItem("name"));
@ -426,7 +431,6 @@ public final class DOMRomUnmarshaller {
}
}
// unmarshall table attributes
final String tn = unmarshallAttribute(tableNode, "name", table.getName());
table.setName(tn);
@ -464,6 +468,7 @@ public final class DOMRomUnmarshaller {
"storageaddress",
String.valueOf(table.getStorageAddress()))));
}
table.setDescription(unmarshallAttribute(tableNode, "description",
table.getDescription()));
table.setDataSize(unmarshallAttribute(tableNode, "sizey",
@ -477,6 +482,7 @@ public final class DOMRomUnmarshaller {
table.setLogParam(unmarshallAttribute(tableNode, "logparam",
table.getLogParam()));
if (table.getType() == Table.TableType.TABLE_3D) {
((Table3D) table).setSwapXY(unmarshallAttribute(tableNode,
"swapxy", ((Table3D) table).getSwapXY()));
@ -490,6 +496,11 @@ public final class DOMRomUnmarshaller {
((Table3D) table).getSizeY()));
}
if (table.getType() == Table.TableType.TABLE_2D_MASKED_SWITCHABLE) {
((Table2DMaskedSwitchable) table).setStringMask(
unmarshallAttribute(tableNode, "mask", "FFFFFFFF"));
}
Node n;
NodeList nodes = tableNode.getChildNodes();
@ -499,7 +510,7 @@ public final class DOMRomUnmarshaller {
if (n.getNodeType() == ELEMENT_NODE) {
if (n.getNodeName().equalsIgnoreCase("table")) {
if (table.getType() == Table.TableType.TABLE_2D) { // if table is 2D,
if (table.getType() == Table.TableType.TABLE_2D || table.getType() == Table.TableType.TABLE_2D_MASKED_SWITCHABLE) { // if table is 2D,
// parse axis
if (RomAttributeParser
@ -580,17 +591,17 @@ public final class DOMRomUnmarshaller {
unmarshallAttribute(n, "name", ""),
unmarshallAttribute(n, "data", "0.0"));
} else if (n.getNodeName().equalsIgnoreCase("bit")) {
((TableBitwiseSwitch) table).setValues(
unmarshallAttribute(n, "name", ""),
unmarshallAttribute(n, "position", "0"));
} else if (n.getNodeName().equalsIgnoreCase("maskedPreset")) {
((Table2DMaskedSwitchable) table).setPredefinedOption(
unmarshallAttribute(n, "presetName", ""),
unmarshallAttribute(n, "maskedData", "0")
);
} else { /* unexpected element in Table (skip) */
}
} else { /* unexpected node-type in Table (skip) */
}
}
return table;
}
@ -673,11 +684,12 @@ public final class DOMRomUnmarshaller {
return;
}
if (!tableNames.containsKey(name) && address > 0) {
//Why cant the address not be zero?
if (!tableNames.containsKey(name) && address >= 0) {
tableNames.put(name, address);
}
else if (tableNames.containsKey(name)) {
if (tableNames.get(name) < 1 && address > 0) {
if (tableNames.get(name) < 1 && address >= 0) {
tableNames.put(name, address);
}
}

View File

@ -1,6 +1,14 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2018 RomRaider.com
<<<<<<< HEAD
<<<<<<< HEAD
* Copyright (C) 2006-2020 RomRaider.com
=======
* Copyright (C) 2006-2019 RomRaider.com
>>>>>>> Added XOR for single byte checksums. Added possibility of multiple checksums in file
=======
* Copyright (C) 2006-2020 RomRaider.com
>>>>>>> Updated copyright. Switched to checkboxes for presets. Allowed multiple selection. Fixed saving bug. CChanged table name to 2DMaskedSwitchable
*
* 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
@ -27,6 +35,7 @@ import java.nio.ByteOrder;
import com.romraider.Settings;
import com.romraider.maps.Table;
import com.romraider.util.ByteUtil;
public final class RomAttributeParser {
@ -115,6 +124,16 @@ public final class RomAttributeParser {
}
}
//This assumes the bits inside the mask aren't spread. OK = 11110000, Not OK = 11001100
public static long parseByteValueMasked(byte[] input, Settings.Endian endian, int address, int length, boolean signed, int mask) throws ArrayIndexOutOfBoundsException, IndexOutOfBoundsException {
long tempValue = parseByteValue(input,endian,address,length,signed) & mask;
byte index = ByteUtil.firstOneOfMask(mask);
return tempValue >> index;
}
public static long parseByteValue(byte[] input, Settings.Endian endian, int address, int length, boolean signed) throws ArrayIndexOutOfBoundsException, IndexOutOfBoundsException {
try {
long output = 0L;
@ -230,6 +249,9 @@ public final class RomAttributeParser {
else if (input.substring(input.length() - 2).equalsIgnoreCase("mb")) {
return Integer.parseInt(input.substring(0, input.length() - 2)) * 1024 * 1024;
}
else if (input.substring(input.length() - 1).equalsIgnoreCase("b")) {
return Integer.parseInt(input.substring(0, input.length() - 1));
}
throw new NumberFormatException();
}
}