SF21
 
   Главная    Наш клуб    Творчество    Оф. игры    Фан. проекты    Почитать    Галерея    Мультимедиа    Прочее ВконтактеTwitterSteam
SF21 / Творчество / Уроки / Ромхакинг / Редактирование исходного кода: делаем отдельную мелодию для бонуса ускорения

Редактирование исходного кода:
Делаем отдельную мелодию для бонуса ускорения

Текст и листинги кодов: Jet
Последняя редакция от 09.07.09.



     Внимание! Данное руководство предполагает, что у вас уже есть определённые навыки и/или познания в области редактирования исходных кодов, в частности, S1 Hivebrain Disassembly (исходный код игры Sonic the Hedgehog от Hivebrain). Знание английского языка также приветствуется.

Вступительные замечания

     В первом уроке мы рассмотрим, как заменить стандартное ускорение музыки при взятии бонуса ускорения на воспроизведение отдельной мелодии. Вам понадобится полностью готовый к редактированию исходный код игры Sonic the Hedgehog с необходимыми инструментами и краткой инструкцией на русском яхыке, запакованные в единый архив Sonic 1 (Split and Text by Hivebrain)(ASM68K)(Rus) 1.1. Мы будем работать с исходным кодом игры, так что никакие дополнительные утилиты, кроме тех, что есть в архиве, нам не понадобятся. Рекомендуем Вам не использовать для редактирования стандартный Блокнот Windows. Он работает лишь с кодировкой Win-1251, очень неудобен и зачастую портит исходники и скрипты. К тому же его система поиска оставляет желать лучшего. Лучше возьмите любой другой, желательно без лишних наворотов, но с поддержкой разных кодировок. Например, неплохой текстовый редактор AkelPad, вложенный в упомянутый выше архив.

Итак, поехали!

     Найдите в файле sonic1.asm процедуру Obj2E_ChkShoes (используйте поиск по файлу, нажав сочетание клавиш Ctrl + F). Указанное сочетание может встречаться в нескольких местах, так что продолжайте поиск, пока не увидите:

Листинг 1
Obj2E_ChkShoes:
		cmpi.b	#3,d0		; does monitor contain speed shoes?
		bne.s	Obj2E_ChkShield
		move.b	#1,($FFFFFE2E).w ; speed up the	BG music
		move.w	#$4B0,($FFFFD034).w ; time limit for the power-up
		move.w	#$C00,($FFFFF760).w ; change Sonic's top speed
		move.w	#$18,($FFFFF762).w
		move.w	#$80,($FFFFF764).w
		move.w	#$E2,d0
		jmp	(PlaySound).l	; Speed	up the music

     Первые две инструкции отвечают за проверку содержимого монитора (например, жизнь, непобедимость, ускорение). Их не трогаем. Далее идёт строка move.b #1,($FFFFFE2E).w – она неправильно откомментирована создателем исходника, на самом деле это флаг (указатель) этого Power-up’a (бонуса). Свойства самого бонуса (следующие четыре строки) оставляем как есть. Наконец, последние две инструкции и вызывают ускорение музыки, они то нам и нужны! Разберем их поподробнее. Строка, приведенная в листинге 1.1, помещает значение E2 в регистр d0 и этим задаёт номер мелодии, которую нужно проиграть, в данном случае E2 (E2 – это процедура ускорения музыки, хотя и вызывается она как мелодия; в меню Sound Test она конечно же не видна). А инструкция, указанная в листинге 1.2, вызывает процедуру воспроизведения музыки PlaySound, которая проигрывает музыку по номеру, заданному в предыдущей строке.

Листинг 1.1
		move.w	#$E2,d0

Листинг 1.2
		jmp	(PlaySound).l	; Speed up the music

     Напрашивается следующий вывод: если нам надо проиграть мелодию, мы должны написать вот это:

Листинг 2
		move.w	X,d0            ; отправка номера мелодии
		jmp	(PlaySound).l   ; вызов процедуры проигрывания музыки

     Вместо значка "Х" в листинге 2 должен стоять идентификатор мелодии; если этот идентификатор однозначный и содержит только цифру, пишем #[знак] (пример: #2), если содержит букву или двузначный – #$[знаки] (например, #$A6, #$C). После знака «точка с запятой» может указываться любой комментарий – такие текстовые блоки, в отличие от остального кода, программой игнорируются и служат исключительно для удобства разработчика (так удобнее и быстрее ориентироваться в коде, читая оставленные ранее подсказки).
     Теперь, когда мы разобрались, заменим E2 на любую свою мелодию. Возьмем музыку 91; тогда у нас должно получиться примерно следующее:

Листинг 2.1
		move.w	#$91,d0         ; комментарий: было E2, стало – 91
		jmp	(PlaySound).l	; играть мелодию 91!

     Сохраним файл sonic1.asm. Теперь нужно собрать (скомпилировать) ром (о том, как это сделать, читайте файл README.txt, вложенный в скачанный вами архив с разбивкой рома (в том же архиве лежал только что отредактированный вами файл sonic1.asm)). Запустим новоиспеченный хак на эмуляторе...

Непредвиденная ошибка

     Получилось! Теперь играет новая мелодия! Но что это?! О нет, действие бонуса кончилось, Соник бегает как обычно, но музыка не прекратилась! Надо исправлять. Ищем процедуру Obj01_ChkShoes:

Листинг 3
Obj01_ChkShoes:
		tst.b	($FFFFFE2E).w	; does Sonic have speed	shoes?
		beq.s	Obj01_ExitChk	; if not, branch
		tst.w	$34(a0)		; check	time remaining
		beq.s	Obj01_ExitChk
		subq.w	#1,$34(a0)	; subtract 1 from time
		bne.s	Obj01_ExitChk
		move.w	#$600,($FFFFF760).w ; restore Sonic's speed
		move.w	#$C,($FFFFF762).w ; restore Sonic's acceleration
		move.w	#$80,($FFFFF764).w ; restore Sonic's deceleration
		move.b	#0,($FFFFFE2E).w ; cancel speed	shoes
		move.w	#$E3,d0
		jmp	(PlaySound).l	; run music at normal speed

     Эта процедура работает в качестве таймера и возвращает исходные свойства ежа по истечении времени (то есть убирает действие бонуса ускорения). Нас интересуют только последние две строки, возвращающие музыку к нормальной скорости. Тут простая замена идентификатора не поможет – ведь по окончании действия бонуса нам нужно вернуть исходную мелодию этапа, а она в каждой зоне разная! До нашей предыдущей замены мелодия этапа просто ускорялась (идентификатор E2, помните?), а указанный здесь идентификатор E3 возвращает ускоренной музыке нормальный темп. Но мы заменили ускорение темпа на совсем другую мелодию. Что же делать?
     Ответ на вопрос содержится в самом исходном коде. Ведь подобный принцип замены мелодии (а не ускорения уже играющей) используется в бонусе неуязвимости! Идем чуть выше, к Obj01_ChkInvin:

Листинг 4
Obj01_ChkInvin:
		tst.b	($FFFFFE2D).w	; does Sonic have invincibility?
		beq.s	Obj01_ChkShoes	; if not, branch
		tst.w	$32(a0)		; check	time remaining for invinciblity
		beq.s	Obj01_ChkShoes	; if no	time remains, branch
		subq.w	#1,$32(a0)	; subtract 1 from time
		bne.s	Obj01_ChkShoes
		tst.b	($FFFFF7AA).w
		bne.s	Obj01_RmvInvin
		cmpi.w	#$C,($FFFFFE14).w
		bcs.s	Obj01_RmvInvin
		moveq	#0,d0
		move.b	($FFFFFE10).w,d0
		cmpi.w	#$103,($FFFFFE10).w ; check if level is	SBZ3
		bne.s	Obj01_PlayMusic
		moveq	#5,d0		; play SBZ music

     Здесь нужную музыку возвращают последние пять строчек. Копируем их и вставляем в конец процедуры Obj01_ChkShoes вместо последних двух. Результат:

Листинг 5
Obj01_ChkShoes:
		tst.b	($FFFFFE2E).w	; does Sonic have speed	shoes?
		beq.s	Obj01_ExitChk	; if not, branch
		tst.w	$34(a0)		; check	time remaining
		beq.s	Obj01_ExitChk
		subq.w	#1,$34(a0)	; subtract 1 from time
		bne.s	Obj01_ExitChk
		move.w	#$600,($FFFFF760).w ; restore Sonic's speed
		move.w	#$C,($FFFFF762).w ; restore Sonic's acceleration
		move.w	#$80,($FFFFF764).w ; restore Sonic's deceleration
		move.b	#0,($FFFFFE2E).w ; cancel speed	shoes
		moveq	#0,d0
		move.b	($FFFFFE10).w,d0
		cmpi.w	#$103,($FFFFFE10).w ; check if level is	SBZ3
		bne.s	Obj01_PlayMusic
		moveq	#5,d0		; play SBZ music

     Опять сохраняем файл, компилируем ром и тестируем его на эмуляторе. Работает! Однако есть некоторые баги (ошибки в программе). О том, что это за баги и как их исправить, мы поговорим чуть ниже.

Ловим баги!

     М-мда. Из-за того, что теперь в игре два бонуса с одинаковой системой изменения музыки, могут вылезти неприятные глюки. Посмотрим, как они работают одновременно. В Spring Yard Zone Act 3 есть место, где лежат два монитора, один с непобедимостью, другой с ускорением – как раз то, что нужно (этот тайник находится на огромном двойном трамплине справа наверху):


     Разбейте сначала монитор с неуязвимостью, затем через 3-4 секунды – монитор c ускорением и ждите. Через определенное время музыка скорости прекратится и начнется мелодия текущего уровня (потому что кончилась неуязвимость и программа заменила мелодию), хотя Соник еще будет бегать быстро (как раз эти самые 3-4 секунды). Через этот же промежуток времени музыка этапа перезапустится (на этот раз по той причине, что закончился бонус ускорения и по его окончании запустилась мелодия этапа). Естественно, тот же эффект можно наблюдать, если точно так же разбить эти мониторы, но в противоположном порядке.
     Разумеется, можно скомпоновать уровень так, чтоб два бонуса не могли работать одновременно – просто расположить их подальше друг от друга. Но так мы теряем свободу в создании своего хака, да и чем мы хуже иностранных ромхакеров, а? Давайте уже все делать на совесть! Ведь настоящему ромхакеру (пусть и начинающему) нужно уметь решать возникающие проблемы. Компромиссов быть не может.
     Итак, в двух местах используется один и тот же кусок кода; так почему бы не оптимизировать его? В процедуре Obj01_ChkInvin вырежьте последние пять строк кода, а в Obj01_ChkShoes их просто удалите. Вставьте ранее вырезанный текст после Obj01_ChkShoes и напишите перед ним Obj01_PlayMusic2:. Это название вашей новой процедуры по возвращению музыки! Вырежьте процедуру Obj01_PlayMusic и вставьте ее между Obj01_PlayMusic2 и Obj01_ExitChk. Это позволит избежать досадных ошибок при компиляции хака. Теперь самое интересное: программирование условий. Это очень просто.

Листинг 6
		cmpi.b	#1,($FFFFFE2E).w ; ботинки есть? (1)
		bne.s 	Obj01_PlayMusic2 ; если нету, вернуть музыку текущего уровня (2)

     Код, приведенный в листинге 6, означает, что если выполняется условие, описанное в строке (1), процессор выполнит инструкцию (2). В противном случае (если условие не выполняется) строка (2) пропускается и выполняется код после нее. Этот код необходимо вставить в конце Obj01_ChkInvin. Для Obj01_ChkShoes инструкции такие:

Листинг 7
		cmpi.b	#1,($FFFFFE2D).w ; непобедимость есть?
		bne.s 	Obj01_PlayMusic2 ; если нет, отключить музыку
		bra.s	Obj01_ChkInvin   ; если есть, продолжить проверки

     Их тоже вставьте в конец соответствующей процедуры. Кстати, процедуру Obj01_RmvInvin можете стереть, она не нужна. Замените каждую из строк bne.s Obj01_RmvInvin и bcs.s Obj01_RmvInvin на move.b #0,($FFFFFE2D).w ; cancel invincibility. Итоговый вариант кода приведен в листинге 8.

Листинг 8
Obj01_ChkInvin:
		tst.b	($FFFFFE2D).w	; does Sonic have invincibility?
		beq.s	Obj01_ChkShoes	; if not, branch
		tst.w	$32(a0)		; check	time remaining for invinciblity
		beq.s	Obj01_ChkShoes	; if no	time remains, branch
		subq.w	#1,$32(a0)	; subtract 1 from time
		bne.s	Obj01_ChkShoes
		tst.b	($FFFFF7AA).w
		move.b	#0,($FFFFFE2D).w ; cancel invincibility
		cmpi.w	#$C,($FFFFFE14).w
		move.b	#0,($FFFFFE2D).w ; cancel invincibility

		cmpi.b	#1,($FFFFFE2E).w ; ботинки есть?
		bne.s 	Obj01_PlayMusic2 ; если нету, вернуть музыку текущего уровня
		
Obj01_ChkShoes:
		tst.b	($FFFFFE2E).w	; does Sonic have speed	shoes?
		beq.s	Obj01_ExitChk	; if not, branch
		tst.w	$34(a0)		; check	time remaining
		beq.s	Obj01_ExitChk
		subq.w	#1,$34(a0)	; subtract 1 from time
		bne.s	Obj01_ExitChk
		move.w	#$600,($FFFFF760).w ; restore Sonic's speed
		move.w	#$C,($FFFFF762).w ; restore Sonic's acceleration
		move.w	#$80,($FFFFF764).w ; restore Sonic's deceleration
		move.b	#0,($FFFFFE2E).w ; cancel speed	shoes

		cmpi.b	#1,($FFFFFE2D).w ; непобедимость есть?
		bne.s 	Obj01_PlayMusic2 ; если нету, заткнуть музыку
		bra.s	Obj01_ChkInvin ; если есть, продолжить проверки 
Obj01_PlayMusic2:
		moveq	#0,d0
		move.b	($FFFFFE10).w,d0
		cmpi.w	#$103,($FFFFFE10).w ; check if level is	SBZ3
		bne.s	Obj01_PlayMusic
		moveq	#5,d0		; play SBZ music
		jmp	Obj01_ChkInvin

Obj01_PlayMusic:
		lea	(MusicList2).l,a1
		move.b	(a1,d0.w),d0
		jsr	(PlaySound).l	; play normal music

Obj01_ExitChk:
		rts

     Вроде мелочь, а сколько пришлось возиться! Все! Компилируем, проверяем, радуемся, экспериментируем и ждем следующих мануалов по редактированию исходных кодов сониковских ромов!

© Jet, 2009.


SF21 / Творчество / Уроки / Ромхакинг / Редактирование исходного кода: делаем отдельную мелодию для бонуса ускорения
Copyright © Slesarev Maxim and SF21 Team 2004-2011. Sonic the Hedgehog and all related characters are copyright © SEGA Corporation and Sonic Team. Права на размещенные материалы принадлежат их авторам. Портал основан 22 ноября 2004 года.

Баннеры