Кстати, да, мне этого не хватает в моём ядре. Только я не буду разносить их, как ты предлагаешь, а видимо перейду к системе 2х скриптов; один скрипт будет выполнятся во время прерываний, это скрипт специально для коротких, незапирающих команд. А второй скрипт будет выполняться так же, как скрипт у меня сейчас. Это позволит распаковывать и фиксить одновременно, примерно как у тебя сейчас. Но идеология прежняя — ядро должно будет контролировать выполнение.
Что изменилось в моём ядре? Я поменял устройство скрипта. «Скрипт» у psndcj — это просто список слов, номера фреймов к которым привязаны переключения эффектов, адреса процедур которые нужно исполнить, иногда данные. Скрипт у меня — это примитивный байткод, который интерпретируется ядром. Я хотел чтобы весь фикс в деме осуществлялся на уровне ядра, а не внутри эффектов. Это означает, что эффекты никогда не получают полный контроль над машиной.
Какого рода команды есть у меня в скрипте? Самая главная команда: дождаться нужного фрейма:
kWAIT 3200
Некоторые команды чисто утилитарные: например, копирование и распаковка данных.
(первая для байтов, вторая для слов). Когда нужно слегка модифицировать эффект для достижения какого-то фикса, нет ничего проще чем добавить простую заглушку (как в первом примере) или подменить адрес данных (как во втором).
Эффекты я обычно стараюсь писать в прерываниях. Обработчик ядра, помимо своих обыкновенных обязанностей, умеет запускать процедуру пользователя. Понятно, задача порубить эффект на фреймы не всегда удобно разрешима, но я стараюсь по возможности это делать, т.к. эффекты в прерываниях позволяют ядру работать параллельно с эффектами, что даёт некую ограниченную форму многозадачности. Типичный план фрейма таков: обработчик прерывания обновляет номер текущего фрейма, играет музыку, затем запускает процедуру пользователя, после чего контроль возвращается ядру. Скрипт может сказать ядру в этом случае ждать пока номер фрейма не достигнет чего-то, т.е. крутиться в холостом цикле до следующего прерывания. Но вполне возможен вариант, когда скрипт говорит ядру распаковать данные, и тогда получается, что каждый свободный такт, оставшийся во фрейме после эффекта, будет потрачен на распаковку. Вот пример достаточно нетривиального кода из Wonderball, для переключения со сцены 2 на сцену 3 (сцена три — это шас с радиальными лучами анимацией):
kWAIT 2304-4 : kPOKE E01_ScrollerAttr, 201 ; атрибуты скроллера выключается немного заранее, чтобы нарисовать на его месте спрайты (спрайты копируются той же процедурой, что и сам скроллер)
kPPOKE E01_AniSprite1, Phase1Sprite ; настройка корректных фаз для анимации волн вокруг чанкового шара
kPPOKE E01_AniSprite2, Phase2Sprite
kPOKE E01_BlitSprite, 1 ; спрайты начинают рисоваться заранее, скрытые атрибутами
kPPOKE E01_CurTableCT3, PlasmaTabCT3_1 ; выбор таблицы для плазмы внутри шара
kINIT E01_TuneCT3 : db 5, 9, 47 ; настройки эффекта плазмы
kWAIT 2304-1 : kINIT E01_SetScene3 ; собственно переключение сцены. спрайты уже нарисованы...
kWAIT 2304+1 : kPOKE E01_ScrollerBlit, 201 ; ...поэтому скроллер можно выключить
kPOKE E01_BeamsOn, 1 ; и включить вместо него эффект радиальных лучей
kINIT E01_PaletteCT3 ; инициализация палитры для цветных чанков
db %01110110,%01010110 : db %01110110,%01010010 : db %01000110,%01000010 : db %00000110,%00000010
db %00000011,%00000001 : db %01000011,%01000001 : db %01011011,%01001001 : db %01011111,%01001011
kPPOKE E01_CurBeamColour, E01_FlashMagenta ; цвет радиальных лучей
kPOKE E01_PickPhase, 1 ; выбор фазы позволяет контролировать направление, в котором будут крутиться лучи
kEXEC E01_JumpCT3, E01_OverlayPage ; заключительная инициализация новой сцены
Поскольку эффект занимается чем-то своим, а ядро — чем-то своим, самой сложной частью для написания такого ядра оказывается менеджер памяти. При работе с таким ядром пользователь не имеет права менять страницы в обход ядра. Ядро ведёт учёт и отличает «страницу ядра», т.е. ту страницу, где хранится скрипт, «страницу музыки» (понятно), «страницу пользователя при работе прерывания» и «страницу пользователя при работе вне прерывания». Есть и другие нюансы, например, моё ядро работает не с реальными, а с виртуальными страницами, благодаря чему на классических машинах я всегда знаю, какие страницы медленные, а какие быстрые. Но я уже устал столько всего писать!
В прошлом мае я написал универсальный движок для трекмо. Прототипом движка для меня было ядро написанное psndcj для дем tbk/4d; psndcj говорил, что его ядро основано на ядре эксполодера. Т.е. родословная, типа, о-го-го.
Немного о ядре psndcj . Оно очень шустрое и легковесное. Ядро сидит чуть ниже верхней страницы. Обработчик прерывания находится в ядре и является его ключевой частью. Прерывания разрешены ВСЕГДА. Обработчик считает фреймы и, при достижении различных ключевых моментов в треке, запускает пользовательские коды. Преимущество работы с номерами фреймов (в противоположность номерам паттернов, например) заключается в том, что
1. Это позволяет синхронизироваться не с точностью до паттерна, а точнее, вплоть до каких-то звучков, индивидуально.
2. Вообще говоря, очень часто музыка играется из PSG, т.е. музыка уже полностью потеряла информацию о номерах строк, паттернах и т.д., а синхронизироваться всё ещё нужно.
Кроме этого, в ядре находился декомпрессор, процедура быстрого копирования данных и процедуры для эффективной работы со скрытым экраном. Идея в том, что по окончанию отрисовки в скрытый экран, код может начинать рисовать следующий кадр, а собственно переключение экрана осуществляет само ядро, сразу после прерывания. Это позволяет более эффективно использовать машинные ресурсы.
Недостаток, с моей точки зрения, этого ядра заключался в том, что оно было написано для работы в стиле «распаковали эффект», «показали эффект», «расчиститили место для следующего эффекта». Ядро запускает эффект и пока эффект не закончился, ядро не контролирует процесс. Конечно, так писать в чём-то проще. Но это очень сильно усложняет фикс. Если нам, допустим хочется, что-то поменять в эффекте посередине эффекта, нам придётся внутри эффекта сравнивать счётчик фреймов ядра с какими-то константами, т.е., по сути, дублировать функциональность ядра.
Другим недостатком было то, что скрипт хранился в основной памяти (насколько я знаю, psndcj недавно сделал версию ядра в которой это ограничение было снято).
Женя psndcj , у меня понятно немного пристрастный взгляд на это всё, было бы классно если бы ты прокомментировал, м.б. расставил как-то иначе акценты. Кроме того, очень интересно узнать, что у тебя в ядре пришло в наследство от эксподера.
Очень инересно, что они по всей видимости решили сохранить тормознутый рваный скроллер оригинального R-Type.
Т.е. сделали ставку на 200% аутентичность. Будет интересно посмотреть как примут такой проект.
Лёш, а не напишешь несколько предложений по каждой из интро? Вот ты сказал блистательная про игру гасмана и мне интересно, потому что я её как-то не заценил, мне интересен твой взгляд поэтому. Интра utz меня наоборот очень впечатлила, не говном разноцветным (впрочем в этот раз у всех говно разноцветное :) ), а тем, насколько музыкально она звучит — он видимо записал туда что-то типа нотной прогрессии, но как она рандомайзится — ума не приложу.
Ребята, не забывайте пожалуйста, что Yerzmyey обычно обрабатывает свои записи эквалайзером. Т.е. это не самый надёжный источник если вам хочется чтобы играло точь-в-точь «как на реале».
Ненавижу переводы на хабре. Во-первых, людей, которые пишут «визуально сексуальные демы» нужно вешать на столбах. Во-вторых, они почему-то никогда не дают ссылки на оригиналы, с которых переводили. Итак, оригиналы первых двух статей:
Вова, спасибо что тащишь на себе такой большой проект. Да, так вышло, что тс-конфа у нас оказалась «спорной» платформой, по ряду причин, в чём-то объективных, в чём-то не очень. Извини, что мы (я) не вполне за тобой успеваем — довлеет груз других проектов. Хочу проговорить: то, что ты делаешь, важно. Я прочитал все статьи в твоей серии. К сожалению, нетривиальные вопросы/замечания/дополнения требуют намного более плотной работы с конфой, поэтому лично мне просто сложно спросить что-то нетупое.
Главная польза от твоей работы, как я вижу её для себя, заключается в том, что гораздо быстрее и проще учиться основам чего-то новое из вот такого вроде поверхностного неглубокого трёпа. В этом плане, ты держишь правильный курс.
А вообше, всё очень просто. Нужно делать нетривиальный проект на тс. Очень надеюсь в какой-то момент осилить.
Какого рода команды есть у меня в скрипте? Самая главная команда: дождаться нужного фрейма:
Некоторые команды чисто утилитарные: например, копирование и распаковка данных.
(копируем упакованную картинку из 0й страницы вниз и потом рапаковываем её в экран на странице 7). Крайне, мегаполезные команды — kPOKE и kPPOKE:
(первая для байтов, вторая для слов). Когда нужно слегка модифицировать эффект для достижения какого-то фикса, нет ничего проще чем добавить простую заглушку (как в первом примере) или подменить адрес данных (как во втором).
Эффекты я обычно стараюсь писать в прерываниях. Обработчик ядра, помимо своих обыкновенных обязанностей, умеет запускать процедуру пользователя. Понятно, задача порубить эффект на фреймы не всегда удобно разрешима, но я стараюсь по возможности это делать, т.к. эффекты в прерываниях позволяют ядру работать параллельно с эффектами, что даёт некую ограниченную форму многозадачности. Типичный план фрейма таков: обработчик прерывания обновляет номер текущего фрейма, играет музыку, затем запускает процедуру пользователя, после чего контроль возвращается ядру. Скрипт может сказать ядру в этом случае ждать пока номер фрейма не достигнет чего-то, т.е. крутиться в холостом цикле до следующего прерывания. Но вполне возможен вариант, когда скрипт говорит ядру распаковать данные, и тогда получается, что каждый свободный такт, оставшийся во фрейме после эффекта, будет потрачен на распаковку. Вот пример достаточно нетривиального кода из Wonderball, для переключения со сцены 2 на сцену 3 (сцена три — это шас с радиальными лучами анимацией):
Поскольку эффект занимается чем-то своим, а ядро — чем-то своим, самой сложной частью для написания такого ядра оказывается менеджер памяти. При работе с таким ядром пользователь не имеет права менять страницы в обход ядра. Ядро ведёт учёт и отличает «страницу ядра», т.е. ту страницу, где хранится скрипт, «страницу музыки» (понятно), «страницу пользователя при работе прерывания» и «страницу пользователя при работе вне прерывания». Есть и другие нюансы, например, моё ядро работает не с реальными, а с виртуальными страницами, благодаря чему на классических машинах я всегда знаю, какие страницы медленные, а какие быстрые. Но я уже устал столько всего писать!
Немного о ядре psndcj . Оно очень шустрое и легковесное. Ядро сидит чуть ниже верхней страницы. Обработчик прерывания находится в ядре и является его ключевой частью. Прерывания разрешены ВСЕГДА. Обработчик считает фреймы и, при достижении различных ключевых моментов в треке, запускает пользовательские коды. Преимущество работы с номерами фреймов (в противоположность номерам паттернов, например) заключается в том, что
1. Это позволяет синхронизироваться не с точностью до паттерна, а точнее, вплоть до каких-то звучков, индивидуально.
2. Вообще говоря, очень часто музыка играется из PSG, т.е. музыка уже полностью потеряла информацию о номерах строк, паттернах и т.д., а синхронизироваться всё ещё нужно.
Кроме этого, в ядре находился декомпрессор, процедура быстрого копирования данных и процедуры для эффективной работы со скрытым экраном. Идея в том, что по окончанию отрисовки в скрытый экран, код может начинать рисовать следующий кадр, а собственно переключение экрана осуществляет само ядро, сразу после прерывания. Это позволяет более эффективно использовать машинные ресурсы.
Недостаток, с моей точки зрения, этого ядра заключался в том, что оно было написано для работы в стиле «распаковали эффект», «показали эффект», «расчиститили место для следующего эффекта». Ядро запускает эффект и пока эффект не закончился, ядро не контролирует процесс. Конечно, так писать в чём-то проще. Но это очень сильно усложняет фикс. Если нам, допустим хочется, что-то поменять в эффекте посередине эффекта, нам придётся внутри эффекта сравнивать счётчик фреймов ядра с какими-то константами, т.е., по сути, дублировать функциональность ядра.
Другим недостатком было то, что скрипт хранился в основной памяти (насколько я знаю, psndcj недавно сделал версию ядра в которой это ограничение было снято).
Женя psndcj , у меня понятно немного пристрастный взгляд на это всё, было бы классно если бы ты прокомментировал, м.б. расставил как-то иначе акценты. Кроме того, очень интересно узнать, что у тебя в ядре пришло в наследство от эксподера.
Т.е. сделали ставку на 200% аутентичность. Будет интересно посмотреть как примут такой проект.
СЕЧЁШЬ!
А ведь я даже не художник!
6octaves.blogspot.co.uk/2013/10/interview-with-demoscener-smash.html — smash^flt
6octaves.blogspot.jp/2014/07/interview-with-demoscener-kb-farbrausch.html — kb^flt
Там же, до кучи, интервью с Navis^ASD и др.: 6octaves.blogspot.co.uk/p/demoscene.html
Хотя лучше интервью чем интервью со smash видимо в природе нет.
Главная польза от твоей работы, как я вижу её для себя, заключается в том, что гораздо быстрее и проще учиться основам чего-то новое из вот такого вроде поверхностного неглубокого трёпа. В этом плане, ты держишь правильный курс.
А вообше, всё очень просто. Нужно делать нетривиальный проект на тс. Очень надеюсь в какой-то момент осилить.