S1 Hacking Studio 2

Справочное руководство

S1 Hacking Studio использует Hivebrain's 2005 Disassembly с компилятором ASM68K. Оригинальный дизасембл был частично изменен для нужд программы, например, некоторые маппинги вынесены в файлы, некоторые данные переконвертированы из формата ASM в BIN. Дизасембл также был усовершенствован и дополнен, добавлено несколько макросов для удобства, добавлено много новых комментариев, множество лейбелов были названы смысловыми именами (до этого у них были имена loc_XXXX или sub_XXXX).

Основные изменения кода

В оригинальный код игры были внесены некоторые изменения и усовершенствования. Сделано это, во-первых, для нужд S1 Hacking Studio, во-вторых, для улучшения самой игры.

Основные усовершенствования

Макросы и их использование

В обновленный дизасембл S1HS добавилось 4 новых макроса. Все макросы теперь находятся в файле macro.asm.

vram

Аргументы:
1 — адрес VRAM
2 — регистр или адрес, куда будет записан полученный код доступа

Макрос для получения доступа к VRAM на запись. Второй аргумент необязателен, если он не указан, то код доступа будет послан сразу в VDP Control Port (адрес $C00004). Вы также можете записать его в регистр или в RAM M68K, и получить доступ позже, послав содержимое регистра в $C00004.

raise

Аргументы:
1 — код ошибки
2 — роутина для обработки ошибки
3 — если существует, прибавляет 2 к указателю стека

Специфический макрос для векторов ошибок, дабы сэкономить размер кода. Вам вряд ли понадобится этот макрос, так как большинство ошибок им уже обрабатывается. Так что забудьте о нем, как о страшном сне.

theld, tpress

Аргументы:
1 — перечень кнопок
2 — адрес битового поля с состоянием кнопок

Эти два макроса проверяют нажаты ли или удерживаются заданные кнопки. Они призваны упростить жизнь и избавить кодеров от нужды постоянно проверять индексы и значения для нужных им кнопок. Все кнопки объявляются ввиде констант с их именами, так что в первом аргументе вы можете сразу писать их имена, например, C или Start. Если вам необходимо проверить несколько кнопок, просто перечислите их, разделяя знаками + или |, например: A+B+C.

Второй аргумент - битовое поле, которое нужно проверить. В нем-то и прописано, какие кнопки активны. В Sonic 1 предусмотрены два таких поля, которые в макросе определены именами Joypad и SonicControl. Первое всегда отображает состояние джойпада и обновляется постоянно. Второе отвечает за управление Соником, оно обычно просто дублирует кнопки джойпада. Однако, поле SonicControl отличается тем, что иногда способно блокироваться, и перестает получать нажатия кнопок с джойпада, например, если не нужно больше, чтобы игрок управлял Соником. В режиме демо-уровней, это поле также заблокировано и получает нажатия кнопок из записанных прохождений. Если вы пишете код для Соника, лучше всего вторым аргументом указывать SonicControl.

После выполнения макросов можно использовать условные переходы. BEQ переходит, если ни одна из заданных кнопок не нажата, BNE срабатывает, если хотя бы одна из перечисленных кнопок нажата:

	tpress	A+B+C,(SonicControl)	; нажаты ли A, B или C?
	beq.s	XXXXXXX			; если нет, переходим

Конфигурация дизасембла

В зависимости от настроек S1HS требуется помимо файлов изменять или добавлять код в файле sonic1.asm, например, если в программе поставлен флажок на Spin Dash'е, требуется добавить его код в sonic1.asm.

Для этого был введен файл config.asm, описывающий часть выбранных в S1HS настроек, в зависимости от которых потом потребуется изменить код. В файле содержится список констант и переменных с определенным значениями. Они при компиляции кода будут влиять на то, какой код добавлять и изменять. Константы и переменные имеют вот такой формат:

Константа	equ	Значение
Переменная	=	Значение

Условия, в зависимости от которых вставлять опредленный код описываются в самом же sonic1.asm с помощью директивы if.

	if (условие)
		; код, который нужно вставлять, если условие верно
	esle
		; код, вставляемый если условие неверно
	endc

В других случаях, например с ударами боссов, условий не требуется, нужно только подставить в строку значение переменной, для этого вместо числа просто пишется значение переменной, например:

	move.b  #var_BHits_GHZ,$21(a0)

Аннотации в коде

В дизасембле S1HS было аннотировано огромное количество кода и исправлены ошибки, неточные названия лейбелов и комментарии оригинального Hivebrain's 2005 Disassembly.

Вот пример плохо-комментированной суброутины в оригинальном дизасембле:

loc_177E6:
		move.b	$3F(a0),d0
		jsr	(CalcSine).l
		asr.w	#6,d0
		add.w	$38(a0),d0
		move.w	d0,$C(a0)
		move.w	$30(a0),8(a0)
		addq.b	#2,$3F(a0)
		cmpi.b	#8,$25(a0)
		bcc.s	locret_1784A
		tst.b	$22(a0)
		bmi.s	loc_1784C
		tst.b	$20(a0)
		bne.s	locret_1784A
		tst.b	$3E(a0)
		bne.s	Obj3D_ShipFlash
		move.b	#$20,$3E(a0)	; set number of	times for ship to flash
		move.w	#$AC,d0
		jsr	(PlaySound_Special).l ;	play boss damage sound

Obj3D_ShipFlash:
		lea	($FFFFFB22).w,a1 ; load	2nd pallet, 2nd	entry
		moveq	#0,d0		; move 0 (black) to d0
		tst.w	(a1)
		bne.s	loc_1783C
		move.w	#$EEE,d0	; move 0EEE (white) to d0

loc_1783C:
		move.w	d0,(a1)		; load colour stored in	d0
		subq.b	#1,$3E(a0)
		bne.s	locret_1784A
		move.b	#$F,$20(a0)

locret_1784A:
		rts

Эта же суброутина в обновленном дизасембле:

; This routine does the main ship stuff

Obj3D_ShipProcess:
		; Move ship slightly up and down during the flight
		move.b	$3F(a0),d0	; Y-amplitude
		jsr	(CalcSine).l
		asr.w	#6,d0		; d0 contains sine
		add.w	$38(a0),d0	; add secondary Y-pos to d0
		move.w	d0,$C(a0)	; and we've got Y-pos with the amplitude
		move.w	$30(a0),8(a0)
		addq.b	#2,$3F(a0)	; reduce the amplitude
		
		; Touch repsonse stuff
		cmpi.b	#8,$25(a0)	; is routine more or equals to 8?
		bcc.s	locret_1784A	; if yes, branch
		tst.b	$22(a0)		; was boss defeated?
		bmi.s	Obj3D_ShipGone	; if yes, branch
		tst.b	$20(a0)		; is touch response zero?
		bne.s	locret_1784A	; if not, branch
		tst.b	$3E(a0)		; is flashes counter zero?
		bne.s	Obj3D_ShipFlash	; if not, branch
		move.b	#$20,$3E(a0)	; set number of	times to flash
		move.w	#$AC,d0
		jsr	(PlaySound_Special).l ;	play boss damage sound

Obj3D_ShipFlash:
		lea	($FFFFFB22).w,a1 ; load	2nd pallet, 2nd	entry
		moveq	#0,d0		; move 0 (black) to d0
		tst.w	(a1)		; is colour in pallete black?
		bne.s	loc_1783C	; if not, branch
		move.w	#$EEE,d0	; move 0EEE (white) to d0

loc_1783C:
		move.w	d0,(a1)		; apply colour stored in d0
		subq.b	#1,$3E(a0)	; subtract 1 from flashes counter
		bne.s	locret_1784A	; if flashes counter is not zero, branch
		move.b	#$F,$20(a0)	; restore touch responsibility

locret_1784A:

Вот лишь неполный список аннотированных роутин и блоков кода: