Digger. Становление. часть 3
Давай раскомментим немножко и глянем чо и как.
Опа! Всё падает, и падает жестоко. Переменные – где угодно, но не по своим адресам… Да что ж такое… как? Почему??!
Дикая копанина, ступор. Blade, ну как так – держи пример, вериейблы хз где!
Но где-то на краю сознания крутится, что кроме самого большого блока есть ещё мелкие.
… Привет, rel старта С файлов.
Старт С кода в сдцц знаменуется переносом переменных и констант кода в свою ОТДЕЛЬНУЮ область памяти.
Фейспалм, чёрт, фак, почему… ну, смысл в этом видать есть, но…
Старт С кода должен начинаться с вызова функции релокации переменных, процедура которого отдельно сохраняется бинарником с адреса #100, который я до этого не учитывал.
И спасибо Blade что указал на это! Ибо я бы ещё сутки это дебажил и пытался додуматься, почему адреса переменных – НЕ ТЕ. Мысль вертелась на поверхности, но не присаживалась на ум.
Сообщение Blade реально сдвинуло меня дальше. Это быле ещё одна возня с компилером, и, похоже — она уже была последняя.
Теперь я полностью в С и в asm.
Visual studio code — для С, Sublime text + z80 – для асм, поехали.
Долгое пиливо обеих частей показывает, что почти минутное ожидание компиляции С кода – не кайф. Давай запилим в начале набор джамповдля асм функций, после которого будут уже их коды? С компилер сохранит точки входа… Дык это ж кернель из 93-его! :)
Подход помогает. Отладка асм становится быстрее в 50 раз.
Итак, некоторые внутренности.
Для реально «быстрой» работы в узких участках диггер использовал х86 асм для процедур работы со спрайтами. Исходники в комплекте, асм понятен точно так-же как и этот их С код :)
База есть. Вызов функций – понятен. Передача параметров происходит через стек.
Сначала идёт адрес возврата, потом – крайне левый параметр своего типа, и так до последнего параметра. Снимай, юзай…
Особенностью оказалось – использование своих регистров — в первую очередь IX, похоже что используется так-же IY (у себя не заметил, но отмечал использование в других проектах), и обширное использование стека для хранения значений переменных внешних относительно вызываемой функции.
То есть вообще часто жесть со стеком :)
Ок, точки вызова есть, давай аккуратно отработаем. Что для этого надо – уже понятно.
Пушить переменные много нельзя, IX сохрани, call – это тот-же push, можешь насрать в область переменных. Себе дороже, в общем.
Для сложных подпрограмм юзаю следующее:
а потом указываю стек и выхожу.
Следующей болячкой было – поиск где собственно отрабатывает интересующий меня С код.
Радует что это можно увидеть в генерируемых 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к, если будут герои. Я не герой :)
Опа! Всё падает, и падает жестоко. Переменные – где угодно, но не по своим адресам… Да что ж такое… как? Почему??!
Дикая копанина, ступор. 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 комментария
А палитру как конвертировал?
как и начальный экран.
в оригинальной игре спрайты лежали как массивы: точек и маска. смотрел ехе диггера твоим вьювером спрайтов в своё время :)
а экран был слегка пожат.
мга симпатичнее выглядит гораздо, при тех же доступных 4х цветах на точку