Хехехе, первая тестовая программа с обильными комментариями на русском готова и крутится в эмуляторе:
Так что скоро наверное будет вторая часть. Правда таки разрываюсь на тему того не сделать ли сперва одну часть краткого введения в ассемблер и архитектуру MOS 6502 чтобы статья в целом лучше заходила тем кто в этом ни бум-бум изначально, а так, из Си пришёл. Хм…
Аллилуйя! Автор Nesicide наконец то устал с чем то там разбираться на своей стороне и добавил поддержку utf-8 и убрал дурацкое насильное автодополнение единственного оставшегося выбора в списке автодополнений (последнее вообще съедало мозг). Если кто-то из любопытства качал сборку для виндовс из-за этого поста, то обязательно перекачайте архив и зайдите в настройки среды — там настройки редактора и поставьте Encoding в utf-8.
Еще у меня есть вопрос к старожилам ресурса — недавно развлекаясь с нереализованными в детстве идеями на ZX Spectrum я написал еще две статьи на менее профильном ресурсе: Перехват прерываний на ZX Spectrum
и как бы её продолжение: Многопоточность на ZX Spectrum
Я знаю что про перехват прерываний не писал только ленивый и возможно это уже просто моветон. Про многопоточность вроде меньше материалов — поэтому вопрос: стоит ли тащить что либо из этого сюда?
файл в таком формате состоит минимум из трёх идущих друг за другом секций
Всё же минимум из двух. Секция графики часто может отсутствовать, это типично для UNROM-подобных конфигураций. Даже базовый NROM в принципе может не иметь секцию графики, а использовать CHR RAM либо даже собственное ОЗУ видеоконтроллера (на железе есть трюк, позволяющий замаппить 2K видеопамяти как память тайлов).
:) Я, кстати, немного сравнивал Z8000 с i8086 по разным возможностям и в целом — забавно.
Как уже написано у Z8000 16 РОН и 8Мб сегментируемой памяти. При этом сегменты сделаны еще круче, чем в i8086 — вместо того чтобы держать отдельные сегментные регистры при сегментированной памяти адресация памяти через регистры автоматически подразумевает, что в чётных регистрах содержится номер сегмента (в верхнем байте), а в нечётных — смещение в сегменте. Т.е. косвенная адресация через регистры возможна с восемью 32-битными регистровыми парами 16-битных регистров R0-R15 которые уже называются RR0-RR14 (и могут быть только чётными номерами). Объединение в регистровые пары — характерная черта i8080/Z80 которая в Z8000 присутствует вплоть до 64-битных регистров RQ0,RQ4,RQ8,RQ12 видимо для операций длинного деления — разбираться не стал.
Дальше-больше. Если в i8086 подытожить все формы адресации, то их можно выразить самой комплексной формой:
[bx|bp+di|si+offset]
Т.е. или bx или bp сложенный с или di или si плюс смещение, при этом любая часть могла быть выкинута из выражения.
А вот в Z8000 самая сложная адресация возможная в любой команде — это [Rx+offset], где Rx это любой из шестнадцати его регистров кроме R0. А самая сложная адресация [Rx+Ry] где так же Rx и Ry это любые регистры кроме R0 возможна только в операциях передачи данных. С одной стороны вроде и менее сложные адресации, но с другой стороны этого более чем достаточно для эффективной адресации стековых переменных, а с другой стороны нет ограничений никаких какие именно регистры могут выступать в роли индексных, так что всё это немного похоже на современные RISC по возможностям.
Еще на англовики можно прочитать, что Z8000 неоднократно использовался в машинах на базе Unix. Чем же он был для них так привлекателен по сравнению с i8086? А вот чем:
Дело в том, что у Z8000 был дополнительный чип в _возможной_ обвязке — Z8010 именуемый еще Memory Managment Unit или MMU.
Так как сам Z8000 (точнее первая модель — Z8001) уже имел сегментированную память на 23 бита (8Мб) состоящую из 128 сегментов по 64Кб, то наличие MMU вроде бы смущает — казалось бы зачем?
Так вот как раз это самое — обеспечивать аппаратную защиту памяти read-only, code-only, data-only и system сегментов.
MMU ставился между процессором и памятью и обычные сегменты Z8010 становились «логическим адресным пространством», а аппаратный маппинг MMU уже превращал их в физические. Как я понял возможен даже трюк с шарингом одного сегмента в физической памяти между несколькими логическими сегментами разных процессов чтобы, допустим, на коде тех же DLL-ек экономить.
Забавно, что в один MMU вмещались дескрипторы только 64 сегментов, поэтому с одним MMU Z8000 мог обрабатывать в защите только 4Мб из 8 возможных.
Но достаточно было поставить еще один MMU в пару к другому — и возможно было обрабатывать аппаратной защитой все 128 возможных сегментов.
Но хуже того — можно было впаять и 4 MMU и сделать 16Мб физической памяти — и тогда с помощью MMU можно было разбрасывать задачи по 24-битному физическому адресному пространству хотя логические адреса конкретной задачи оставались 23-битными.
В общем Z8000 был реально не промах и наверное даже жаль, что его звезда закатилась. :)
Очень странно, ибо это реальный пакет где просто распаковываешь IDE, запускаешь, делаешь New->Project->From template и имеешь рабочий код который прямо в IDE же можно отлаживать проходясь отладчиком по реальным строкам кода, а не каким то там символам из отладочного файла. И всё это в ассемблере ca65 и всё это прям без проблем (ну кроме некоторых).
Может годы назад проект был глючным и не катил, да и сейчас вот глюки есть, но альтернатив я на горизонтах просто не заметил.
NESICIDE крайне малопопулярен, за исключением автора его почти никто не использует, а процент русскоязычных разработчиков для NES сам по себе крайне невелик, так что наличие около нуля русскоязычных пользователей до настоящего момента было вполне ожидаемо. По причине непопулярности заточенных именно под него статей с пошаговыми инструкциями я не припоминаю.
Весело девки пляшут. Довольно быстро обнаружил, что редактор Nesicide не воспринимает русские буквы ни под каким соусом — заменяет их на знаки вопроса хоть при вводе с клавиатуры хоть при загрузке из файла. А как мне комментарии писать для туториалов на русском то?
Залез на гитхаб в проект и посмотрел там на код. Оказалось, что для редактора используется компонента QsciScintilla у которой в документации по методу setUtf8 чёрным по белому написано:
Sets the current text encoding. If cp is true then UTF8 is used, otherwise Latin1 is used.
И конечно же оказалось, что нигде в коде инициализации setUtf8( true ) не вызывается.
Вот так да, все годы существования Nesicide автор похоже и не подозревал, что редактор в нём ничего кроме латиницы с некоторой диакритикой не воспринимает принципиально! И никто не пожаловался! =8()
В общем я сказал и автор пообещал исправить в следующих релизах. :)
P.S.
Вот опять таки посмотрел статьи migera по ссылке из начала статьи — хорошая информация, но опять не про то как сесть и начать программировать конкретный код с конкретными эффектами конкретными инструментами, а больше справочная информация. Мне же хочется написать именно такую статью, что садишься за неё, а через несколько часов встаёшь уже с работающим кодом в работающей среде никуда больше не заглядывая особо.
А есть на примете какие-нибудь русскоязычные руководства в том духе о котором я пишу — чтобы от установки Nesicide и по каждому аспекту отдельно и нудно проходилось? Просто чтобы не писать одно и то же, а как то изменить точку зрения по сравнению с существующими аналогами.
Со времён этой заметки появилось ещё некоторое количество статей и на английском и на русском. Но писать всё равно стоит. Во-первых, время идёт, инструменты меняются, обновляются и устаревают. Во-вторых, иметь варианты всегда хорошо, не пошло дело по одному гайду (автор непонятно объясняет, читатель почему-то не понимает) — хорошо иметь другой. Ну и просто лишнее напоминание публике о том, что есть такая возможность, писать под подобные старые платформы.
Начал сам знакомится с программированием на ассемблере через Nesicide уже пару вечеров и уже начало получаться и начала складываться картинка как оно вообще происходит, что за куски памяти и сегменты описываются в одном файле, судя по всему начинаю уже догадываться как их натягивать на мапперы и на экране символ уже инкрементируется в цикле, после GBA в принципе это уже конечно детали и тонкости.
И вот тут возникает вопрос — есть смысл писать на русском введение в программирование на NES по лекалам как я написал про GBA — от скачивания среды и через поэтапную реализацию всех нужных техник для создания игры или что-то такое уже есть? Есть ли на английском даже — и то вопрос?
наоборот — у процессов разные стеки и регистры, а вот память как программ так и глобальных данных общая, поэтому нельзя модифицировать код или полагаться в работе на перезаписываемые глобальные переменные.
Так что скоро наверное будет вторая часть. Правда таки разрываюсь на тему того не сделать ли сперва одну часть краткого введения в ассемблер и архитектуру MOS 6502 чтобы статья в целом лучше заходила тем кто в этом ни бум-бум изначально, а так, из Си пришёл. Хм…
Перехват прерываний на ZX Spectrum
и как бы её продолжение:
Многопоточность на ZX Spectrum
Я знаю что про перехват прерываний не писал только ленивый и возможно это уже просто моветон. Про многопоточность вроде меньше материалов — поэтому вопрос: стоит ли тащить что либо из этого сюда?
Эмм… интересно конечно же как? Маппер VRAM который возвращает на верхние линии адреса частично состояние нижних?
Как уже написано у Z8000 16 РОН и 8Мб сегментируемой памяти. При этом сегменты сделаны еще круче, чем в i8086 — вместо того чтобы держать отдельные сегментные регистры при сегментированной памяти адресация памяти через регистры автоматически подразумевает, что в чётных регистрах содержится номер сегмента (в верхнем байте), а в нечётных — смещение в сегменте. Т.е. косвенная адресация через регистры возможна с восемью 32-битными регистровыми парами 16-битных регистров R0-R15 которые уже называются RR0-RR14 (и могут быть только чётными номерами). Объединение в регистровые пары — характерная черта i8080/Z80 которая в Z8000 присутствует вплоть до 64-битных регистров RQ0,RQ4,RQ8,RQ12 видимо для операций длинного деления — разбираться не стал.
Дальше-больше. Если в i8086 подытожить все формы адресации, то их можно выразить самой комплексной формой:
Т.е. или bx или bp сложенный с или di или si плюс смещение, при этом любая часть могла быть выкинута из выражения.
А вот в Z8000 самая сложная адресация возможная в любой команде — это [Rx+offset], где Rx это любой из шестнадцати его регистров кроме R0. А самая сложная адресация [Rx+Ry] где так же Rx и Ry это любые регистры кроме R0 возможна только в операциях передачи данных. С одной стороны вроде и менее сложные адресации, но с другой стороны этого более чем достаточно для эффективной адресации стековых переменных, а с другой стороны нет ограничений никаких какие именно регистры могут выступать в роли индексных, так что всё это немного похоже на современные RISC по возможностям.
Еще на англовики можно прочитать, что Z8000 неоднократно использовался в машинах на базе Unix. Чем же он был для них так привлекателен по сравнению с i8086? А вот чем:
Дело в том, что у Z8000 был дополнительный чип в _возможной_ обвязке — Z8010 именуемый еще Memory Managment Unit или MMU.
Так как сам Z8000 (точнее первая модель — Z8001) уже имел сегментированную память на 23 бита (8Мб) состоящую из 128 сегментов по 64Кб, то наличие MMU вроде бы смущает — казалось бы зачем?
Так вот как раз это самое — обеспечивать аппаратную защиту памяти read-only, code-only, data-only и system сегментов.
MMU ставился между процессором и памятью и обычные сегменты Z8010 становились «логическим адресным пространством», а аппаратный маппинг MMU уже превращал их в физические. Как я понял возможен даже трюк с шарингом одного сегмента в физической памяти между несколькими логическими сегментами разных процессов чтобы, допустим, на коде тех же DLL-ек экономить.
Забавно, что в один MMU вмещались дескрипторы только 64 сегментов, поэтому с одним MMU Z8000 мог обрабатывать в защите только 4Мб из 8 возможных.
Но достаточно было поставить еще один MMU в пару к другому — и возможно было обрабатывать аппаратной защитой все 128 возможных сегментов.
Но хуже того — можно было впаять и 4 MMU и сделать 16Мб физической памяти — и тогда с помощью MMU можно было разбрасывать задачи по 24-битному физическому адресному пространству хотя логические адреса конкретной задачи оставались 23-битными.
В общем Z8000 был реально не промах и наверное даже жаль, что его звезда закатилась. :)
Регистров было бы в 2 раза больше :-)
Чем больше, тем лучше. Обязательно пишите ещё!
Может годы назад проект был глючным и не катил, да и сейчас вот глюки есть, но альтернатив я на горизонтах просто не заметил.
Залез на гитхаб в проект и посмотрел там на код. Оказалось, что для редактора используется компонента QsciScintilla у которой в документации по методу setUtf8 чёрным по белому написано:
И конечно же оказалось, что нигде в коде инициализации setUtf8( true ) не вызывается.
Вот так да, все годы существования Nesicide автор похоже и не подозревал, что редактор в нём ничего кроме латиницы с некоторой диакритикой не воспринимает принципиально! И никто не пожаловался! =8()
В общем я сказал и автор пообещал исправить в следующих релизах. :)
Вот опять таки посмотрел статьи migera по ссылке из начала статьи — хорошая информация, но опять не про то как сесть и начать программировать конкретный код с конкретными эффектами конкретными инструментами, а больше справочная информация. Мне же хочется написать именно такую статью, что садишься за неё, а через несколько часов встаёшь уже с работающим кодом в работающей среде никуда больше не заглядывая особо.
И вот тут возникает вопрос — есть смысл писать на русском введение в программирование на NES по лекалам как я написал про GBA — от скачивания среды и через поэтапную реализацию всех нужных техник для создания игры или что-то такое уже есть? Есть ли на английском даже — и то вопрос?