Skip to content

Instantly share code, notes, and snippets.

@peterc
Created September 27, 2016 23:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peterc/e5aa1315154813d0de48f9c555b8c055 to your computer and use it in GitHub Desktop.
Save peterc/e5aa1315154813d0de48f9c555b8c055 to your computer and use it in GitHub Desktop.
Decoding and encoding of Solar Jetman (NES) passwords / game codes
# Decoding and encoding of Solar Jetman (NES)
# game password codes
#
# Based on research done by Bisqwit / Joel Yliluoma
# See https://www.youtube.com/watch?v=Ex1iFZuUdJ4
SYMBOLS = %w{B D G H K L M N P Q R T V W X Z}
def checksum_for_bytes(bytes)
((((bytes[0] ^ bytes[1]) + bytes[2]) ^ bytes[4]) * 257 / 256 + bytes[5]) & 0b11111111
end
def decode(code)
{}.tap do |o|
nibbles = code.chars.map { |c| SYMBOLS.index(c) }
bytes = nibbles.each_slice(6).to_a.transpose.map { |a, b| (a << 4) + b }
o[:extra_lives] = (bytes[0] & 0b11110000) >> 4
o[:level] = (bytes[2] & 0b11111100) >> 2
o[:map] = bytes[2] & 1
o[:map2] = (bytes[2] & 2) >> 1
o[:booster] = bytes[4] & 1
o[:shield] = (bytes[4] & 2) >> 1
o[:pod] = (bytes[4] & 0b1100) >> 2
o[:score] = (bytes[5] & 0b1111) * 100000 + (bytes[1] & 0b1111) * 10000 + (bytes[0] & 0b1111) * 1000 + ((bytes[4] & 0b11110000) >> 4) * 100 + ((bytes[5] & 0b11110000) >> 4) * 10 + ((bytes[1] & 0b11110000) >> 4)
raise "Invalid code" unless bytes[3] == checksum_for_bytes(bytes)
end
end
def encode(o)
bytes = []
bytes[0] = (o[:extra_lives] << 4) + ((o[:score] % 10000) / 1000)
bytes[1] = ((o[:score] % 10) << 4) + ((o[:score] % 100000) / 10000)
bytes[2] = (o[:level] << 2) + (o[:map2] << 1) + o[:map]
bytes[4] = (((o[:score] % 1000) / 100) << 4) + (o[:pod] << 2) + (o[:shield] << 1) + o[:booster]
bytes[5] = (((o[:score] % 100) / 10) << 4) + ((o[:score] % 1000000) / 100000)
bytes[3] = checksum_for_bytes(bytes)
bytes.map { |b| [(b & 0b11110000) >> 4, b & 0b1111] }.transpose.flatten.map { |c| SYMBOLS[c] }.join
end
# Decode an existing code
data = decode("PMGPBPBBZLTB")
puts "Extra lives: #{data[:extra_lives]}\t\tLevel: #{data[:level]}"
puts "Map: #{data[:map]}\t\t\tMap2: #{data[:map2]}"
puts "Booster: #{data[:booster]}\t\tShield: #{data[:shield]}"
puts "Pod: #{data[:pod]}\t\t\tScore: #{data[:score]}"
# Create a new code
puts encode(extra_lives: 8, level: 11, map: 1, map2: 1, booster: 1, shield: 1, pod: 2, score: 86)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment