«откуда инфа? что именно с бета-диском так происходит?»
Я из таких лоскутов это собирал что уже не вспомню, иногда просто форумы какие то. Если это точно неправда, то надо исправить и тут. Прошу проверить даже такой момент — есть ли точки входа где байты в оригинальном пзу ненулевые.
откуда инфа? что именно с бета-диском так происходит?
я вот сдуру сделал так в своём эмуляторе, и после этого стал неправильно работать TESTall: vtrd.in/system/TEST_ALL.zip
который переходит на #3D30 явно предполагая, что выбираться с него будет уже опкод ret из ПЗУ тырдоса
а в других эмулях — unreal, spin, xpeccy — оно работает!
Попробовал так сделать — ассемблер ругается что символ неопределён. Логично, ведь ini-файл есть параметр в линкер, но не в ассемблер. А если сообщаешь через .global что есть символ который потом пытаешься положить в .byte, то ругается что range error. Опять таки логично, ведь символы это адреса как правило и обойти можно сделав <NAME, т.е. взять младший байт и видимо в простой ситуации как PRG_BANKS уже сработало бы, но я попытался воткнуть это в вычисление по битовым маскам
byte MIRRORING | (HAS_SRAM << 1) | ((MAPPER & $0F) << 4) | NAME
и тут линкер выдал ошибку «Attribute expected» которая даже не гуглится особо да и я не понимаю как линкер может такое вообще отрабатывать нормально. Если только весь байт сразу там и определить разве что, но есть ли там битовые операции?
Нда, сам не заметил как скатился к полному разжёвыванию каждого нового встреченного ключевого слова и объяснения как байты лежат в памяти, так что заявление из первой статьи о том, что я не буду учить как программировать в ассемблере и архитектуре 6502 вообще пошло ломанными трещинами и начало рассыпаться в пух и прах.
Уже даже не пойму какая аудитория выйдет идеальной для этого всего, уже даже закрадывается что как тот PHP-шник который стал делать выступления на конференциях как он стал писать на NES за месяц. :D
P.S.
А ведь если задуматься, то такой подход (как у SjAsm) ничем не мешает и созданию кросс-платформенных форматов — генерацию каких то заголовков и служебных вещей тоже легко положить на какие то макросы из SAVEBIN OUTPUT_FILE которые обязательно надо выполнить в оговоренном порядке. В общем то дело техники. И у меня возникает подозрение, что FASM так и работает, поэтому конкретные форматы конкретных PE и COFF там дело библиотечного уровня.
В SjAsmPlus код в банках размещается как раз ORG'ами в одни и те же адреса и сохраняется в бинарники по мере трансляции, т.е. в те моменты, когда в нужных адресах виртуальной памяти сгенерирован нужный код, а дальше по ходу трансляции он может быть перезаписан.
О, кстати, вчитался и да — это то что мне было непонятно, вчера уже сонный был, так что цитата выше немного не по делу и касается только первой части. Получается что путало само наличие директивы PAGE X, и это воспринималось как раз как то наподобие сегментации, но непонятно как работающее в рамках многостраничных моделей. А это просто как бы переключение виртуальной памяти по схеме реальных 128Кб для возможных упрощений в каких то моментах, но сбрасывать на диск всё-равно надо постранично в момент активации нужных страниц.
Теперь и с SjAsmPlus всё понятно, спасибо.
В целом такой же «сегментированный» модульный и высокоуровневый подход не редкость и в ассемблерах и активно использовался и в программировании на Intel 8086, так что наверняка для многих из вас открытием он не будет. Но тем кто привык под «модулями» понимать просто включаемые в основной файл директивой INCLUDE тексты цельной программы компилируемые в один проход — тем надо немного переучится.
Есть ассемблеры без линкеров, есть с линкерами. Для того, чтобы были упоминания сегментов, нужно, чтобы исходник был под ассемблер с линкером. SjAsmPlus — ассемблер без линкера. В среде любителей-энтузиастов это более типичная архитектура ассемблера, т.к. её проще сделать (любители же сами эти ассемблеры и писали) и проще пользоваться в рамках одной целевой платформы. Из любительских кросс-ассемблеров с линкером сходу вспоминаю разве что WLA DX.
В SjAsmPlus код в банках размещается как раз ORG'ами в одни и те же адреса и сохраняется в бинарники по мере трансляции, т.е. в те моменты, когда в нужных адресах виртуальной памяти сгенерирован нужный код, а дальше по ходу трансляции он может быть перезаписан.
CA65/CC65 — пакет не для конкретно NES, а для любых систем на 6502
Нигде я не говорил что CC65 это только для NES, более того в начале этой части статьи написано про любой MOS 6502, но как то абстрактно и действительно стоит обозначить что cc65 имеет широкий охват. Это стоит сделать еще в предыдущей части. Действительно.
Также бывают ситуации, когда часть памяти кода переключаемая (разная память в одних и тех же адресах, т.е. банки)
Ни видел упоминаний сегментов в нескольких серьёзных исходниках, например Mighty Final Fight (под SjAsmPlus), но я тут реально слабо понимаю в том как именно в таком коде метки привязываются к переключению страниц.
У меня сложилось ощущение что просто через пару еще других ключевых слов и, вероятно, привязанных к виртуальным образам самого спектрума. Вообще не уверен.
Но разбираясь с секциями MEMORY и SEGMENTS ini-файла линкера cc65 очень быстро и легко понял как оно должно ложится на мапперы и любую структуру памяти любой машины. Это действительно сложно на первый взгляд, но понять нетрудно как и все выгоды — на самом деле даже очень просто.
Т.е. как переключать банки памяти на CA65 я понял даже быстрее чем на SjAsmPlus несмотря на то что со вторым столкнулся намного раньше.
Забавно, ведь во втором это сделано явно проще и для конкретной платформы, но глядя в документацию я не смог понять как.
А в CC65 просто поглядел пару минут в файл .ini с описаниями кусков памяти и сегментов и понял всё очень быстро.
Дальше только уточнения насчёт align и т.п. из официальной документации. И сразу понял кристально как сюда встраивать переключения банков.
Действительно вроде и сложнее, но по факту много проще.
CA65/CC65 — пакет не для конкретно NES, а для любых систем на 6502 (и частично 65816) в принципе, изначально для восьмибитных Atari (1989 год, между прочим). Соответственно сегментная модель в линкере позволяет задать любую карту памяти для любого компьютера с этим процессором. Также бывают ситуации, когда часть памяти кода переключаемая (разная память в одних и тех же адресах, т.е. банки), часть обязательно должна быть фиксированной, есть разные виды памяти, и всё это дело сохраняется в какой-то образ определённого формата — всё это легко позволяют задать сегменты (для NES: хидер iNES, расположение ОЗУ, банки PRG и CHR).
У меня есть такая проблема — я вырос в детстве на ZX Spectrum 48 (конкретно отечественном клоне Кворум-64), но именно в детстве не стал в это деле опытным и начитанным ассемблерщиком и сейчас возвращаясь к этому и восторгаясь тем или иным вещам просто вынужден описывать как можно более подробно, вплоть для самого себя, с чем сталкиваюсь, причём опять и снова, но уже наученный про всё.
Вероятно действительно выходит ну очень подробно и с остановкой на каждом шаге. Надеюсь так и есть.
Я читал Робуса, и не понял ни слова (это проблема, разумеется, моя, а не Робуса :)
А тут прям всё хорошо и понятно! Даже обидно, что никто не комментирует.
Я бы и сам рад, но нечего добавить :)
Лет десять назад я сделал три вещи, которые оказались весьма востребованными в тот момент, и с помощью которых с тех пор была создана добрая половина homebrew для NES:
— Конвертер-редактор графики и экранов, а впоследствии также и составных спрайтов — NES Screen Tool, с довольно корявым, но вполне человеческим лицом. До этого были только редакторы тайлов типа Tile Layer Pro и YY-CHR, а также дикие утилиты под DOS, что очень затрудняло подготовку графики для игр. Альтернативы ему не появилось до сих пор (а надо).
— Библиотеку FamiTone, которая позволила легко и просто добавлять музыку и (решающий фактор) звуковые эффекты в игры, делая их в человеческом FamiTracker. В этом также большая заслуга jsr, Gradualore и rainwarrior, которые добавили и развили поддержку кастомных экспортёров из FamiTracker. До этого не было готового плеера, который можно было просто взять и вставить — все либо изобретали велосипед, обязательно включающий написание музыки в hex-кодах, либо приватно делились кодом. К тому же, в тот момент предпочтения в комьюнити касательно кросс-ассемблеров делились на три равные части, NESASM/asm6/CA65, код между которыми переносить довольно затруднительно, а я поддержал все три сразу. С тех пор появилось несколько альтернатив (в том числе форков моего кода), FamiTone ещё в лидерах, но его начинает теснить решение от Gradualore, которое встроили в NES Maker.
— Библиотеку neslib, которая позволила легко и просто писать на C. Ранее на сцене ходили настроения, что ничего путного сделать на C невозможно, не стоит даже и пытаться — никто и не пытался. А я видел, что делают Mojon Twins с компилятором C на ZX (как известно, ныне чурерра заполонила), и показал, что так можно было. Также я привлёк самих Mojon'ов, чтобы они показали класс (Sir Ababol и другие игры). Это в свою очередь сподвигло nesdoug'а не только самому начать писать на C, но и сделать серию туториалов, которые потом перевели на русский.
Соответственно, теперь куда не клюнь — ваш пострел везде поспел.
«As far asI know, there are no other tutorials for cc65 (not counting the example games over at Shiru’s site.)»
Воу, круто.
Тут еще на выходных пообщался с Кристофером который делает IDE Nesicide — он сейчас оказывается учавствует в джеме (сделать игру на NES за 48 часов) где вот: globalgamejam.org/2020/games/super-city-mayor-3
Credits:
Music by Shiru from the Famitone library.
Я из таких лоскутов это собирал что уже не вспомню, иногда просто форумы какие то. Если это точно неправда, то надо исправить и тут. Прошу проверить даже такой момент — есть ли точки входа где байты в оригинальном пзу ненулевые.
откуда инфа? что именно с бета-диском так происходит?
я вот сдуру сделал так в своём эмуляторе, и после этого стал неправильно работать TESTall:
vtrd.in/system/TEST_ALL.zip
который переходит на #3D30 явно предполагая, что выбираться с него будет уже опкод ret из ПЗУ тырдоса
а в других эмулях — unreal, spin, xpeccy — оно работает!
byte MIRRORING | (HAS_SRAM << 1) | ((MAPPER & $0F) << 4) | NAME
и тут линкер выдал ошибку «Attribute expected» которая даже не гуглится особо да и я не понимаю как линкер может такое вообще отрабатывать нормально. Если только весь байт сразу там и определить разве что, но есть ли там битовые операции?
И в теле объявления заголовка использовать эти определения, типа .byte NES_PRG_BANKS.
Уже даже не пойму какая аудитория выйдет идеальной для этого всего, уже даже закрадывается что как тот PHP-шник который стал делать выступления на конференциях как он стал писать на NES за месяц. :D
А ведь если задуматься, то такой подход (как у SjAsm) ничем не мешает и созданию кросс-платформенных форматов — генерацию каких то заголовков и служебных вещей тоже легко положить на какие то макросы из SAVEBIN OUTPUT_FILE которые обязательно надо выполнить в оговоренном порядке. В общем то дело техники. И у меня возникает подозрение, что FASM так и работает, поэтому конкретные форматы конкретных PE и COFF там дело библиотечного уровня.
Теперь и с SjAsmPlus всё понятно, спасибо.
Не оно разве?
В SjAsmPlus код в банках размещается как раз ORG'ами в одни и те же адреса и сохраняется в бинарники по мере трансляции, т.е. в те моменты, когда в нужных адресах виртуальной памяти сгенерирован нужный код, а дальше по ходу трансляции он может быть перезаписан.
Ни видел упоминаний сегментов в нескольких серьёзных исходниках, например Mighty Final Fight (под SjAsmPlus), но я тут реально слабо понимаю в том как именно в таком коде метки привязываются к переключению страниц.
У меня сложилось ощущение что просто через пару еще других ключевых слов и, вероятно, привязанных к виртуальным образам самого спектрума. Вообще не уверен.
Но разбираясь с секциями MEMORY и SEGMENTS ini-файла линкера cc65 очень быстро и легко понял как оно должно ложится на мапперы и любую структуру памяти любой машины. Это действительно сложно на первый взгляд, но понять нетрудно как и все выгоды — на самом деле даже очень просто.
Т.е. как переключать банки памяти на CA65 я понял даже быстрее чем на SjAsmPlus несмотря на то что со вторым столкнулся намного раньше.
Забавно, ведь во втором это сделано явно проще и для конкретной платформы, но глядя в документацию я не смог понять как.
А в CC65 просто поглядел пару минут в файл .ini с описаниями кусков памяти и сегментов и понял всё очень быстро.
Дальше только уточнения насчёт align и т.п. из официальной документации. И сразу понял кристально как сюда встраивать переключения банков.
Действительно вроде и сложнее, но по факту много проще.
Вероятно действительно выходит ну очень подробно и с остановкой на каждом шаге. Надеюсь так и есть.
А тут прям всё хорошо и понятно! Даже обидно, что никто не комментирует.
Я бы и сам рад, но нечего добавить :)
— Конвертер-редактор графики и экранов, а впоследствии также и составных спрайтов — NES Screen Tool, с довольно корявым, но вполне человеческим лицом. До этого были только редакторы тайлов типа Tile Layer Pro и YY-CHR, а также дикие утилиты под DOS, что очень затрудняло подготовку графики для игр. Альтернативы ему не появилось до сих пор (а надо).
— Библиотеку FamiTone, которая позволила легко и просто добавлять музыку и (решающий фактор) звуковые эффекты в игры, делая их в человеческом FamiTracker. В этом также большая заслуга jsr, Gradualore и rainwarrior, которые добавили и развили поддержку кастомных экспортёров из FamiTracker. До этого не было готового плеера, который можно было просто взять и вставить — все либо изобретали велосипед, обязательно включающий написание музыки в hex-кодах, либо приватно делились кодом. К тому же, в тот момент предпочтения в комьюнити касательно кросс-ассемблеров делились на три равные части, NESASM/asm6/CA65, код между которыми переносить довольно затруднительно, а я поддержал все три сразу. С тех пор появилось несколько альтернатив (в том числе форков моего кода), FamiTone ещё в лидерах, но его начинает теснить решение от Gradualore, которое встроили в NES Maker.
— Библиотеку neslib, которая позволила легко и просто писать на C. Ранее на сцене ходили настроения, что ничего путного сделать на C невозможно, не стоит даже и пытаться — никто и не пытался. А я видел, что делают Mojon Twins с компилятором C на ZX (как известно, ныне чурерра заполонила), и показал, что так можно было. Также я привлёк самих Mojon'ов, чтобы они показали класс (Sir Ababol и другие игры). Это в свою очередь сподвигло nesdoug'а не только самому начать писать на C, но и сделать серию туториалов, которые потом перевели на русский.
Соответственно, теперь куда не клюнь — ваш пострел везде поспел.
Когда я искал аналогичные материалы, то наткнулся на статью на хабре про Си в рамках cc65 тут habr.com/ru/post/348022/
А это перевод англоязычных статей от Nesdoug: nesdoug.com/ где если в архив заглянуть, то в первоварианте от 2018 года написано: nesdoug.files.wordpress.com/2018/07/introduction-e28093-nesdoug.pdf
Воу, круто.
Тут еще на выходных пообщался с Кристофером который делает IDE Nesicide — он сейчас оказывается учавствует в джеме (сделать игру на NES за 48 часов) где вот: globalgamejam.org/2020/games/super-city-mayor-3
xD И снова Shiru!
Ну прям респект как говорится.