Сегодня я хотел бы рассказать про одну замечательную серию игр. Многие познакомились с ней, благодаря версии на NES, некоторые видели персидского принца на DOS, кто-то играл в Принц Персии на Sega Genesis и… вроде всё, но нет! Первая часть была портирована на большое количество разных игровых платформ. А сколько систем паролей было придумано по этому поводу? А сколько портов было у второй части? А какие пароли были там?
Про это я и хотел бы Вам рассказать.
Prince of Persia (Sega Master System/Sega Game Gear)
Теория
Пароль состоит из 6 позиций. Эти позиции сохраняют данные игровые параметры:
- уровень (1-14)
- время (0-99)
- жизни (0-7)
- рандом (0-25)
Генерация
1 позиция = ((уровень -1) + рандом) mod26
2 позиция = ((время div10) + рандом) mod26
3 позиция = ((время mod10) + рандом) mod26
4 позиция = (жизни + рандом) mod26
5 позиция = рандом
6 позиция = ((сумма позиций с 1 по 5) + 10) mod26
Кодирование
Символы в позициях принимают значения «ABCDEFGHIJKLMNOPQRSTUVWXYZ», где A=0, B=1… Y=24, Z=25.
- уровень (12)
- жизни (6)
- время (59)
- рандом (18)
Вычисляем:
1)
1 позиция = ((12 -1) + 18) mod26
2 позиция = ((59 div10) + 18) mod26
3 позиция = ((59 mod10) +18) mod26
4 позиция = (6+18) mod26
5 позиция = 18
6 позиция = 10
2)
1 позиция = 3
2 позиция = 23
3 позиция = 1
4 позиция = 24
5 позиция = 18
6 позиция = (3+23+1+24+18+10) mod26 = 1
Теперь кодируем получившиеся значения:
DXBYSB
Интересный баг
В игре есть баг, с помощью которого можно получить бессмертие. Но перед объяснением, я хотел бы обсудить архитектуру уровней. Условно разделим экран на 3 этажа.
Если у принца жизни от 1 до 7, то при падении со 2 этажа на 1, жизни не тратятся. А при падении с 3 этажа на 1, тратится 1 жизнь. Если жизней 0, то происходит всё наоборот. При падении со 2 этажа на 1, принц умирает, а при падении с 3 этажа на 1, происходит баг: игра даст принцу 8 жизней (не забываем, что максимум равняется семи).
После проделанной операции, принц сможет спрыгивать с 3 и 2 этажа, не нанося себе урон (если взять 4 этаж, то принц умрёт). Также принц будет неуязвим для вражеских атак (если оружие будет в руках). После прохождения уровня, баг исчезает и у принца снова станет 0 жизней. А если с нулём жизней напасть на стражника, то он Вас просто проигнорирует и убить его станет невозможно.
Вот так вот.
Prince of Persia (Game Boy/Game Boy Color)
Теория
Пароль состоит из 8 позиций. Эти позиции сохраняют данные игровые параметры:
- уровень (2-14)
- время (1-59)
- жизни (3-9)
Примечание: на 7 уровень нельзя создать пароль.
Генерация
1 позиция = (4 позиция + 7 позиция + 8 позиция) mod10
2 позиция = (5 позиция + 6 позиция) mod10
3 позиция = (7 позиция + 8 позиция) mod10
4 позиция = жизни
5 позиция = время mod10
6 позиция = время div10
7 позиция = уровень mod10
8 позиция = уровень div10
Кодирование
Ко всем позициям применяется операция: XOR 5. Если после выполнения этой операции получилось двухзначное число, то надо вычесть 4.
- уровень (9)
- жизни (7)
- время (35)
Вычисляем:
1)
1 позиция = 0
2 позиция = 0
3 позиция = 0
4 позиция = 7
5 позиция = 35 mod10
6 позиция = 35 div10
7 позиция = 9 mod10
8 позиция = 9 div10
2)
1 позиция = (7+9+0) mod10 = 6
2 позиция = (5+3) mod10 = 8
3 позиция = (9+0) mod10 = 9
4 позиция = 7
5 позиция = 5
6 позиция = 3
7 позиция = 9
8 позиция = 0
Теперь кодируем получившиеся значения:
6 XOR 5 = 3
8 XOR 5 = 13-4 = 9
9 XOR 5 = 12-4 = 8
7 XOR 5 = 2
5 XOR 5 = 0
3 XOR 5 = 6
9 XOR 5 = 12-4 = 8
0 XOR 5 = 5
Готовый пароль: 39820685
Prince of Persia (Sega Genesis)
Теория
Пароль состоит из 6 позиций. Эти позиции сохраняют данные игровые параметры:
US version:
- уровень (1-13)
- время (0-60)
- жизни (1-8)
EU version:
- уровень (1-13)
- время (0-60)
- жизни (0-8)
Если будете играть в эту игру, то лучше выбирайте EU версию, так как:
- в EU версии добавили 4 дополнительных уровня
- в EU версии есть музыкальное сопровождение на уровнях
- в EU версии есть баг-бессмертие
Генерация
Условно разделим пароль на две части (каждая часть состоит из трёх позиций).
Первая часть сохраняет время:
(10545*время)mod 17576
Полученное число из 10 CC переводится в 26 СС (СС — система счисления).
Потом полученное значение нужно зеркально отобразить. Если длина полученного «пароля» меньше 3 символов, то справа дописывается необходимое число нулей.
Вторая часть сохраняет время, количество жизней и уровень:
((10545*время) + (14157*(уровень-1)) + (5145*жизни))mod 17576
Полученное число из 10 CC переводится в 26 СС. Потом полученное значение нужно зеркально отобразить. Если длина полученного «пароля» меньше 3 символов, то справа дописывается необходимое число нулей.
Кодирование
Символы в позициях принимают значения «ABCDEFGHIJKLMNOPQRSTUVWXYZ», где A=0, B=1… Y=24, Z=25.
- уровень (12)
- жизни (6)
- время (39)
Вычисляем:
Первая часть пароля:
(10545*39)mod 17576 = 411255 mod 17576 = 7007
7007 (10 СС) = 10,9,13 (26 СС)
Зеркально отображаем полученное значение:
10,9,13 =13,9,10
Вторая часть пароля:
((10545*39) + (14157*(12-1)) + (5145*6))mod 17576 = (411255+155727+30870)mod 17576 = 268
268 (10 СС) = 10,8 (26 СС)
Зеркально отображаем полученное значение:
10,8 = 8,10
Дописываем справа ноль:
8,10,0
Теперь кодируем получившиеся значения:
13,9,10,8,10,0 = NJKIKA
Интересный баг
В игре есть баг, с помощью которого можно получить бессмертие. Чтобы его активировать, нужно в EU версии ввести пароль с нулевым количеством жизней. Теперь принцу не страшны враги (главное — не убирать оружие). Но с активацией бага, игрок получает одну проблему. Если упасть с большой высоты, которая грозит потерей всех жизней, то ничего не произойдёт. Но если упасть с высоты, при которой у принца должна потратиться жизнь, то игра зависнет, а экран окрасится в красные тона.
Prince of Persia (SNES)
Вот и настало время поговорить о самой лучшей реализации первого персидского принца (по моему скромному мнению).
По сравнению со всеми предыдущими версиями, для SNES сделали более красочные локации, улучшили парирование, частично изменили начальные уровни и добавили много новых стадий (итого 20). А чтобы игрок не мучался, время увеличили до 120 минут (играй сколько влезет).
Теория
Пароль состоит из 7 позиций, каждая позиция состоит из 5 битов, итого 7*5= 35 битов. Эти биты сохраняют данные игровые параметры:
- уровень (1-20)
- затраченное на игру время (0-7200) (в секундах)
- жизни (0-15)
Теперь посмотрим из чего состоит сырой пароль:
(?(0),S(0),L(3),T(0),T(7)) (C1(0),S(1),L(2),T(1),T(6)) (C2(0),S(2),L(1),T(2),T(5)) (C3(0),S(3),L(0),T(3),T(4))
(C4(0),S(4),U(0),T(8),T(9)) (C4(1),T(10),T(11),T(12),T(13)) (C4(2),C4(3),C4(4),T(14),T(15))
* в скобках указан номер бита.
Обозначения
S — номер уровня ((1-20)-1) в двоичной C.C.
L — количество жизней (0-15) в двоичной C.C.
U — неиспользуемые биты.
? — всегда равен нулю.
T — затраченное на игру время (0-7200).
Время записывается в пароле, в соответствии со специальной формулой:
(время*7) + (5, если время mod60?0) + (5*((время div60)-1)) + рандом (0-6 + ((5, если время mod60=0) или (14534, если время div 7200=1)))
C1 = S(1) XOR S(4) XOR L(0) XOR L(1) XOR T(0) XOR T(1) XOR T(2) XOR T(5) XOR T(7) XOR T(8) XOR T(10) XOR T(13) XOR T(15) XOR U(0) XOR 1
C2 = S(1) XOR S(2) XOR S(3) XOR L(0) XOR L(2) XOR L(3) XOR T(1) XOR T(4) XOR T(5) XOR T(8) XOR T(9) XOR T(10) XOR T(12) XOR T(14) XOR T(15)
C3 = S(0) XOR S(1) XOR S(3) XOR L(2) XOR T(2) XOR T(3) XOR T(5) XOR T(6) XOR T(7) XOR T(8) XOR T(9) XOR T(11) XOR T(14) XOR U(0)
C4 = S(0),L(3),T(0),T(7)
+ S(1),L(2),T(1),T(6)
+ S(2),L(1),T(2),T(5)
+ S(3),L(0),T(3),T(4)
+ S(4),U(0),T(8),T(9)
+T(10),T(11),T(12),T(13)
+ 0, 0,T(14),T(15)
Кодирование
US/EU: «BTL3GY7Q9CVM4HZ8R+DWN5J12S!FXP6K».
JP: «AIQYEMU34BJRZFNVW5CKS1GOPX6DLT2H».
- уровень (15)
- жизни (13)
- время (95.00) или (5700 секунд)
- неиспользуемый бит активирован
Переводим значения в двоичную систему счисления:
Уровень = 15-1 =14 = 01110
Жизни = 13 = 1101
Вычисляем время:
Время = 7200-5700=1500
(1500*7) + (0, т.к. 1500 mod 60 = 0) + (5*(25-1)) + рандом (т.к. 1500 mod 60 = 0, то рандом = 0-6+5 = 0-11. Я выбираю рандом = 11.)
10500 + 120 + 11 = 10631 = 0010100110000111
Вычисляем контрольные суммы:
C1 = 1 XOR 0 XOR 1 XOR 0 XOR 1 XOR 1 XOR 1 XOR 0 XOR 1 XOR 1 XOR 0 XOR 1 XOR 0 XOR 1 XOR 1 = 0
C2 = 1 XOR 1 XOR 1 XOR 1 XOR 1 XOR 1 XOR 1 XOR 0 XOR 0 XOR 1 XOR 0 XOR 0 XOR 0 XOR 0 XOR 0 = 0
C3 = 0 XOR 1 XOR 1 XOR 1 XOR 1 XOR 0 XOR 0 XOR 0 XOR 1 XOR 1 XOR 0 XOR 1 XOR 0 XOR 1 = 0
C4 = 0111 + 1110 + 1010 + 1100 + 0110 +0101 + 0000 = 110110
Записываем получившийся пароль в двоичной С.С.:
(00111) (01110) (01010) (01100) (00110) (10101) (10100)
Записываем получившийся пароль в десятичной С.С.:
(7) (14) (10) (12) (6) (21) (20)
Теперь кодируем получившиеся значения:
US/EU: QZV475N
JP: 3NJZU1S
Prince of Persia 2: The Shadow & The Flame
Первая часть обрела огромную популярность. Выход сиквела был лишь вопросом времени. И через четыре года появилось продолжение. Но новая часть не сыскала бурных аплодисментов, которыми наградили первую часть. И портировали её на небольшое количество игровых платформ. А жаль! Я считаю, что вторая часть получилась лучше первой. Теперь принц путешествует не по однообразным тёмным локациям, а по целой Персии. Но хватит лирики, пора переходить к делу.
Игра обзавелась двумя портами, которые сохраняют игровой процесс с помощью паролей. Эти порты ужасны (лучше играйте в DOS версию). SNES версия получилась корявая: музыка дребезжащая, звуки противные, геймплей убит и ко всему этому, в игре вырезан 14 уровень, в котором должна состояться битва с Джаффаром.
Версия для Sega Genesis не лучше. Так как эту игру официально не выпустили, то я её смог увидеть только с помощью пиратского картриджа на Сегу. И каково? оказалось моё разочарование, когда я дошёл до 9 уровня и узнал, что из-за бага со статуей лошади, этот уровень непроходим. Игру можно пройти, но для этого нужен пароль на 10 уровень… а в книге паролей, этой игры не было.
Prince of Persia 2: The Shadow & The Flame (SNES)
Теория
Пароль состоит из 6 позиций, каждая позиция состоит из 4 битов, итого 6*4= 24 бита. Эти биты сохраняют данные игровые параметры:
US/EU versions:
- уровень (1-13)
- время (0-164)
- жизни (1-15)
Теперь посмотрим из чего состоит сырой пароль:
(S(3),S(2),S(1),S(0)) (L(3),L(2),L(1),L(0)) (T1(3),T1(2),T1(1),T1(0)) (T2(3),T2(2),T2(1),T2(0))
(C1(3),C1(2),C1(1),C1(0)) (C2(3),C2(2),C2(1),C2(0))
Обозначения
S — (уровень — 1) в двоичной С.С.
L — количество жизней (1-15) в двоичной С.С.
T1 — 1 значение (0-15) в двоичной С.С.
T2 — 2 значение (0-15) в двоичной С.С.
1 значение — количество единиц времени (число десятков из 1 значения переходит во 2 значение).
2 значение — количество десятков времени (число десятков из 2 значения переходит в количество сотен).
C1 = (сумма позиций с 1 по 3) mod16
C2 = ((сумма позиций с 1 по 3) div16) + 4 позиция
Кодирование
Символы в позициях принимают значения «BCDFGHJKLMNPRTVW», где B=0… W=15.
Особенности сохранения времени и работоспособности пароля:
Если подумать, то всё просто — одна позиция отвечает за время mod10, а другая за время div10 и максимальное количество времени равняется 99. Но не всё так просто. В пароле не проверяется максимальное значение единиц и десятков. Что это значит? В пароле можно установить количество десятков и единиц от 0 до 15. Если я создам пароль, где количество единиц равно 15, то единиц будет 5, а 1 перейдёт в количество десятков, анологично, если я создам пароль, где количество десятков равно 15, то десятков будет 5, а 1 перейдёт в количество сотен.
Получается, максимальное количество времени равняется:
150
+015
=
165
Но выше, я уже описал, что максимальное значение = 164. А почему? Это происходит из-за контрольной суммы. Если С2?16, то пароль не будет работать. Этот аспект я объясню чуть позже, а сейчас перейдём к генерации пароля (чтобы понять дальнейшее повествование, я советую прочитать пример генерации пароля).
- уровень (2)
- жизни (1)
- время (163)
Переводим значения в двоичную систему счисления:
Уровень = 2-1 =1 = 0001
Жизни = 1= 0001
Вычисляем время:
163= 150+13
1 значение = 13 = 1101
2 значение = 15 = 1111
Записываем сырой пароль и вычисляем 2 контрольные суммы:
(0001) (0001) (1101) (1111) (****) (****)
C1 = 0001+0001+1101 = 1111
C2 = (0001+0001+1101)mod16 + 1111 = 0000 + 1111 = 1111
(0001) (0001) (1101) (1111) (1111) (1111)
Записываем получившийся пароль в десятичной С.С.:
(1) (1) (13) (15) (15) (15)
Теперь кодируем получившиеся значения:
CCTWWW
Итог
Я создал пароль CCTWWW. Если увеличить уровень на 1, то пароль не будет работать, т.к. C2 станет равна 16. Неработающий пароль будет иметь вид: DCTWBB. А теперь проверим игру «на вшивость». Второй уровень очень короткий, поэтому его можно пройти без потери времени. Если я пройду уровень, какой пароль выдаст мне игра?
Вдруг в системе паролей есть секрет, который я не раскрыл? А что если…
… вот зараза. В игре не только геймплей ужасный, но и система паролей недоделанная.
Prince of Persia 2: The Shadow & The Flame (Sega Genesis)
Теория
Пароль состоит из 5 позиций. Эти позиции сохраняют данные игровые параметры:
- уровень (1-14)
- время (0-99)
- жизни (1-12)
Генерация
1 позиция = (уровень) или (уровень (1-7) +15)
2 позиция = (время mod10) или (время mod10 + 10) или (время mod10 (0-2) + 20)
3 позиция = (1 позиция + 2 позиция + 4 позиция + 5 позиция) mod23
4 позиция = (время div10) или (время div10 + 10) или (время div10 (0-2) + 20)
5 позиция = (жизни -1) или (жизни (1-11) + 11)
Кодирование
Символы в позициях принимают значения «HFMGRANBPWTEIZVQDLYSKCX», где H=0, F=1… C=21, X=22.
- уровень (11)
- жизни (10)
- время (92)
Вычисляем:
Первый шаг:
1 позиция = уровень сохраняется по одной из двух формул. Так как уровень больше 7, то сохранить данные можно только по первой формуле (11).
2 позиция = время сохраняется по одной из трёх формул. 92 mod10 = 2. Это значение можно закодировать по любой формуле и я выбираю третью (2+20 = 22)
3 позиция = 0
4 позиция = время сохраняется по одной из трёх формул. 92 div10 = 9. Это значение можно закодировать только по первой и второй формуле, и я выбираю вторую (9+10 = 19)
5 позиция = жизни сохраняются по одной из двух формул. Это значение можно закодировать по любой формуле и я выбираю вторую (10+11 = 21).
Второй шаг:
1 позиция = 11
2 позиция = 22
3 позиция = (11 + 22 + 19 + 21)mod 23 = 4
4 позиция = 19
5 позиция = 21
Теперь кодируем получившиеся значения:
EXRSC
Заключение
Вот и подошёл список игр к концу. Ну что ж, удачи, спасибо за прочтение.
Комментарии (25)
pchelintsev_an
05.10.2016 23:50+2Одна из любимых игр. У меня вопрос. Как Вы узнали, что именно так генерируются пароли? Можно ли привести ссылки на ресурсы, где более подробно разбирается генератор на основе реверс-инжиниринга игры? Очень хочется вкусить ассемблер любимой игры.
LoadRunner
06.10.2016 08:25Пример генерации паролей — это хорошо. Но почему нет примера расшифровки пароля?
Особенно интересно для случаев, где надо выбирать одну из нескольких формул. Коллизий не будет?awlvita
06.10.2016 16:25Коллизий не будет, если правильно составить алгоритм дешифрации.
Но почему нет примера расшифровки пароля?
Я не вижу в этом смысл. Хотя, весьма интересно найти каракули в блокнотике и понять: «А какие данные сохраняет этот пароль?»LoadRunner
06.10.2016 17:19Ну я вижу в этом смысл, как демонстрацию того, что алгоритм генерации паролей работает в обе стороны, а не как в архиваторе Бабушкина.
awlvita
06.10.2016 18:01Если алгоритм работает в одну сторону, то должен работать и в обратную. Или я ошибаюсь?
LoadRunner
06.10.2016 20:46Зависит от алгоритма. Но суть в другом — в демонстрации, как он работает именно в обратную сторону. Как он из набора символов интерпретируется в жизни-время-уровень. Это ведь тоже интересный момент в генерации паролей.
pchelintsev_an
06.10.2016 18:11А ещё секреты в игре есть?
awlvita
06.10.2016 18:16В какой именно версии?
Miay
26.01.2017 21:29Переболел я уже соц. сетями, но тут появился телеграмм, который полностью дублирует любую соц. сеть :(
awlvita
06.10.2016 19:32Из секретов, я знаю только специальные чит-коды. А из багов, я знаю глюк на третьем уровне:
pchelintsev_an
06.10.2016 20:27+1Обзор исходного кода Prince of Persia для Apple II (три статьи):
Часть 1 (введение)
Часть 2 (загрузчик)
Часть 3 (объяснение кода)
Техническая дока от разработчика
Ссылка на сырцы (на ассемблере)
claymen
09.10.2016 16:20+2Как раз на днях рассказывал напарнику, как в детстве летом у бабушки в деревне по вечерам на ч/б телике играли в приставку, в частности в принца, и что были коды и что я пытался их вычислять, путем сравнения нескольких кодов, так например мне удалось сделать код на первый уровень но с увеличенным временем на 150%.
Надо заметить что было это ещё до школьного курса программирования, и никакх познаний, особенно битовых сдвигах и кодах символов небыло…
Всё так принц персии шедевр.
На ютубе есть ролик с рассказом как делалась игра, движения персонажа снимали на камеру, процесс переноса не вспомню, но поэтому он движется так правильно.
printerresetter
Народу видно занятся нечем, разбирает всякую ерунду. Скажите, какая от этого польза?
awlvita
И не поспоришь. Как таковой пользы нет.
kuber
Вы просто слишком молоды. Я в свое время потратил большое количество времени, чтобы понять как генерируются пароли в данной игре. И еще больше времени потратил на её прохождение.
printerresetter
36 лет, наверно, я слишком стар дабы тратить свое рабочее вреям на разбор тривиальных алгоритмов.
lookid
Если брать конкретную задачу, то это похоже на генерацию hash-кода.
pewpew
Смотря кому. Если вам, то вероятно никакой.