diff --git a/src/main/java/com/romraider/maps/Rom.java b/src/main/java/com/romraider/maps/Rom.java index 91106ddb..283fb2bd 100644 --- a/src/main/java/com/romraider/maps/Rom.java +++ b/src/main/java/com/romraider/maps/Rom.java @@ -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 tableNodes = new Vector(); private byte[] binData; private boolean isAbstract = false; - private ChecksumManager checksumManager; + private LinkedList checksumManagers = new LinkedList(); 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); + } } } } \ No newline at end of file diff --git a/src/main/java/com/romraider/maps/Table.java b/src/main/java/com/romraider/maps/Table.java index 2ec6aaf9..80994b63 100644 --- a/src/main/java/com/romraider/maps/Table.java +++ b/src/main/java/com/romraider/maps/Table.java @@ -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(); - - 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(); - } - - // Calc compare - double compareValue = cell.getCompareValue(); - if(compareMax < compareValue) { - compareMax = compareValue; - } - if(compareMin > compareValue) { - compareMin = compareValue; - } - } - setMaxBin(binMax); - setMinBin(binMin); - setMaxCompare(compareMax); - setMinCompare(compareMin); + if(data.length > 0) { + double binMax = data[0].getBinValue(); + double binMin = data[0].getBinValue(); + + 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(); + } + + // 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; diff --git a/src/main/java/com/romraider/maps/Table2D.java b/src/main/java/com/romraider/maps/Table2D.java index ede7472d..e1491887 100644 --- a/src/main/java/com/romraider/maps/Table2D.java +++ b/src/main/java/com/romraider/maps/Table2D.java @@ -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 @@ -62,7 +62,15 @@ public class Table2D extends Table { public Table1D getAxis() { 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); diff --git a/src/main/java/com/romraider/maps/Table2DMaskedSwitchable.java b/src/main/java/com/romraider/maps/Table2DMaskedSwitchable.java new file mode 100644 index 00000000..0b8a20de --- /dev/null +++ b/src/main/java/com/romraider/maps/Table2DMaskedSwitchable.java @@ -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 defaultEntries = new LinkedList(); + private final List buttonGroup = new ArrayList(); + + //Struct for saving Preset values + private class PresetEntry { + String name; + LinkedList 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(); + + + 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 values; //Pointer to PresetEntry.data + + public void setPresetData(LinkedList 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); + } + } +} diff --git a/src/main/java/com/romraider/maps/checksum/ChecksumBYTEXOR.java b/src/main/java/com/romraider/maps/checksum/ChecksumBYTEXOR.java new file mode 100644 index 00000000..43301e1f --- /dev/null +++ b/src/main/java/com/romraider/maps/checksum/ChecksumBYTEXOR.java @@ -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 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; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/romraider/util/ByteUtil.java b/src/main/java/com/romraider/util/ByteUtil.java index cedde6f4..3cb3336e 100644 --- a/src/main/java/com/romraider/util/ByteUtil.java +++ b/src/main/java/com/romraider/util/ByteUtil.java @@ -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 @@ -118,6 +118,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]; @@ -134,4 +159,5 @@ public final class ByteUtil { return failure; } + } diff --git a/src/main/java/com/romraider/xml/DOMRomUnmarshaller.java b/src/main/java/com/romraider/xml/DOMRomUnmarshaller.java index ea324714..8526a168 100644 --- a/src/main/java/com/romraider/xml/DOMRomUnmarshaller.java +++ b/src/main/java/com/romraider/xml/DOMRomUnmarshaller.java @@ -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", @@ -476,6 +481,7 @@ public final class DOMRomUnmarshaller { table.isLocked())); table.setLogParam(unmarshallAttribute(tableNode, "logparam", table.getLogParam())); + if (table.getType() == Table.TableType.TABLE_3D) { ((Table3D) table).setSwapXY(unmarshallAttribute(tableNode, @@ -489,7 +495,12 @@ public final class DOMRomUnmarshaller { ((Table3D) table).setSizeY(unmarshallAttribute(tableNode, "sizey", ((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 @@ -579,18 +590,18 @@ public final class DOMRomUnmarshaller { ((TableSwitch) table).setValues( 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); } } diff --git a/src/main/java/com/romraider/xml/RomAttributeParser.java b/src/main/java/com/romraider/xml/RomAttributeParser.java index eb4b752c..6c000afc 100644 --- a/src/main/java/com/romraider/xml/RomAttributeParser.java +++ b/src/main/java/com/romraider/xml/RomAttributeParser.java @@ -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 { @@ -114,7 +123,17 @@ public final class RomAttributeParser { return Table.TableType.TABLE_1D; } } + + //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(); } }