diff --git a/src/main/java/com/romraider/editor/ecu/ECUEditor.java b/src/main/java/com/romraider/editor/ecu/ECUEditor.java index fc8766f2..91dff2e9 100644 --- a/src/main/java/com/romraider/editor/ecu/ECUEditor.java +++ b/src/main/java/com/romraider/editor/ecu/ECUEditor.java @@ -1,6 +1,6 @@ /* * RomRaider Open-Source Tuning, Logging and Reflashing - * Copyright (C) 2006-2014 RomRaider.com + * Copyright (C) 2006-2017 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 @@ -716,6 +716,11 @@ class OpenImageWorker extends SwingWorker { editor.refreshTableCompareMenus(); editor.getStatusPanel().setStatus("Done loading image..."); + setProgress(95); + + editor.getStatusPanel().setStatus("Validating checksum..."); + rom.validateChecksum(); + setProgress(100); return null; } diff --git a/src/main/java/com/romraider/maps/Rom.java b/src/main/java/com/romraider/maps/Rom.java index c96ab66d..91106ddb 100644 --- a/src/main/java/com/romraider/maps/Rom.java +++ b/src/main/java/com/romraider/maps/Rom.java @@ -1,6 +1,6 @@ /* * RomRaider Open-Source Tuning, Logging and Reflashing - * Copyright (C) 2006-2016 RomRaider.com + * Copyright (C) 2006-2017 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 @@ -24,6 +24,8 @@ import static com.romraider.util.HexUtil.asBytes; import static com.romraider.util.HexUtil.asHex; import static javax.swing.JOptionPane.DEFAULT_OPTION; import static javax.swing.JOptionPane.QUESTION_MESSAGE; +import static javax.swing.JOptionPane.WARNING_MESSAGE; +import static javax.swing.JOptionPane.showMessageDialog; import static javax.swing.JOptionPane.showOptionDialog; import java.beans.PropertyVetoException; @@ -43,6 +45,7 @@ import org.apache.log4j.Logger; import com.romraider.Settings; import com.romraider.logger.ecu.ui.handler.table.TableUpdateHandler; +import com.romraider.maps.checksum.ChecksumManager; import com.romraider.swing.CategoryTreeNode; import com.romraider.swing.JProgressPane; import com.romraider.swing.TableFrame; @@ -60,6 +63,7 @@ public class Rom extends DefaultMutableTreeNode implements Serializable { private final Vector tableNodes = new Vector(); private byte[] binData; private boolean isAbstract = false; + private ChecksumManager checksumManager; public Rom() { tableNodes.clear(); @@ -354,6 +358,7 @@ public class Rom extends DefaultMutableTreeNode implements Serializable { } } } + updateChecksum(); return binData; } @@ -416,4 +421,35 @@ public class Rom extends DefaultMutableTreeNode implements Serializable { public DefaultMutableTreeNode getLastChild() { return (DefaultMutableTreeNode) super.getLastChild(); } + + public void setChecksumManager(ChecksumManager checksumManager) { + this.checksumManager = checksumManager; + } + + public ChecksumManager getChecksumType() { + return checksumManager; + } + + public void validateChecksum() { + if (checksumManager != null) { + final String message = String.format( + "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); + } + } + } + + public void updateChecksum() { + if (checksumManager != null) { + checksumManager.update(binData); + } + } } \ No newline at end of file diff --git a/src/main/java/com/romraider/maps/RomID.java b/src/main/java/com/romraider/maps/RomID.java index 3dcf51c1..e90ad4df 100644 --- a/src/main/java/com/romraider/maps/RomID.java +++ b/src/main/java/com/romraider/maps/RomID.java @@ -43,6 +43,7 @@ public class RomID implements Serializable { private int fileSize; private int ramOffset; private boolean obsolete; // whether a more recent revision exists + private String checksum; // checksum method used to validate ROM contents public String toString() { return String.format( @@ -216,4 +217,12 @@ public class RomID implements Serializable { public void setEditStamp(String editStamp) { this.editStamp = editStamp; } + + public void setChecksum(String checksum) { + this.checksum = checksum; + } + + public String getChecksum() { + return checksum; + } } \ No newline at end of file diff --git a/src/main/java/com/romraider/maps/checksum/ChecksumFactory.java b/src/main/java/com/romraider/maps/checksum/ChecksumFactory.java new file mode 100644 index 00000000..4b5c450f --- /dev/null +++ b/src/main/java/com/romraider/maps/checksum/ChecksumFactory.java @@ -0,0 +1,74 @@ +/* + * RomRaider Open-Source Tuning, Logging and Reflashing + * Copyright (C) 2006-2017 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.checksum; + +import static javax.swing.JOptionPane.ERROR_MESSAGE; +import static javax.swing.JOptionPane.showMessageDialog; + +import java.util.Map; + +/** + * Instantiate a ChecksumManager class. + */ +public final class ChecksumFactory { + private static final String TYPE = "type"; + private static final String MISSING = + "Error in checksum definition, 'type' attribute missing."; + private static final String NO_CLASS = + "Error loading Checksum Manager of type: %s"; + private ChecksumFactory() { + } + + /** + * Instantiate the specific ChecksumManager class based on + * the "type" requested. + * @param attrs - the configuration for the checksum manager, must + * contain a "type" K,V pair + * @return a configured instance of the requested ChecksumManager + * @throws ClassNotFoundException if the class based on "type" + * does not exist + */ + public static ChecksumManager getManager( + Map attrs) { + + ChecksumManager cm = null; + Class cls; + final String type = attrs.get(TYPE); + try { + cls = Class.forName( + ChecksumFactory.class.getPackage().getName() + + ".Checksum" + type.toUpperCase()); + cm = (ChecksumManager) cls.newInstance(); + cm.configure(attrs); + } catch (Exception e) { + String message = null; + if (type == null) { + message = MISSING; + } + else { + message = String.format(NO_CLASS, type.toUpperCase()); + } + showMessageDialog(null, + message, + "Error Loading Checksum Manager", ERROR_MESSAGE); + } + return cm; + } +} diff --git a/src/main/java/com/romraider/maps/checksum/ChecksumManager.java b/src/main/java/com/romraider/maps/checksum/ChecksumManager.java new file mode 100644 index 00000000..1b4cae39 --- /dev/null +++ b/src/main/java/com/romraider/maps/checksum/ChecksumManager.java @@ -0,0 +1,51 @@ +/* + * RomRaider Open-Source Tuning, Logging and Reflashing + * Copyright (C) 2006-2017 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.checksum; + +import java.util.Map; + +/** + * The Checksum Manager interface is implemented by Checksum classes + * which perform validation and calculation of ROM checksums upon open + * and save. + */ +public interface ChecksumManager { + + /** + * Once the ChecksumManager is created configure it with the + * information needed to perform checksums. + * @param vars - a map of variables specific to the type of + * checksums being performed + */ + void configure(Map vars); + + /** + * Perform the checksum validation upon ROM file loading. + * @param binData - the ROM file to validate + * @return true or false, the result of validation + */ + boolean validate(byte[] data); + + /** + * Update the checksum upon saving the ROM file. + * @param data - the ROM file to update + */ + void update(byte[] data); +} diff --git a/src/main/java/com/romraider/maps/checksum/ChecksumSTD.java b/src/main/java/com/romraider/maps/checksum/ChecksumSTD.java new file mode 100644 index 00000000..1570d411 --- /dev/null +++ b/src/main/java/com/romraider/maps/checksum/ChecksumSTD.java @@ -0,0 +1,83 @@ +/* + * RomRaider Open-Source Tuning, Logging and Reflashing + * Copyright (C) 2006-2017 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.checksum; + +import static com.romraider.xml.RomAttributeParser.parseByteValue; +import static com.romraider.xml.RomAttributeParser.parseIntegerValue; + +import java.util.Map; + +import com.romraider.util.HexUtil; + +/** + * This class implements the "std" checksum validation and calculations + * for Nissan ROMs. + */ + public final class ChecksumSTD implements ChecksumManager { + private static final String START = "start"; + private static final String END = "end"; + private static final String SUMLOC = "sumloc"; + private static final String XORLOC = "xorloc"; + private int start; + private int end; + private int sumloc; + private int xorloc; + private int sumt; + private int xort; + + public ChecksumSTD() { + } + + @Override + public void configure(Map vars) { + this.start = HexUtil.hexToInt(vars.get(START)); + this.end = HexUtil.hexToInt(vars.get(END)); + this.sumloc = HexUtil.hexToInt(vars.get(SUMLOC)); + this.xorloc = HexUtil.hexToInt(vars.get(XORLOC)); + } + + @Override + public boolean validate(byte[] binData) { + calculate(binData); + final boolean valid = + (sumt == (int)parseByteValue(binData, 0, sumloc, 4, true)) && + (xort == (int)parseByteValue(binData, 0, xorloc, 4, true)); + return valid; + } + + @Override + public void update(byte[] binData) { + calculate(binData); + System.arraycopy(parseIntegerValue(sumt, 0, 4), 0, binData, sumloc, 4); + System.arraycopy(parseIntegerValue(xort, 0, 4), 0, binData, xorloc, 4); + } + + private void calculate(byte[] binData) { + sumt = 0; + xort = 0; + int dw = 0; + for (int i = start; i < end; i += 4) { + if ((i == sumloc) || (i == xorloc)) continue; + dw = (int)parseByteValue(binData, 0, i, 4, true); + sumt += dw; + xort ^= dw; + } + } +} diff --git a/src/main/java/com/romraider/swing/RomPropertyPanel.java b/src/main/java/com/romraider/swing/RomPropertyPanel.java index 19ad2b6a..6514aca9 100644 --- a/src/main/java/com/romraider/swing/RomPropertyPanel.java +++ b/src/main/java/com/romraider/swing/RomPropertyPanel.java @@ -1,6 +1,6 @@ /* * RomRaider Open-Source Tuning, Logging and Reflashing - * Copyright (C) 2006-2012 RomRaider.com + * Copyright (C) 2006-2017 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 @@ -22,6 +22,8 @@ package com.romraider.swing; import com.romraider.maps.Rom; import javax.swing.*; +import javax.swing.GroupLayout.Alignment; +import javax.swing.LayoutStyle.ComponentPlacement; public class RomPropertyPanel extends javax.swing.JPanel { @@ -46,6 +48,7 @@ public class RomPropertyPanel extends javax.swing.JPanel { submodel.setText(rom.getRomID().getSubModel()); transmission.setText(rom.getRomID().getTransmission()); editStamp.setText(rom.getRomID().getEditStamp()); + checksum.setText(rom.getRomID().getChecksum()); tableList.setListData(rom.getTables()); } @@ -81,6 +84,12 @@ public class RomPropertyPanel extends javax.swing.JPanel { lblTables = new javax.swing.JLabel(); lblEditStamp = new javax.swing.JLabel(); editStamp = new javax.swing.JLabel(); + lblChecksum = new javax.swing.JLabel(); + checksum = new javax.swing.JLabel(); + + lblChecksum.setText("Checksum:"); + + checksum.setText("subaru"); lblEditStamp.setText("Edit Stamp:"); @@ -154,122 +163,115 @@ public class RomPropertyPanel extends javax.swing.JPanel { lblTables.setText("Tables:"); GroupLayout layout = new GroupLayout(this); - this.setLayout(layout); layout.setHorizontalGroup( - layout.createParallelGroup(GroupLayout.Alignment.LEADING) + layout.createParallelGroup(Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(lblFilename) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(fileName, GroupLayout.PREFERRED_SIZE, 302, GroupLayout.PREFERRED_SIZE)) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(lblECURevision) - .addComponent(lblEcuVersion) - .addComponent(lblFilesize)) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(fileSize) - .addComponent(ecuVersion) - .addComponent(xmlID))) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(lblYear) - .addComponent(lblModel) - .addComponent(lblSubmodel) - .addComponent(lblTransmission) - .addComponent(lblMarket) - .addComponent(lblMake)) - .addGap(7, 7, 7) - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(make) - .addComponent(market) - .addComponent(year) - .addGroup(layout.createSequentialGroup() - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(transmission) - .addComponent(submodel))) - .addComponent(model)))) - .addGap(32, 32, 32) - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(lblInternalId) - .addComponent(lblStorageAddress) - .addComponent(lblEditStamp)) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 53, Short.MAX_VALUE) - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(internalID) - .addComponent(storageAddress) - .addComponent(editStamp)) - .addGap(36, 36, 36)) - .addComponent(lblTables) - .addComponent(jScrollPane1, GroupLayout.PREFERRED_SIZE, 226, GroupLayout.PREFERRED_SIZE)))) - .addContainerGap()) + .addComponent(lblFilename) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(fileName, GroupLayout.PREFERRED_SIZE, 302, GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(lblECURevision) + .addComponent(lblEcuVersion) + .addComponent(lblFilesize) + .addComponent(lblChecksum) + .addComponent(lblMake) + .addComponent(lblMarket) + .addComponent(lblYear) + .addComponent(lblModel) + .addComponent(lblSubmodel) + .addComponent(lblTransmission)) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(transmission) + .addComponent(submodel) + .addComponent(model) + .addComponent(year) + .addComponent(market) + .addComponent(make) + .addComponent(checksum, GroupLayout.PREFERRED_SIZE, 70, GroupLayout.PREFERRED_SIZE) + .addComponent(fileSize) + .addComponent(ecuVersion) + .addComponent(xmlID)) + .addGap(20) + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(lblTables) + .addComponent(lblEditStamp) + .addComponent(lblStorageAddress) + .addComponent(lblInternalId)) + .addGap(18) + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(editStamp) + .addComponent(storageAddress) + .addComponent(internalID))) + .addGroup(layout.createSequentialGroup() + .addGap(163) + .addComponent(jScrollPane1, GroupLayout.PREFERRED_SIZE, 226, GroupLayout.PREFERRED_SIZE))) + .addContainerGap(51, Short.MAX_VALUE)) ); layout.setVerticalGroup( - layout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addGap(21, 21, 21) - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(lblFilename) - .addComponent(fileName)) - .addGroup(layout.createSequentialGroup() - .addGap(40, 40, 40) - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(lblECURevision) - .addComponent(xmlID) - .addComponent(lblInternalId) - .addComponent(internalID)) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(ecuVersion) - .addComponent(lblEcuVersion) - .addComponent(storageAddress) - .addComponent(lblStorageAddress)) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(lblFilesize) - .addComponent(fileSize) - .addComponent(lblEditStamp) - .addComponent(editStamp)))) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblTables) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(lblMake) - .addComponent(make)) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(lblMarket) - .addComponent(market)) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(lblYear) - .addComponent(year)) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(lblModel) - .addComponent(model)) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(lblSubmodel) - .addComponent(submodel)) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(lblTransmission) - .addComponent(transmission))) - .addComponent(jScrollPane1, 0, 0, Short.MAX_VALUE)) - .addContainerGap()) + layout.createParallelGroup(Alignment.TRAILING) + .addGroup(layout.createSequentialGroup() + .addGap(21) + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(lblFilename) + .addComponent(fileName)) + .addGap(26) + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(lblECURevision) + .addComponent(xmlID) + .addComponent(lblInternalId) + .addComponent(internalID)) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(lblEcuVersion) + .addComponent(ecuVersion) + .addComponent(lblStorageAddress) + .addComponent(storageAddress)) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(lblFilesize) + .addComponent(fileSize) + .addComponent(lblEditStamp) + .addComponent(editStamp)) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(lblChecksum) + .addComponent(checksum) + .addComponent(lblTables)) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(lblMake) + .addComponent(make)) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(lblMarket) + .addComponent(market)) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(lblYear) + .addComponent(year)) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(lblModel) + .addComponent(model)) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(lblSubmodel) + .addComponent(submodel)) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(lblTransmission) + .addComponent(transmission))) + .addComponent(jScrollPane1, 0, 0, Short.MAX_VALUE)) + .addContainerGap()) ); + this.setLayout(layout); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables @@ -302,6 +304,8 @@ public class RomPropertyPanel extends javax.swing.JPanel { private javax.swing.JLabel year; private javax.swing.JLabel lblEditStamp; private javax.swing.JLabel editStamp; + private javax.swing.JLabel lblChecksum; + private javax.swing.JLabel checksum; // End of variables declaration//GEN-END:variables } \ No newline at end of file diff --git a/src/main/java/com/romraider/xml/DOMRomUnmarshaller.java b/src/main/java/com/romraider/xml/DOMRomUnmarshaller.java index 5d403c3f..65a5803b 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-2016 RomRaider.com + * Copyright (C) 2006-2017 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,8 @@ import com.romraider.maps.Table1D; import com.romraider.maps.Table2D; import com.romraider.maps.Table3D; import com.romraider.maps.TableSwitch; +import com.romraider.maps.checksum.ChecksumFactory; +import com.romraider.maps.checksum.ChecksumManager; import com.romraider.swing.DebugPanel; import com.romraider.swing.JProgressPane; import com.romraider.util.ObjectCloner; @@ -61,6 +63,7 @@ public final class DOMRomUnmarshaller { private String memModelEndian = null; private final Scale rawScale = new Scale(); private final Map tableNames = new HashMap(); + private ChecksumManager checksumManager = null; public DOMRomUnmarshaller() { } @@ -107,6 +110,7 @@ public final class DOMRomUnmarshaller { output.getRomID().setRamOffset( output.getRomID().getFileSize() - input.length); + output.setChecksumManager(checksumManager); return output; } } @@ -230,6 +234,9 @@ public final class DOMRomUnmarshaller { } catch (XMLParseException ex) { LOGGER.error("Error unmarshalling rom", ex); } + } else if (n.getNodeName().equalsIgnoreCase("checksum")) { + rom.getRomID().setChecksum(unmarshallAttribute(n, "type", "")); + checksumManager = unmarshallChecksum(n); } else { /* unexpected element in Rom (skip) */ } @@ -674,4 +681,20 @@ public final class DOMRomUnmarshaller { } } } + + /** + * Unmarshall the attributes of the checksum element and populate a + * CheckSumManager object to be assigned to the ROM. + * @param node - the checksum element node to process + * @return CheckSumManager object + */ + private ChecksumManager unmarshallChecksum(Node node) { + final Map attrs = new HashMap(); + + for (int i = 0; i < node.getAttributes().getLength(); i++) { + attrs.put(node.getAttributes().item(i).getNodeName().toLowerCase(), + node.getAttributes().item(i).getNodeValue()); + } + return ChecksumFactory.getManager(attrs); + } }