+536.57
Рейтинг
1489.62
Сила
  • avatar aa-dav
  • 0
Да, игр где были скроллинги по обоим осям и так то было меньше остальных, а чтобы еще и монолитный статус-бар — это был своего рода высший пилотаж и вообще редко обычно в шедеврах. :)
В онлайн-эмуляторе aa-dav.github.io/ доступен новый исходник «bitmap noise» — выбираем пункт и нажимаем «Compile and Run».
После выполнения инициализирующего кода в simple_lib.inc раскладка памяти следующая:
С адреса $8000 располагаются 16384 _слов_ (ячейки памяти 16-битные) описывающие 16-цветный битмап 256x256 (на экране без записи в регистры скроллинга видны верхние 192 строки). Т.к. ячейки — слова, то в каждое слово влезает четыре пикселя по 4 бита цветности на каждый. Раскладка линейная.
Но еще с адреса $C000 располагается зона атрибутов размером 32x32 знакоместа. Атрибут имеет маску PPPP00NN NNNNNNNN, где N это номер выводимого знакоместа в соответствующей квадратной сетке, а PPPP — верхние биты палитры из 256 цветов которые будут добавляться к цветам пикселя. Т.е. номер субпалитры в 16 слотов из 16 субпалитр. Чтобы записать в палитру надо записать в ячейку/порт $FFF6 номер слота палитры (0..255), а в $FFF7 RGB-значение в формате 0RRRRRGGGGGBBBBB.
Таким образом на экране может быть одновременно 256 цветов, но не более чем 16 цветов в знакоместе.
Более того — отображение в знакоместах можно перенастраивать на другие знакоместа через таблицу атрибутов реализуя быстро работающие текстовые видеорежимы ну или игровое тайловое поле с аппаратным скроллингом.
Размышляя на досуге о том не присобачить ли какой-нибудь ЯВУ вместо ассемблера просто подумал — а насколько архитектура Simp4 хорошо ложится на крайне минималистичный язык Forth?
А ведь есть весьма хороший из-за симметричности системы команд уровень «природной» совместимости.
Во первых т.к. в Simp4 нет байтов, а и регистры и ячейки памяти есть 16-битные, то Forth уже удачно ложится по своей безтиповой стековой модели. Угу.
Во вторых если рассмотреть базовые арифметические операции Forth — они производятся над двумя величинами в вершине стека которые замещаются одним результатом.
Но в Simp4 этому крайне удачно соответствует сам принцип работы со стеком и в точности, например, операция форта + будет реализована всего одной машинной командой размером в минимальное одно слово:

[ sp ] = [ sp ] + [ sp ] ; считываем со стека два операнда (с пост-декрементом), суммируем и отправляем обратно в стек (с пост-инкрементом)


Вместо + может быть и минус и вся прочая базовая арифметика процессора.
Такая адресация используя специфичное поведение регистра sp при косвенной адресации реализует именно что базовую модель форта — со стека снимаются два аргумента, помещаются на вход АЛУ (sp каждый раз при «изъятии» пост-декрементируется) и далее результат из АЛУ записывается обратно в стек с пред-инкрементом. Ровно то, что нужно форту.

Сложнее, например, с командой DUP. Она должна продублировать вершину стека. Но записать это как

[ sp ] <- [ sp ]; аналог move с нулём в качестве второго операнда режима сложения с inplace-immediate


нельзя, т.к. sp без альтернатив при косвенном считывании пост-декрементируется, а при записи пост-инкрементируется, это его неизменная фича. А значит мы останемся ни с чем. Просто холостая проброска без изменения состояния машины.
А значит нужно сперва нацелить другой регистр на вершину стека и действие выполняется в две 16-битных инструкции:

r0 <- sp + 0
[ sp ] <- [ r0 ]


Т.е. загоняем в r0 копию указателя на вершину стека и вот её уже дублируем.
Но интересно тут то, что константа 0 в используемом тут режиме inplace-immediate (может полностью отсутствовать с кодом операции + как во второй инструкции) может быть любым числом от -8..+7, что позволяет уложить этот режим в одно слово инструкции. А значит во первых — ряд инструкций которым нужно дотянуться неглубоко в стек (до -8 от вершины) могут использовать этот сокращённый режим инструкции, а форту больше и не надо.

Однако такое удобство стека в Simp4 вроде бы как ставит подножку — использовать его уже понятно, что очень удобно для форта, но как же переходы в другие участки кода (CALL-ы) которые тоже используют стек?
А вот как: в Simp4 на самом деле по архитектуре нет команды CALL, а она эмулируется последовательностью из, например, таких инструкций:

[ sp ] <- pc + 2
pc <- proc_address


Т.е. да, в Simp4 мы всегда сами помещаем в стек «вручную» адрес возврата предварительно его вычислив где опять таки пригождается сложение в режиме inplace-immediate, т.к. желательно уложится в одно слово и потом мы совершаем безусловный прыжок куда надо. Такая последовательность инструкций занимает уже три слова, т.к. proc_address как полное 16-битное слово надо размещать за последней инструкцией. Поэтому в стек в первой команде помещается pc+2 — на момент выполнения этой инструкции pc уже смотрит в начало следующей которая занимает 2 слова, вот мы и вычисляем адрес возврата сразу за ними.
Окей, но это для нас значит, что мы можем вообще изменить стратегию вызова процедур в режиме форта и не использовать для неё регистр sp!
Можно применить совмещённую стратегию программного стека и LINK REGISTER. Договоримся, что регистр r4 указывает на слово сразу под вершиной программного стека для вызова процедур и тогда вызов будем писать так:

[ r4 ] <- pc + 2
pc <- proc_address


Это всё те же три слова инструкций, но регистр r4 сам не декрементируется. У него в отличие от sp такой фичи нет.
Поэтому если процедура не вызывает другие процедуры (leaf-node) она просто не портит r4 и делает возврат тривиально:

pc <- [ r4 ]


И ячейка на которую указывает [ r4 ] снова готова к использованию без какого либо пенальти по сравнению с классическим стилем вызова процедур в Simp4 как я его использую.
Но если процедура собирается вызывать другие процедуры, то она должна начинаться с тривиального пролога:

r4 <- r4 - 1


Просто при входе декрементируем r4 в одну инструкцию-слово.
И возврат из такой процедуры усложняется всего лишь на одно слово:

r4 <- r4 + 1 ; увеличиваем r4 на 1
pc <- [ r4 ] ; переходим по адресу возврата в ячейке куда указывает r4


И вуаля! Такой отказ от использования аппаратного стека для подпрограмм совсем не выглядит катастрофой, обременительные расходы совсем небольшие, а для leaf-node-процедур вообще нулевые. Зато гибкость аппаратного стека для арифметики самого Форта выглядит солидным достижением.

Забавно, забавно. Simp4 оказывается сравнительно дружелюбная архитектура к Форту хотя таковой совсем не планировалась. :)
  • avatar aa-dav
  • 0
Но в остальном, скажу честно, у меня там наверное больше несовпадений со списком Shiru, чем совпадений.

Cybernoid 2 присутствует? :)
  • avatar aa-dav
  • 0
в первой части вертикального скроллинга не увидел.
в какой он появился с сохранением статус бара?
  • avatar aa-dav
  • 0
Важно! Похоже, что для корректной работы Nesicide нужно сперва установить на компьютер Mingw32 и прописать путь до его папки BIN в переменной среды PATH! Похоже, что Nesicide который изначально разрабатывается и тестируется в Linux нужны некоторые утилиты командной строки такие как make и которые есть в Mingw32. Я этот момент проворонил потому что у меня он всегда стоит и прописан в пути.
  • avatar aa-dav
  • 0
Можно бесконечно спорить на частных примерах где получается больше, а где меньше. Но это не самоцель же на самом деле. Я просто показал в статье, что меня позабавило, что несмотря на очевидное разбазаривание плотности команд (у того же дедушки PDP-11 с наследниками в виде БК-шек она гораздо выше) весьма базовые действия такие как сложение слов с занесением сразу же результата в целевую ячейку памяти получаются заметно короче нежели на классических 8-битках. Многое конечно будет наоборот заметно больше — например нет ничего похожего даже на LDIR или инкремент регистра всегда осуществляется за слово, а не за байт (хотя инкремент может быть любым числом в диапазоне -8..+7 и может записать результат не в тот регистр из которого бралось первое слагаемое. собственно в архитектуре нет выделенной операции MOV потому что это инкремент на 0 какого-то регистра или ячейки памяти с занесением в другой регистр/ячейку памяти). Ну и тому подобное и так далее.
В 80-х такая архитектура не могла бы появится, потому что там более бережно отнеслись бы к расходу памяти и сделали бы что-нибудь типа PDP-11 или MSP-430. С их довольно ветвистыми системами команд и режимами адресаций.
Я же преследовал простоту всего — отказ от байта это в эту же копилку. Я прекрасно понимаю, что у Simpleton поэтому немало слабых сторон.
Но практикум программирования в эмуляторе показал лично для меня, что да, программировать просто — очень небольшой, буквально с час, период привыкания и всё, ты просто пишешь код состоящий из очень простых операций вида R = X op Y и многое о чём болела постоянно голова в Z80 или 6502 вообще отсутствует как класс.
  • avatar aa-dav
  • 0
P.S. «Семь байт» читать как «Семь слов»
  • avatar aa-dav
  • 0
локальные переменные — необязательно стековые, могут быть ведь и статические, где можно
Так с машинной точки зрения между статическими и глобальными разницы нет. Если статические — значит верно всё то что написано выше про глобальные.
ну вот, а у z80 — три байтика)))
С фига ли? Семь байт на _сложение двух слов из стека с записью результата в стек_. По любому смещению.
Три байта у Z80 тут даже близко нет.

вообще выигрыш у тебя больше за счёт 16-битности там, где от z80 ты тоже требуешь 16-битных операций
У Z80 есть 16-битные операции. И загрузка и сохранение и арифметика. Но вот…
При этом Simpleton субоптимальная архитектура — я писал про это в статье про сам Simpleton 4 в первых же параграфах. Её главная цель не вложить максимум команд в минимум байт, а обеспечить максимально чтобы были простыми одновременно и машинная и программистская стороны вопроса. Оптимальностью команд при этом пришлось пожертвовать, но что интересно — широкое слово даже после этого чаще всего обходит 8-битки по плотности команд когда действительно надо работать со словами. Даже если это такая мощная 8-битка как Z80 где обработка слов есть. Причём обходит заметно, причём разбазаривая биты и не делая сложных режимов адресации. Это забавно.
  • avatar aa-dav
  • 0
P.S.
Правда еще надо заметить (по ссылке выше это описано) — если смещения от вершины стека переменных укладываются в -8..+7 слов, то размер примера [ a ] = [ b ] + [ c ] снова можно вернуть к четырём словам, но загрязнение регистров адресами локальных переменных останется. Причём если дальше нужно поработать с переменными отстоящими от уже полученных указателей опять же не далее чем на 4-битное знаковое смещение — опять можно обойтись в инструкции перенастройки одним словом. Короче inplace immediate может дать возможность к оптимизации. Но это так, полумеры.
  • avatar aa-dav
  • 0
всё же чаще в прикладных полезных программах оперируют локальными переменными
Это когда пошли процессоры заточенные под стековую адресацию.
На MOS6502 адресовать стек легко невозможно. На Z80 даже вроде бы при наличии адресации через IX/IY+offset такие инструкции дают приличный пенальти на работу со словами. Поэтому максимально быстрый код писался на глобальных переменных. Для меня это составляет некоторую романтику той эпохи поэтому инструкции адресации стека я вводить не стал.

так вот другой пример, на локальные — сложить два числа с верхушки стека, что будет здесь? ;)
Семь слов если на стеке (и загрязнение трёх регистров). Против четырёх слов без загрязнения регистров у глобальных переменных.

Я это обдумывал по следующей ссылке и там же придумал апгрейд архитектуры до лёгкой адресации стека: gamedev.ru/flame/forum/?id=249067&page=23&m=5439258#m333
Там как раз сперва рассуждения о том насколько просядет производительность с переменными в стеке.
А потом идея превратить один из пяти регистров без особых функций в аналог BP из i86: косвенные чтения/записи по регистру r4 всегда считывают слово из [ pc++ ], прибавляют его к r4 и полученное значение используется в качестве адреса для косвенного чтения/записи.
Тогда всё еще большую симметричность приобретёт: r0-r3 — регистры без специальных функций и r4-r7 — регистры особого назначения.
Но я не хочу так делать чтобы не ломать дух эпохи.
Хочешь Си — просади производительность. :)
  • avatar aa-dav
  • 0
P.S.
В этом SimpX тоже пытается быть максимально простым и схемотехнически и программистски, но не экономией на спичках!
Текстовый видеорежим в нём является частным случаем графического режима. Идеи эти базированы очевидно на тайловых видеочипах консолей, но сделан тот ход, что номера тайлов в битмапе не линейно возрастают, а образуют двумерную картинку «as is» битмапа.
Но в статье описано, что перетусовки бит в этом случае настолько просты и прямолинейны, что не несут никаких накладных расходов по сравнению с линейной организацией тайловой карты.
В SimpX же это позволяет на одной и той же физической схеме реализовать и быстрый текстовый режим и линейный графический.
А при желании — демосценить с атрибутами знакомест! :D
  • avatar aa-dav
  • 0
Коррекция: «нижнее левое знакоместо» => «нижнее правое знакоместо»
  • avatar aa-dav
  • 1
Вот тут есть старое видео графического режима: youtu.be/ESg7SWPMpE8
Тут видно, что выделяются знакоместа 8x8 пикселей.
И конечно это не просто так.
SimpX использует 16-цветный битмап 256x256 пикселей (видимая зона — 256x192), но каждое знакоместо 8x8 имеет собственный 4-битный атрибут палитры. Таким образом это эдакое мощное расширение спектрумных идей — в пределах знакоместа 16 цветов одной из 16 палитр (палитра содержит 15-битные RGB — 0RRRRRGGGGGBBBBB) так что всего на экране цветов может быть 256.
Более того зона атрибутов (32*32 слова) SimpX содержит так же индирекции какое именно знакоместо в текущем знакоместе выводится (0-1023).
Т.е. формат атрибута знакоместа в битах следующий:
PPPP00NNNNNNNNNN, где P — это номер палитры, а N — номер знакоместа которое в данном знакоместе выводится.
Если всю область чармапа залить нулями, то каждое знакоместо на экране будет выводить первый (нулевой) квадратик 8x8 из битмапа 256x256 — левый верхний уголочек. Если залить числом 1023 — то на экране 32*24 раз выведено будет нижнее левое знакоместо битмапа.
В любом случае манипулируя верхними четырьмя битами этой заливки можно окрашивать знакоместа в одну из 16 субпалитр.

Сейчас в simple_lib.inc эти характеристики используются чтобы организовать простейший текстовый видеорежим — битмап (16 килослов) заливается (частично) вот этой картинкой:

И чармап используется как буфер символов, т.к. они просто маппятся на эту картинку.
Если же залить чармап возрастающими от 0 до 1023 числами — то битмап будет отображён на экран прямолинейно как есть и даст графический режим с 16 цветами.
Который можно обогащать 16 субпалитрами добавляя к чарам в чармапе верхние 4 бита субпалитры.
  • avatar aa-dav
  • 0
Rw->Kw
была опечатка
Имелось ввиду под Rw — K2 — килослова.
  • avatar aa-dav
  • 1
это уже возможно, просто не хватает времени.
но да, если залить в чармап (1Rw) последовательно возрастающие числа, то битмап станет прямым отображением пикселей на экране.
это уже сейчас работает, но руки не доходят…
  • avatar aa-dav
  • 2
Я считаю, что деление на цифровой/аналоговый вообще неуместно в этом случае
(оффтоп) Я до сих пор иногда балдею с того, что Майк Гордон — в частности композитор музыки к Doom 2016 раскопал где-то старый советский реально аналоговый синтезатор Поливокс и… www.youtube.com/watch?v=oKzYf1JW7kE
  • avatar aa-dav
  • 1
Для меня очевидно, что звук у Adlib'а проигрывает SID с точки зрения удовольствия от прослушивания.
Никаких претензий к этому нет и быть не может. Сам феномен чиптюна — когда есть уже лет 20 как CD-диски несжатых симфонических оркестров 44кГц+2 канала — это само по себе о многом говорит.
Нам нравится именно то шипящее, шкворчащее, упрощенно-усложнённое звучание. Оно было экономией на схемотехнике, но создало свой стиль и шарм до сих пор влияющий и на «большую музыку».

Слышал/читал в 1990-е много мнений о том, что у Adlib-а (оригинального и того, что в SB) звук «пластмассовый», «неинтересный» и прочее.

Тут надо понимать, что Yamaha — компания производящая в начале 19 века клавесины и пианино — это компания звукопроизводящего инструмента. И она была одна из первых в вопросе электронного синтеза.
Они пытались воссоздать звучание настоящей струны. Синусоиды, тембры, реверберации и тому подобное.
Но это всё еще дешевые (правда не на момент появления) попытки к нему приблизиться.
В итоге получилась наверное эдакая «зловещая долина» ( ru.wikipedia.org/wiki/%D0%97%D0%BB%D0%BE%D0%B2%D0%B5%D1%89%D0%B0%D1%8F_%D0%B4%D0%BE%D0%BB%D0%B8%D0%BD%D0%B0 ) в мире музыки. Вроде звучание и похоже на фортепьяно, но блин, какое то совсем деревянное и ненатуральное. Хм…
Я думаю так оно и было.
При этом примитивные осцилляторы типа тех что трудились в C64/NES/ZX 128 просто не вызывали отторжения, т.к. их искусственность была сразу очевидна и не вызывала никаких «зловещих долин».
Просто новый формат мелодии.
  • avatar aa-dav
  • 0
Простой вопрос: почему авторы маленьких интро под DOS чрезвычайно редко использовали возможности Adlib (неважно — в оригинальном Adlib или в SB)?
У меня нет кругозора чтобы сказать что это действительно так.
Звуковой чип из C64 — SID — это три настраиваемых осциллятора. Классическая работа с ними: по прерыванию 50/60 раз в секунду менять им параметры чтобы создавать полифоническое глубокое звучание со всякими перкуссиями и тому подобное.
Так вот чип YM3812 из Adlib/Sound Blaster — это намного круче технически, но с полностью таким же принципом. Там просто уже 9 каналов и каждый содержит по два осциллятора которые спрягаются в FM-синтез. Чтобы всем этим управлять нужно уже более двухсот байтовых параметров! В остальном же — сам принцип «хороводства» — всё то же самое.
  • avatar aa-dav
  • 0
Почему же в интрах так редко использовали adlib совместимость
Если программа использовала ТОЛЬКО музыкальный чип из Sound Blaster — она без проблем запустилась бы и на Adlib.
Эта особенность зачастую в SETUP.EXE игр так и выглядела, что отдельно были настройки для PCM-звука и отдельно для музыки (тот же Duke3D). И Sound Blaster там писался в последнем случае в одной строке с Adlib через слеш.

У меня в то время была звуковая карта из разряда дешевых — фирмы ESS. Она умела притворятся и Sound Blaster-ом тоже и в сущности в дешевом сегменте тоже его сильно потеснила.
Ну к тому времени уже конечно это всё было не удивительно. Когда у меня были такие фишки Sound Blaster уже превращался как какие то ненужные совершенно обвески с генераторами эхо-эффектов в 3D-пространстве, которые тупо вырезали софтом, т.е. никакой существенной разгрузки ЦП уже не происходило такими ускорителями звука.