|
|
@@ -14,8 +14,8 @@ import (
|
|
|
// with all applicable fields populated or an error depicting the reason for
|
|
|
// failure.
|
|
|
func Parse(rawPokemon p.RawPokemon) (*p.Pokemon, error) {
|
|
|
- if l := len(rawPokemon); l < 232 {
|
|
|
- return nil, fmt.Errorf("Invalid length for generation 7 pokemon: %d bytes", l)
|
|
|
+ if err := validateRawPokemon(rawPokemon); err != nil {
|
|
|
+ return nil, err
|
|
|
}
|
|
|
|
|
|
var pkmn p.Pokemon
|
|
|
@@ -97,3 +97,32 @@ func binaryToUTF16leString(b []byte) string {
|
|
|
|
|
|
return s
|
|
|
}
|
|
|
+
|
|
|
+func calculateChecksum(b []byte) uint16 {
|
|
|
+ var sum uint16
|
|
|
+ for i := 8; i < 232; i += 2 {
|
|
|
+ sum += toUint16(b[i : i+2])
|
|
|
+ }
|
|
|
+ return sum & 0xffff
|
|
|
+}
|
|
|
+
|
|
|
+func toUint16(b []byte) uint16 {
|
|
|
+ return binary.LittleEndian.Uint16(b)
|
|
|
+}
|
|
|
+
|
|
|
+func validateRawPokemon(rawPokemon p.RawPokemon) error {
|
|
|
+ if l := len(rawPokemon); l != 232 && l != 260 {
|
|
|
+ return fmt.Errorf("Invalid length for generation 7 pokemon: %d bytes", l)
|
|
|
+ }
|
|
|
+
|
|
|
+ checksumValue := toUint16(rawPokemon[0x06:0x08])
|
|
|
+ if calculatedChecksum := calculateChecksum(rawPokemon); calculatedChecksum != checksumValue {
|
|
|
+ return fmt.Errorf("Invalid checksum for generation 7 pokemon")
|
|
|
+ }
|
|
|
+
|
|
|
+ if toUint16(rawPokemon[0x04:0x06]) == 1 || rawPokemon[0x58] == 1 || rawPokemon[0x90] == 1 || rawPokemon[0xc8] == 1 {
|
|
|
+ return fmt.Errorf("Invalid bytes supplied for generation 7 pokemon")
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|