/* * RomRaider Open-Source Tuning, Logging and Reflashing * Copyright (C) 2006-2012 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 static com.romraider.xml.RomAttributeParser.parseByteValue; import static com.romraider.xml.RomAttributeParser.parseIntegerValue; import com.romraider.Settings; public class RomChecksum { public static void calculateRomChecksum(byte[] input, int storageAddress, int dataSize) { for (int i = storageAddress; i < storageAddress + dataSize; i+=12) { byte[] newSum = calculateChecksum(input, (int)parseByteValue(input, 0, i , 4, true), (int)parseByteValue(input, 0, i+4, 4, true)); System.arraycopy(newSum, 0, input, i + 8, 4); } } public static int validateRomChecksum(byte[] input, int storageAddress, int dataSize) { int result = 0; int[] results = new int[dataSize / 12]; int j = 0; for (int i = storageAddress; i < storageAddress + dataSize; i+=12) { int startAddr = (int)parseByteValue(input, 0, i , 4, true); int endAddr = (int)parseByteValue(input, 0, i+4, 4, true); int diff = (int)parseByteValue(input, 0, i+8, 4, true); if (j == 0 && startAddr == 0 && endAddr == 0 && diff == Settings.CHECK_TOTAL) { return result = -1; // -1, all checksums disabled if the first one is disabled } else { results[j] = validateChecksum(input, startAddr, endAddr, diff); } j++; } for (j = 0; j < (dataSize / 12); j++) { if (results[j] != 0) { return j + 1; // position of invalid checksum } } return result; // 0, all checksums are valid } private static int validateChecksum(byte[] input, int startAddr, int endAddr, int diff) { int byteSum = 0; for (int i=startAddr; i<endAddr; i+=4) { byteSum += (int)parseByteValue(input, 0, i, 4, true); } int result = (Settings.CHECK_TOTAL - diff - byteSum); return result; } private static byte[] calculateChecksum(byte[] input, int startAddr, int endAddr) { int byteSum = 0; for (int i=startAddr; i<endAddr; i+=4) { byteSum += (int)parseByteValue(input, 0, i, 4, true); } return parseIntegerValue((Settings.CHECK_TOTAL - byteSum), 0, 4); } }