Move XDF into seperate test; Fix bug where table is rendered twice; Improve XDF support

This commit is contained in:
Robin K 2022-11-06 19:49:57 +01:00 committed by Dale Schultz
parent f6014b7665
commit a637a382f0
12 changed files with 260 additions and 155 deletions

View File

@ -379,7 +379,37 @@ public class ECUEditor extends AbstractFrame {
INFORMATION_MESSAGE);
}
}
public TableView createTableView(Table t)
{
TableView v = null;
try {
if (t != null) {
if(t instanceof TableSwitch)
v = new TableSwitchView((TableSwitch)t);
else if(t instanceof TableBitwiseSwitch)
v = new TableBitwiseSwitchView((TableBitwiseSwitch)t);
else if(t instanceof Table1D)
v = new Table1DView((Table1D)t, Table1DType.NO_AXIS);
else if(t instanceof Table2D)
v = new Table2DView((Table2D)t);
else if(t instanceof Table3D)
v = new Table3DView((Table3D)t);
}
}
catch(Exception e) {
final String msg = MessageFormat.format(
rb.getString("POPULATEFAIL"), t.getName(),
e.toString());
final Exception ex = new Exception(msg);
showMessageDialog(this,
new DebugPanel(ex, settings.getSupportURL()),
rb.getString("EXCEPTION"),
ERROR_MESSAGE);
}
return v;
}
public void displayTable(TableTreeNode node) {
TableFrame frame = node.getFrame();
@ -418,53 +448,21 @@ public class ECUEditor extends AbstractFrame {
}
}
if(frame == null) {
TableView v;
Table t = node.getTable();
try {
if (t != null) {
if(t instanceof TableSwitch)
v = new TableSwitchView((TableSwitch)t);
else if(t instanceof TableBitwiseSwitch)
v = new TableBitwiseSwitchView((TableBitwiseSwitch)t);
else if(t instanceof Table1D)
v = new Table1DView((Table1D)node.getTable(), Table1DType.NO_AXIS);
else if(t instanceof Table2D)
v = new Table2DView((Table2D)t);
else if(t instanceof Table3D)
v = new Table3DView((Table3D)t);
else
return;
Rom rom = RomTree.getRomNode(node);
frame = new TableFrame(node.getTable().getName() + " | " + rom.getFileName(), v);
}
}
catch(Exception e) {
final String msg = MessageFormat.format(
rb.getString("POPULATEFAIL"), t.getName(),
e.toString());
final Exception ex = new Exception(msg);
showMessageDialog(this,
new DebugPanel(ex, settings.getSupportURL()),
rb.getString("EXCEPTION"),
ERROR_MESSAGE);
}
}
if(frame == null) {
Rom rom = RomTree.getRomNode(node);
TableView v = createTableView(node.getTable());
frame = new TableFrame(node.getTable().getName() + " | " + rom.getFileName(), v);
v.populateTableVisual();
v.drawTable();
rightPanel.add(frame);
rightPanel.repaint();
refreshTableCompareMenus();
}
} catch (IllegalArgumentException ex) {
// Do nothing.
}
// frame not added. Draw table and add the frame.
TableView v = frame.getTableView();
if(v != null)
v.drawTable();
rightPanel.add(frame);
rightPanel.repaint();
refreshTableCompareMenus();
}
public void removeDisplayTable(TableFrame frame) {

View File

@ -60,7 +60,12 @@ public class OpenImageWorker extends SwingWorker<Void, Void> {
public OpenImageWorker(File inputFile) {
this.inputFile = inputFile;
}
public Rom getRom()
{
return rom;
}
private void loadRom(Rom rom, byte[] input) {
ECUEditor editor = ECUEditorManager.getECUEditor();
editor.getStatusPanel().setStatus(

View File

@ -385,7 +385,7 @@ public class DataCellView extends JLabel implements MouseListener, Serializable
String displayString = null;
try {
FORMATTER.applyPattern(tableView.getTable().getCurrentScale().getFormat());
double staticDouble = NumberUtil.doubleValue(dataCell.getStaticText());
double staticDouble = Double.parseDouble(dataCell.getStaticText());
displayString = FORMATTER.format(JEPUtil.evaluate(tableView.getTable().getCurrentScale().getExpression(), staticDouble));
} catch (Exception ex) {
displayString = dataCell.getStaticText();

View File

@ -74,13 +74,16 @@ public class Rom extends DefaultMutableTreeNode implements Serializable {
private File fullFileName = new File(".");
private byte[] binData;
private Document doc;
// This is currently only used for unit testing
// It could however be used to create a list of faulty tables instead
// of an endless loop or error messages with a bad definition or bin
private List<String> faultyTables = new LinkedList<String>();
//This keeps track of DataCells on a byte level
//This might also be possible to achieve by using the same Data Tables
protected HashMap<Integer, LinkedList<DataCell>> byteCellMapping = new HashMap<Integer, LinkedList<DataCell>>();
private boolean isAbstract = false;
private final LinkedHashMap<String, TableTreeNode> tableNodes = new LinkedHashMap<String, TableTreeNode>();
private LinkedList<ChecksumManager> checksumManagers = new LinkedList<ChecksumManager>();
@ -89,7 +92,12 @@ public class Rom extends DefaultMutableTreeNode implements Serializable {
public Rom(RomID romID) {
this.romID = romID;
}
public List<String> getFaultyTables()
{
return faultyTables;
}
//This makes sure we automatically sort the tables by name
public void sortedAdd(DefaultMutableTreeNode currentParent, DefaultMutableTreeNode newNode) {
boolean found = false;
@ -215,11 +223,29 @@ public class Rom extends DefaultMutableTreeNode implements Serializable {
rb.getString("ECUDEFERROR"), JOptionPane.ERROR_MESSAGE);
}
private void handleException(Table table, Exception e, boolean isOutOfBounds)
{
boolean isTesting = SettingsManager.getTesting();
if(!isTesting)
{
if(isOutOfBounds)
showBadTablePopup(table, e);
else
showNullExceptionPopup(table, e);
}
else
{
e.printStackTrace();
}
faultyTables.add(table.getName());
}
public void populateTables(byte[] binData, JProgressPane progress) {
this.binData = binData;
int size = tableNodes.size();
int i = 0;
Vector <String> badKeys = new Vector<String>();
faultyTables.clear();
for(String name: tableNodes.keySet()) {
// update progress
@ -227,7 +253,6 @@ public class Rom extends DefaultMutableTreeNode implements Serializable {
progress.update(rb.getString("POPTABLES"), currProgress);
Table table = tableNodes.get(name.toLowerCase()).getTable();
try {
if (table.getStorageAddress() >= 0) {
try {
@ -237,15 +262,12 @@ public class Rom extends DefaultMutableTreeNode implements Serializable {
if (null != table.getName() && table.getName().equalsIgnoreCase("Checksum Fix")){
setEditStamp(binData, table.getStorageAddress());
}
i++;
} catch (ArrayIndexOutOfBoundsException ex) {
showBadTablePopup(table, ex);
badKeys.add(table.getName());
handleException(table, ex, true);
size--;
} catch (IndexOutOfBoundsException iex) {
showBadTablePopup(table, iex);
badKeys.add(table.getName());
handleException(table, iex, true);
size--;
}
} else {
@ -254,13 +276,12 @@ public class Rom extends DefaultMutableTreeNode implements Serializable {
}
} catch (NullPointerException ex) {
showNullExceptionPopup(table, ex);
badKeys.add(table.getName());
handleException(table, ex, false);
size--;
}
}
for(String s: badKeys) {
for(String s: faultyTables) {
tableNodes.remove(s.toLowerCase());
}
}
@ -482,14 +503,6 @@ public class Rom extends DefaultMutableTreeNode implements Serializable {
this.setFileName(fullFileName.getName());
}
public boolean isAbstract() {
return isAbstract;
}
public void setAbstract(boolean isAbstract) {
this.isAbstract = isAbstract;
}
@Override
public DefaultMutableTreeNode getChildAt(int i) {
return (DefaultMutableTreeNode) super.getChildAt(i);

View File

@ -22,6 +22,7 @@
package com.romraider.maps;
import java.io.Serializable;
import java.util.HashMap;
import com.romraider.util.JEPUtil;
@ -40,8 +41,8 @@ public class Scale implements Serializable {
private double min = 0.0;
private double max = 0.0;
private double lastApproximatedInput;
private double lastApproximatedOutput;
HashMap<Double, Double> cachedValues = new HashMap<Double,Double>();
int maxCacheSize = 100;
@Override
public String toString() {
@ -77,9 +78,11 @@ public class Scale implements Serializable {
public double approximateToByteFunction(double input, int storageType, boolean signed) {
//If we just calculated this, return the last output
if(lastApproximatedInput == input)
return lastApproximatedOutput;
// Check if we already calculated this
if(cachedValues.containsKey(input))
{
return cachedValues.get(input);
}
long maxValue = (int) Math.pow(2, 8 * storageType);
long minValue = 0;
@ -127,8 +130,10 @@ public class Scale implements Serializable {
lastError = error;
}
lastApproximatedInput = input;
lastApproximatedOutput = output;
if(cachedValues.size() < maxCacheSize)
{
cachedValues.put(input, output);
}
//System.out.println("Input: " + input + " from approx: " + JEPUtil.evaluate(getExpression(), output));
return currentStep;

View File

@ -46,8 +46,6 @@ public class Table1DView extends TableView {
this.table = table;
this.hide = hide;
this.type = axisType;
populateTableVisual();
}
public Table1DType getType() {

View File

@ -38,7 +38,6 @@ public class Table2DView extends TableView {
super(table);
axis = new Table1DView(table.getAxis(), Table1DType.X_AXIS);
verticalOverhead += 18;
populateTableVisual();
}
public Table1DView getAxis() {
@ -78,7 +77,8 @@ public class Table2DView extends TableView {
centerLayout.setRows(2);
centerLayout.setColumns(table.getDataSize());
axis.populateTableVisual();
// add to table
for (int i = 0; i < table.getDataSize(); i++) {
centerPanel.add(axis.getDataCell(i));

View File

@ -56,8 +56,6 @@ public class Table3DView extends TableView {
verticalOverhead += 39;
horizontalOverhead += 10;
populateTableVisual();
}
@Override
@ -96,7 +94,9 @@ public class Table3DView extends TableView {
// temporarily remove lock
boolean tempLock = table.locked;
table.locked = false;
xAxis.populateTableVisual();
yAxis.populateTableVisual();
for (int x = 0; x < xAxis.getTable().getDataSize(); x++) {
centerPanel.add(xAxis.getDataCell(x));
}
@ -174,7 +174,6 @@ public class Table3DView extends TableView {
xAxisLabel.setBorder(new EmptyBorder(2, 4, 2, 4));
if(presetPanel != null) presetPanel.populatePanel();
drawTable();
}
@Override

View File

@ -63,7 +63,6 @@ public class TableFrame extends JInternalFrame implements InternalFrameListener,
t.setTableFrame(this);
add(tableView);
tableView.repaint();
setBorder(createBevelBorder(0));
if (System.getProperty("os.name").startsWith("Mac OS"))

View File

@ -65,6 +65,10 @@ public class SettingsManager {
testing = b;
}
public static boolean getTesting() {
return testing;
}
private static Settings load() {
Settings loadedSettings;
try {

View File

@ -215,6 +215,8 @@ public class XDFConversionLayer extends ConversionLayer {
int staticCells = 0;
int indexCount = -1;
String lastStaticValue = "";
int numDigitsStatic = -1;
int localNumDigits = -1;
if (!hasEmbedInfo) {
for (int i = 0; i < nodeCountAxis; i++) {
@ -278,17 +280,11 @@ public class XDFConversionLayer extends ConversionLayer {
} else if (n.getNodeName().equalsIgnoreCase("units")) {
scaling.setAttribute("units", n.getTextContent());
} else if (n.getNodeName().equalsIgnoreCase("decimalpl")) {
String format = "0";
if (!n.getTextContent().equals("0")) {
try {
int count = Math.abs(Integer.parseInt(n.getTextContent()));
format = "0." + new String(new char[count]).replace("\0", "0");
} catch (NumberFormatException e) {
//Do nothing
}
try {
localNumDigits = Math.abs(Integer.parseInt(n.getTextContent()));
} catch (NumberFormatException e) {
//Do nothing
}
scaling.setAttribute("format", format);
} else if (!hasEmbedInfo && n.getNodeName().equalsIgnoreCase("math")) {
String formula = n.getAttributes().getNamedItem("equation").getNodeValue();
formula = formula.replace("X", "x").replace(",", ".");
@ -300,20 +296,42 @@ public class XDFConversionLayer extends ConversionLayer {
targetTable.appendChild(data);
lastStaticValue = label;
staticCells++;
if(numDigitsStatic == -1)
{
// Assume the format from the static data
String split[] = label.split("\\.");
if(split.length > 1)
{
numDigitsStatic = split[1].length();
}
else
{
numDigitsStatic = 0;
}
}
}
}
}
if (staticCells == indexCount && indexCount > 1 && !lastStaticValue.equalsIgnoreCase("0.00")) {
boolean isStatic = staticCells == indexCount && indexCount > 1 && !lastStaticValue.equalsIgnoreCase("0.00");
if (isStatic)
{
staticTable = "Static ";
targetTable.setAttribute("size" + id, "" + staticCells);
targetTable.removeAttribute("endian");
targetTable.removeAttribute("storagetype");
}
}
// Case 1: Static table and no num digits set == Deduce from text
// Case 2: Non static table and digits are set
// Case 3: Non static table and digits arent sent --> use defaults
int digits = isStatic && localNumDigits == -1 ? numDigitsStatic : (localNumDigits == -1 ? numDigits : localNumDigits);
if (digits == 0)
scaling.setAttribute("format", "0");
else
scaling.setAttribute("format", "0." + new String(new char[digits]).replace("\0", "0"));
if (!scaling.hasAttribute("format")) {
String format = "0." + new String(new char[numDigits]).replace("\0", "0");
scaling.setAttribute("format", format);
}
if (!targetTable.hasAttribute("storageaddress") && staticTable.isEmpty())
return null;
@ -576,58 +594,4 @@ public class XDFConversionLayer extends ConversionLayer {
return doc;
}
/*
private static LinkedList<File> listFileTree(File dir) {
LinkedList<File> fileTree = new LinkedList<File>();
if (dir == null || dir.listFiles() == null) {
return fileTree;
}
for (File entry : dir.listFiles()) {
if (entry.isFile())
fileTree.add(entry);
else if (entry.isDirectory())
fileTree.addAll(listFileTree(entry));
}
return fileTree;
}
*/
// Test Code
public static void main(String args[]) {
initDebugLogging();
initLookAndFeel();
ECUEditor editor = getECUEditor();
editor.initializeEditorUI();
editor.checkDefinitions();
// Make sure we dont override any settings
SettingsManager.setTesting(true);
Settings settings = SettingsManager.getSettings();
List < File > listOfFiles = new LinkedList < File > ();
// File folder = new File("C:\\Users\\User\\Downloads\\BMW-XDFs-master\\");
listOfFiles.add(new File("E:\\Downloads\\MS430069_64K.xdf"));
// listOfFiles.add(new File("C:\\Users\\User\\Downloads\\BMW-XDFs-master\\F G
// series B58\\00003076501103.xdf"));
// Collection<File> listOfFiles = listFileTree(folder);
// Collections.shuffle((List<?>) listOfFiles);
for (File f: listOfFiles) {
ConversionLayer l = new XDFConversionLayer();
if (l.isFileSupported(f)) {
settings.getEcuDefinitionFiles().clear();
settings.getEcuDefinitionFiles().add(f);
// File bin = new File(f.getAbsolutePath().replace(".xdf", "_original.bin"));
File bin = new File("E:\\google_drive\\ECU_Tuning\\maps\\MS43_430069_64KB_.bin");
if (bin.exists()) {
System.out.println(f);
OpenImageWorker w = new OpenImageWorker(bin);
w.execute();
break;
}
}
}
}
}

View File

@ -0,0 +1,120 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2021 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.xml;
import static com.romraider.editor.ecu.ECUEditorManager.getECUEditor;
import static com.romraider.swing.LookAndFeelManager.initLookAndFeel;
import static com.romraider.util.LogManager.initDebugLogging;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import java.io.File;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Vector;
import org.junit.Test;
import com.romraider.Settings;
import com.romraider.editor.ecu.ECUEditor;
import com.romraider.editor.ecu.OpenImageWorker;
import com.romraider.maps.Rom;
import com.romraider.maps.Table;
import com.romraider.util.SettingsManager;
import com.romraider.xml.ConversionLayer.ConversionLayer;
import com.romraider.xml.ConversionLayer.XDFConversionLayer;
public class XDFConversionLayerTest{
private static LinkedList<File> listFileTree(File dir) {
LinkedList<File> fileTree = new LinkedList<File>();
if (dir == null || dir.listFiles() == null) {
return fileTree;
}
for (File entry : dir.listFiles()) {
if (entry.isFile())
fileTree.add(entry);
else if (entry.isDirectory())
fileTree.addAll(listFileTree(entry));
}
return fileTree;
}
@Test
public void loadXDFs() {
initDebugLogging();
initLookAndFeel();
ECUEditor editor = getECUEditor();
editor.initializeEditorUI();
editor.checkDefinitions();
// Make sure we dont override any settings
SettingsManager.setTesting(true);
Settings settings = SettingsManager.getSettings();
// https://github.com/dmacpro91/BMW-XDFs
// Download locally and unzip
File folder = new File("C:\\Users\\User\\Downloads\\BMW-XDFs-master\\");
Collection<File> listOfFiles = listFileTree(folder);
for (File f: listOfFiles) {
ConversionLayer l = new XDFConversionLayer();
if (l.isFileSupported(f)) {
editor.closeAllImages();
settings.getEcuDefinitionFiles().clear();
settings.getEcuDefinitionFiles().add(f);
File bin = new File(f.getAbsolutePath().replace(".xdf", "_original.bin"));
if (bin.exists()) {
OpenImageWorker w = new OpenImageWorker(bin);
w.execute();
//Wait until rom its loaded
while(!w.isDone())
{
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Rom r = w.getRom();
try
{
assertNotEquals(r, null);
assertEquals(r.getFaultyTables().size(), 0);
}
catch(AssertionError e)
{
System.out.println(f + ": Faulty Tables " + r.getFaultyTables().size());
continue;
}
// Populate tables visually
Vector<Table> tables = r.getTables();
for (Table table:tables)
{
editor.createTableView(table);
}
}
}
}
}
}