Digger. Становление. часть 3

Давай раскомментим немножко и глянем чо и как.
Опа! Всё падает, и падает жестоко. Переменные – где угодно, но не по своим адресам… Да что ж такое… как? Почему??!
Дикая копанина, ступор. Blade, ну как так – держи пример, вериейблы хз где!
Но где-то на краю сознания крутится, что кроме самого большого блока есть ещё мелкие.


… Привет, rel старта С файлов.
Старт С кода в сдцц знаменуется переносом переменных и констант кода в свою ОТДЕЛЬНУЮ область памяти.
Фейспалм, чёрт, фак, почему… ну, смысл в этом видать есть, но…


Старт С кода должен начинаться с вызова функции релокации переменных, процедура которого отдельно сохраняется бинарником с адреса #100, который я до этого не учитывал.
И спасибо Blade что указал на это! Ибо я бы ещё сутки это дебажил и пытался додуматься, почему адреса переменных – НЕ ТЕ. Мысль вертелась на поверхности, но не присаживалась на ум.

Сообщение Blade реально сдвинуло меня дальше. Это быле ещё одна возня с компилером, и, похоже — она уже была последняя.

Теперь я полностью в С и в asm.

Visual studio code — для С, Sublime text + z80 – для асм, поехали.

Долгое пиливо обеих частей показывает, что почти минутное ожидание компиляции С кода – не кайф. Давай запилим в начале набор джамповдля асм функций, после которого будут уже их коды? С компилер сохранит точки входа… Дык это ж кернель из 93-его! :)
Подход помогает. Отладка асм становится быстрее в 50 раз.

Итак, некоторые внутренности.
Для реально «быстрой» работы в узких участках диггер использовал х86 асм для процедур работы со спрайтами. Исходники в комплекте, асм понятен точно так-же как и этот их С код :)

База есть. Вызов функций – понятен. Передача параметров происходит через стек.
Сначала идёт адрес возврата, потом – крайне левый параметр своего типа, и так до последнего параметра. Снимай, юзай…
Особенностью оказалось – использование своих регистров — в первую очередь IX, похоже что используется так-же IY (у себя не заметил, но отмечал использование в других проектах), и обширное использование стека для хранения значений переменных внешних относительно вызываемой функции.
То есть вообще часто жесть со стеком :)
ld	hl,#0x0000
	push	hl
	ld	hl,#0x0f04
	push	hl
	ld	a,(_image_0)
	push	af
	inc	sp
	xor	a, a
	push	af
	inc	sp
	call	_sp_chnge
	ld	hl,#6
	add	hl,sp
	ld	sp,hl 


Ок, точки вызова есть, давай аккуратно отработаем. Что для этого надо – уже понятно.
Пушить переменные много нельзя, IX сохрани, call – это тот-же push, можешь насрать в область переменных. Себе дороже, в общем.

Для сложных подпрограмм юзаю следующее:
CHECK_POINT_proc
		ld hl,#2
		add hl,sp
		ld (restore_stack+1),sp
		ld sp,my_stack
 		ld c,(hl)	; x
		inc hl
		…

а потом указываю стек и выхожу.

Следующей болячкой было – поиск где собственно отрабатывает интересующий меня С код.
Радует что это можно увидеть в генерируемых sdcc файлах. Неуказанные в коде (но указанные в определении) функции по умолчанию являются CALL 0000, что очень радует весьма.
Кроме того – абсолютное засилье переменных типа int ВЕЗДЕ. Понятная для х86 структура, но тяжёлая для 8бит z80.
Вносим typedef unsigned char u8; в определения *.H, вперёд… аккуратно…
результат изменений отлично виден после компиляции в файле main.asm

От 150 кб С кода получаем 350 кб странного астма в тхт. Но – отлично что можно видеть компилируемые строки С кода в каментах.

Дальше началась уже работа в тихую. Основные первоначальные грабли уже все на лице отпечатались, начался нормальный процесс разработки.

Первоначальные 56к свелись в 30кб кода.

Основные переделки:
— х86 асм используется как для вывода, так и для вычислений коллизий спрайтов. Результатом этой процедуры является 16-ти битное значение, каждый бит которого говорит о том, с каким именно из 16 обьектов на экране произошло пересечение по координатам.
— В С коде дописана процедура ввода имени после гибели диггера (да, так уже удобнее ;) )
— Подсчёт очков происходит через переменную типа Long. Пришлось переделывать исходный код для вывода очков, тоже С.
Да и вообще хороший язык таки :)


Может как-то стандартную графику ну хоть немного улучшить? Er, поможешь?
Чо делаем – в игре юзается 16 спрайтов обьектов, разделяемых на 5 групп –
Диггер, мешки, насекомые (баги), бонус и взрыв. Каждому назначаем свою палитру, отдельно – палитру на бекграунд… ;)

Так, музыку бы надо. Да и спец эффекты нужны. В оригинале — программируется бипер. мда.
Беру отличный AYfx, от Shiru, немного правлю — складываем все звуки в канал В.
Договариваемся с Nik-O, и Олег пишет музыку, которая не использует центральный канал :) А так же музыку для начального меню.

Blade подкинул интересную мысль сделать версию игры во фрейм. Скорость оригинальной игры — 4 фрейма.
Вчера фреймовость уже готова. Плавно, красиво :)

В общем, результат всей этой возни мы увидим завтра, на WGC.

PS: Код вполне может быть скомпилен под 128к, если будут герои. Я не герой :)

4 комментария

avatar
Я так понимаю, ты спрайты взял готовые, из исходника?
А палитру как конвертировал?
avatar
нашлись файлы gif с оригинальными спрайтами, все спрайты полностью, для MGA
как и начальный экран.

в оригинальной игре спрайты лежали как массивы: точек и маска. смотрел ехе диггера твоим вьювером спрайтов в своё время :)
а экран был слегка пожат.
avatar
версией vga?
avatar
тогда не было вга. сга и мга.
мга симпатичнее выглядит гораздо, при тех же доступных 4х цветах на точку
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.