Пользователь
0,0
рейтинг
22 января 2015 в 13:27

Разработка → Снимаем образы с картриджей для Dendy/Famicom/NES

Ни для кого не секрет, что сейчас можно легко скачать эмулятор почти любой игровой консоли 80х-90х и поиграть в классические игры на компьютере, телефоне и многих других платформах. В сети легко можно найти и ROM'ы этих самых игр. Зачастую люди качают их и даже не задумываются, каким же образом кто-то однажды прочитал их из картриджа. В этой статье я и постараюсь рассказать, как же это делалось в случае с NES/Famicom, которая у нас была больше известна как «Денди», и покажу, как можно сделать это самостоятельно.

image



Сразу должен сказать, что меня тут уговорили сниматься в целом многосерийном шоу на тему того, как устроены и работают игровые консоли. Поэтому публикация сегодня сразу в двух вариантах: в виде видео и по старинке в виде статьи. Кому как больше нравится, тем более целевая аудитория у каждого варианта явно разная. В статье я постараюсь раскрыть больше технических подробностей, когда видео несёт более развлекательный характер.

Видео:



(Ссылкой: www.youtube.com/watch?v=gPSpk2gbAD4)

Статья:


Итак, как же работает картридж у Famicom? Многие сразу же скажут, что это просто ROM-память с параллельным доступом, и ничего сложного в её чтении быть не должно, но это не совсем так. Во-первых, в картридже сразу два типа памяти: с кодом игры, и с изображениями из игры. Каждая из них включается прямо в шину данных консоли. Первая — параллельно с оперативной памятью и процессором (CPU), а вторая параллельно с видеопамятью и видеочипом (PPU). Таким образом картридж является чем-то вроде оперативной памяти, куда уже загружена игра.

Рассмотрим же распиновку слота картриджа, и как он работает.

image
Вид на консоль сверху. Слева — передняя часть.

→ CPU A0-A14 — контакты, через которые задаётся адрес для чтения CPU памяти
CPU D0-D7 — контакты, через которые мы передаём данные CPU памяти
→ PPU A0-A13 — контакты, через которые задаётся адрес для чтения PPU памяти
PPU D0-D7 — контакты, через которые мы передаём данные PPU памяти
→ M2 — местный clock-сигнал, принимает высокий уровень, когда идёт обращение к CPU памяти
→ /ROMSEL — логический NAND между M2 и CPU A15, который недоступен напрямую
→ CPU R/W — определяет, тип операции: высокий уровень — чтение, низкий — запись
← /IRQ — позволяет картриджу генерировать прерывание, внутри консоли подтянут к +5В
→ PPU /RD — принимает низкий уровень, когда консоль читает PPU память
→ PPU /WR — принимает низкий уровень, когда консоль пишет в PPU память
→ PPU /A13 — просто напросто инвертированный сигнал от PPU A13
← CIRAM A10 — позволяет картриджу определять принцип зеркалирования видеопамяти в консоли
← CIRAM /CE — при низком уровне включает видеопамять внутри консоли
→ Звук (вход) — тут в картридж идёт звук с аудиочипа
← Звук (вход) — тут из картриджа идёт звук в том виде, в каком мы его уже слышим
* Земля и питание — без комментариев, напряжение 5 вольт

Теперь подробнее, немного технической информации.

CPU память консоли лежит в диапазоне между 0 и $FFFF (16 бит адресации). К картриджу обычно относятся адреса $8000-$FFFF. Обратите внимание, что при этом у нас нет контакта CPU A15, который должен отвечать на старший разряд адреса. Вместо него есть /ROMSEL, который принимает низкий уровень только в случае, когда M2 и теоретический CPU A15 одновременно принимают высокий уровень. Т.е. когда консоль читает или пишет в адреса $8000-$FFFF. Поэтому обычно его можно напрямую подключить к /CE ноге ROM-памяти. Чтение или запись выбираются через CPU R/W. Зачем нужна запись в картридж? Да много зачем, но об этом ниже.

PPU память имеет адреса от 0 до $3FFF (14 бит адресации), к картриджу при этом обычно относится 0-$1FFF. Именно в этом диапазоне хранятся изображения, и это может быть как ROM, так и RAM, но картридж сам определяет, какие адреса относятся к нему, а какие к внутренней части консоли, именно для этого используется CIRAM /CE. Обычно (почти всегда) его замыкают напрямую на PPU /A13, т.е. память консоли активируется, когда A13 равно единице — в диапазоне от $2000 до $3FFF. Обратите внимание, что внутри Famicom и NES памяти ниже $2000 и нет вовсе, она обязана быть в картридже. У PPU используются отдельные контакты для чтения и записи: PPU /RD и PPU /WR. Отдельно стоит сказать про CIRAM A10 — этот контакт определяет, как зеркалируется память в диапазоне между $2000 и $2FFF внутри консоли. Обычно это важно определить в зависимости от того, как в игре происходит движение — вертикально или горизонтально. В старых играх это было жёстко задано перемычкой на плате, в более новых обычно может меняться программно во время игры.

Да, в оригинальном Фамикоме были ещё аудиовход и аудиовыход, что позволяло картриджу быть дополнительным источником звука. Использовалось это редко, но позволяло сделать музыку в играх гораздо приятнее за счёт дополнительных синтезаторов звука. В NES этих контактов уже не было. В современных китайских «Денди» и прочих клонах их тоже не припаивают. Само собой, звуковой чип из картриджа никак не сдампить.

У NES принцип работы не отличается, хотя там у картриджей уже 72 контакта: несколько идут напрямую в гнездо снизу консоли (ни разу не использовалось ни в одной игре), плюс четыре идут на чип для защиты от пиратства.

Перейдём к практике.

Итак, вроде ничего особо сложного нет. Надо просто как-то прочитать все данные по всем адресам и сохранить их в NES-файл. Для этого я решил взять два микроконтроллера ATMEGA64. Да, это очень избыточно, но мне просто нужно огромное количество ног – у картриджа их всё-таки 60. Хотя CPU и PPU память не нужно читать одновременно, и их можно было бы подключить к одним и тем же ногам, но для первого эксперимента я решил их изолировать. Тем более так гораздо проще разводить плату, двустороннюю делать мне совсем не хотелось.

image

Слот для картриджей можно и купить, это стандартный краевой разъём на 60 ног, но он почему-то везде был только под заказ, поэтому я просто выпаял его из дешёвой новодельной денди.

После сборки и печати корпуса устройство получилось таким:

image

Не буду вдаваться в подробности прошивки, выше уже изложены принципы работы с памятью, а исходники будут в конце статьи.

Всё ли так просто? Увы, на самом деле нет. Жизненный срок у NES и Famicom был достаточно долгим, и разработчики игр очень быстро (уже в 85м году) столкнулись с тем, что при таком подходе в картридж можно впихнуть очень мало информации. И вовсе не из-за его малого объема, а из-за того, что адресное пространство для кода ограничивалось этими самыми $8000-$FFFF, а это всего-то 32 килобайта. В такой размер вписывались только самые простейшие игры типа «Battle City», «Ice Climber», «Duck Hunt», «Tetris», «Lode Runner». Проще говоря, всё то, что мы привыкли видеть на сборниках типа «9999999 in 1» с повторяющимися играми.

Так в картриджи начали ставить мапперы.

image

Это такие микросхемы, которые отвечают за переключение банков памяти, в результате чего появилась возможность существенно расширить адресное пространство. Представьте, что по какому-то адресу хранится код первого уровня игры. Вы его проходите, маппер переключает банк памяти, и в результате абсолютно по тому же самому адресу считывается уже код не первого, а второго уровня. Аналогично и с видеопамятью.

Получается, что чтобы сдампить картридж, нужно заранее знать, какой в нём стоит маппер, и какие команды надо посылать ему для переключения банков памяти. И всё это всё равно было бы легко, если бы во всех картриджах стоял одинаковый маппер, ну или если бы их было всего несколько. Но существует несколько сотен разных мапперов и способов их подключения. Иногда обходились простой логической схемой, а иногда ставили очень навороченные микросхемы с кучей регистров и дополнительных функций. При этом не редкостью было, что брали какой-то популярный маппер, но подключали его необычным образом, что в корне меняло принципы взаимодействия с ним.

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

К слову, в картриджах чего только не было. Помимо ROM-памяти и мапперов туда ставили и дополнительную оперативную память (иногда с батарейкой для возможности сохраняться в игре), всякие счётчики времени, описанные выше синтезаторы звука и многое другое вплоть до модема. Увы, у нас в стране в девяностые лицензионных картриджей было днём с огнём не сыскать, а пираты не сильно заморачивались, и игры с такими наворотами тут не продавались.

Я решил реализовать хотя бы чтение игр на самых популярных мапперах. Клиентскую часть к дамперу я пишу на C#, поэтому просто описал интерфейс IMapper и класс, который соответствует каждому мапперу:

image

У каждого реализованы методы для дампинга данных. Вот как выглядит метод чтения программной памяти игры на MMC3 маппере:
        public void DumpPrg(FamicomDumperConnection dumper, List<byte> data, int size)
        {
            dumper.WritePrg(0xA001, 0);
            byte banks = (byte)(size / 0x2000);
            for (byte bank = 0; bank < banks-2; bank += 2)
            {
                Console.Write("Reading PRG banks #{0} and #{1}... ", bank, bank+1);
                dumper.WritePrg(0x8000, 6);
                dumper.WritePrg(0x8001, bank);
                dumper.WritePrg(0x8000, 7);
                dumper.WritePrg(0x8001, (byte)(bank | 1));
                data.AddRange(dumper.ReadPrg(0x8000, 0x4000));
                Console.WriteLine("OK");
            }
            Console.Write("Reading PRG banks #{0} and #{1}... ", banks-2, banks-1);
            data.AddRange(dumper.ReadPrg(0xC000, 0x4000));
            Console.WriteLine("OK");
        }

Если кому интересно, описание этого маппера можно почитать здесь: wiki.nesdev.com/w/index.php/MMC3

Я решил попробовать побыть на месте первопроходцев и сдампить картридж вот с таким необычным меню:



Для этого я прочитал сначала картридж так, как если бы там не было маппера, запустил его на эмуляторе и начал дизассемблировать. Вскоре я нашёл нужную мне инструкцию:



После этого я прочитал картридж снова, предварительно выполнив запись по адресу $B600, и получил уже вполне работоспособный ROM. Само собой, игры в нём не запускаются, ведь для этого нужно снова переключать банки памяти. И даже если я прослежу, что же происходит в момент выбора игры в меню, и прочитаю весь картридж, эмулятор скорее всего никак не сможет всё это запустить.

Ещё мне в руки попал лицензионный картридж одной из самых культовых игр тех времён — «The Legend of Zelda». Он без проблем работает и с дампером, и с Фамикомом через простой пассивный переходник. Делать дамп этой игры смысла нет, она заинтересовала меня другим. В этом картридже стоит дополнительная RAM память и батарейка, что позволяет сохраняться в игре. Лежит эта память в диапазоне $6000-$7FFF. Я попробовал её прочитать и скормить эмулятору. Он без проблем её понял. После этого я ради эксперимента решил увеличить в ней число сердечек и записать назад в картридж. Сработало.



Получилась забавная возможность переносить сохранения между эмулятором и реальной консолью.

Многие наверное спросят, зачем я вообще за это взялся, когда почти любой ROM можно найти в сети. Да банально из любопытства и самообразования. Было интересно посмотреть, что происходит внутри этих картриджей, и как всё это работает. К тому же им можно как читать, так и записывать картриджи. Но об этом в следующий раз.

Ссылки на исходники:
github.com/ClusterM/famicom-dumper — сам дампер (исходники на C, разводка платы, 3D модельки корпуса)
github.com/ClusterM/famicom-dumper-client — клиент на C#
Cluster @ClusterM
карма
266,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (77)

  • 0
    А нельзя ли автоматизировать подход, путем поиска опкода инструкции по записи в память? Возможны, конечно, ложные срабатывания, но, думаю, что это сильно сузит круг подозреваемых мапперов, особенно для опытного специалиста. Можно вообще даже сделать эвристику, зная то, как ведут себя извесные мапперы.

    P.S.: Я имею ввиду автоматизированный подход без использования дизассемблера
    • +2
      Там могут быть очень хитрые условия переключения банков. Но если заранее знать, что в картридже стоит какой-то из популярных мапперов, то теоретически можно сделать. Но в таких случаях проще перебором.
      • 0
        Я так понимаю, что в любом случае переключение осуществляется через запись в память, поэтому отправная точка — это поиск этого места в бинарном коде.

        Ну и ламерский вопрос: а взор с лупой на микросхему не даёт ответа на этот вопрос?
        • 0
          Да, но эта операция может выполняться очень условно. Не всегда очевидно, как оно работает.
          Если картридж оригинальный лицензионный, то там обычно видно, какой стоит маппер (на фото в посте как раз есть), но в современных китайских стоят бескорпусные микросхемы.
    • +1
      Санчез просил показать :)
      www.youtube.com/watch?v=jnOPwUJCvmQ
      www.youtube.com/watch?v=wRORWjdERcU
      www.youtube.com/watch?v=fSX9N9Sq_sA

      Не знаю, как именно он всё это делает. Видно, что кеширует данные, но непонятно, как именно он отслеживает, когда банк переключился.
      • 0
        Там походу эмулятор исполняет игру, и когда случается write, эмулятор прерывается даёт сигнал дамперу о том, что появился новый банк.
        • 0
          Запись в память картриджа не всегда переключает банки, иногда это может делаться много раз в секунду. И не только запись в область картриджа может переключать банки.
          • 0
            Да, но видимо эмулятор знает про разные типы эмуляторов и фильтрует неимеющие к переключению банков записи.
            • 0
              Так смысл тогда теряется, если эмулятор знает :) В таком случае проще картридж целиком сдампить и эмулировать. Ретрон вроде так и делает.
              • 0
                Как это смысл теряется? Эмулятор тут как раз вспомогательный инструмент для того, чтобы сдампить картридж и не ковыряться в ассемблере.
                • 0
                  Вы противоречите сами себе. Если софт уже знает маппер, то уже не нужно ни ковыряться в ассемблере, ни использовать эмулятор. А если не знает, то возникает вышеописанная проблема.
                  • 0
                    Секундочку. Софт не знает маппер априори. Но может догадаться эвристически, зная как управляются известные софту мапперы и видя как и куда происходит запись. Это можно автоматизировать. А руками и глазками придется искать дольше.
                    • 0
                      Слишком уж многие мапперы реагируют на абсолютно одинаковые операции, но дают разный результат. Но вообще да, теоретически так можно автоматически определять их. Но смысл всё равно сомнительный. Всё несдампленное обычно на каких-то ещё неизвестных мапперах.
      • 0
        Ха, вот это мой девайс. С эмулем все как раз просто: программа сама говорит когда и что записать, Копифамиклон просто пересылает в эмуль изменившиеся данные. Так как это требует некоторого времени, эмулятор их кеширует. Так что самый 100% вариант дампинга неизвестной игры — прогнать ее на таком устройстве. С другой стороны, в игре могут быть неиспользуемые блоки или для дампинга некоторых придется пройти всю игру.
        • 0
          А как оно узнаёт, когда данные изменились? Устройство держит в себе какой-то кеш и уведомляет эмулятор при изменении данных? Эмулятор же в таком случае должен каждый раз к железу обращаться, разве нет? Или проверка идёт только после записи в 0x6000-0xFFFF?
          • 0
            Никакого кэша в железе. Действительно, в эмуляторе ведется мониторинг записи в адреса 0x6000-0xFFFF, при обнаружении таковой, эмуляция ставится на паузу и делается подобная запись на копифамиклоне. Затем вычитывается новое состояние, которое кэшируется эмулятором. И так до следующей записи.
            • 0
              Но этот метод не является 100% универсальным. И для полноценного дампа надо же всё равно вручную разбираться в принципах работы маппера.
              • 0
                Он таки как раз универсален и не зависит от маппера вообще. А вот 100% полноту дампа не гарантирует, о чем я и сказал выше.
                • 0
                  Ну просто нет гарантии, что маппер реагирует именно на запись в 0x6000-0xFFFF, хоть это и в 99% случаев так. Ну и потом всё равно надо сидеть и разбираться, где какой банк, и как они переключаются, чтобы сделать полноценный ROM.
  • 0
    А вы не имели опыта «пересадки» палитры? Я знаю из какой игры заставка в последней многоигровке — это «Король Лев» для сеги и там нормальные цвета, есть пиратский порт на фамиком — но там цвета тихий ужас (подозреваю что пираты повредили палитру), я все пытался — но неосилил.
    • +1
      А на NES скорее всего красивее и не сделать из-за ограничений палитры. В пиратском порте Короля Льва на NES вроде такие же цвета, если мне память не изменяет.
    • 0
      А нет ли у Вас нормального порта «Короля Льва» под NES, чтобы нормально запускался? У меня есть 2 разных и несколько эмуляторов, но то игра виснет на стартовом экране, то экран жутко трясет вверх-вниз пикселей на 8. Палитру, насколько мне известно, можно в случае крайней необходимости задать руками в каком-нибудь FCEUX.
      • 0
        Именно пиратского порта со SNES? У меня есть, есть ещё порт на MMC3.
      • 0
        Есть — вечером могу скинуть, на NESTOPIA идет на ура, но там явно «битая» палитра, Игра выглядет по краскам где-то уровня 2600 атари.
        • 0
          ClusterM Psionic Порылся в закромах и нашел у себя аж два порта. И даже решил проблему с трясущимся, поменяв регион с автоматического на PAL. Будет любопытно, если у нас у всех разные порты.
          • 0
            Вот этот дамп.
            vk.com/doc29443603_361179277
          • 0
            По ссылке ниже ужаснейший официальный порт с геймбоя. Это очень странный случай, когда пиратский порт на голову выше по качеству.
            У меня есть порты от конторы «Supergame». Если надо, пишите в личку.
  • 0
    Шикарно! Спасибо. Сильно ли отличаются картриджи для Sega, SNES, N64?
    • +1
      По поводу переключения банков памяти пока не вникал, но везде вплоть до GBA принципы похожие — память с параллельным доступом, которая включается прямо в шину. Потом стали использовать последовательный доступ и шифрование.
  • +14
    Помню, в 90х годах я сдампил один многоигровой картридж с маппером. Шел тем путем, как описанные в статье первопроходцы: сначала сдампил первый банк, потом продизассемблировал его (код меню выбора и запуска игры). Нашел, как программируется маппер и тогда уже считал (подключив картридж через переходник к программатору УФППЗУ) из него все данные. Получилось 256Кб, из них 128 — графика.

    При этом дизассемблер 6502 был собственной разработки. Он работал на ZX Spectrum (кросс-дизассемблер). Все это делалось в рамках проекта «контроллер дисковода для Dendy». Проект так и не был завершен, не в последнюю очередь — из-за мапперов и прочей аппаратуры, которую ставили на картриджи и которую никак нельзя было в универсальном виде поставить на контроллер дисковода. Ну и из-за обнаружившейся чрезвычайной трудоемкости считывания и адаптации картриджей. Над каждым пришлось бы корпеть днями.
  • +4
    О, спасибо! Первая интересная статья в этом году.
  • +2
    Отличная статья!

    Кстати, не помешал бы мощный холивар на хабре на тему рейтинга консольных игр. У меня сейчас в PSP почти всё, кроме NeoGeo. Реально доставляет запускать игру 1981 года и играть, получая удовольствие. Ъ игр уже почти не делают.
  • +2
    Инетесно :) не только статьи Ализара угадываются по заголовку
    • 0
      Отнюдь. Про «умный дом» не было )
      • 0
        А про приставки было.
        Половину статей ClusterM по заголовку угадал, когда они выходили :)
  • 0
    Огромное спасибо!
  • 0
    А сделали бы адресацию сразу 32-х битной и проблемы бы такой не было как класса.

    P.S.
    Будешь много играть на приставке — сядет трубка :P
    • 0
      32-х битная шина на 6502 и в 1983м году? Тогда очень важно было сделать игровую консоль дешёвой.
    • –1
      640кб хватит всем!
      • +2
        Вы не поверите, хватало. И игрушки были загляденье. А попроси среднего современного тыжпрограммиста написать игру, уложившись в 32К?
        • +1
          Я знаю о чем речь(у меня был Pentagon128, ещё можно заглянуть мне в профиль), но
          А сделали бы адресацию сразу 32-х битной и проблемы бы такой не было как класса.
          звучит подобно
          640кб хватит всем!
          , однако теперь нам и 32-х битов не хватает :)
        • +1
          Дайте мне прямой доступ к оборудованию, чтоб ОС не мешалась, и 16-разрядный код, чтоб команды много места не жрали — и можно даже в 4к уложиться. За примерами далеко ходить не надо, под DOS и сейчас средней криворукости кодер не то что на ASM'е — даже на Turbo Pascal 7.0 может написать простенькую игрушку, уложившись в 32к.
          В начале даём:
          {$A-,B-,D-,E-,F-,G-,I-,L-,N-,O-,P-,Q-,R-,S-,T-,V+,X+} {$M 16384,0,655360}
          потом:
          asm
           mov ax,13h
           int 10h

          Ну и дальше как-то через mem[$A000:i]:=...
          Минимум документации (всего пара книжек), минимум кодерского скилла — и оно легко напишется и будет работать. ИМХО даже проще и понятнее, чем инициализировать DirectX или написать шейдера в WebGL.
          Недаром же говорят — если хочешь уменьшить размер программы минимум на порядок, начни с того, что выкинь все фреймворки.
  • 0
    Очень интересная статья! Спасибо. А какие ваши дальнейшие планы на статьи/ видео? В принципе, с удовольствие посмотрел бы на разработку клона nes/famicom хоть на ориганальном железе, хоть на плис:) касательно первопроходцев — если речь о тех, кто спиративал игры. То, думаю там в большинстве случаев было завладевание исходных кодов игр. Иначе как объяснить всяческие изменения в число жизней, замену текстур и т.д. Не диссасемблили же они игры) второй вариант — тупо считывали 2 пзушки и перезаписывали их.
    • +1
      Про дальнейшие планы пока секрет.
      Конечно дизассемблировали. По вашей логике у создателей Game Genie должны были быть исходные коды абсолютно всех игр, ведь именно они были первоисточником всех патчей в те годы. Да и не было бы особого смысла в исходниках, они всё равно на ассемблере писались. Текстуры же легко заменяются без изменения кода игры.
      • 0
        Про текстуры плохой пример — согласен.
        Просто, например, зачем потенциальному пирату лезть в код игры, если он может скопировать ROM и реверснуть плату картриджа. Это кажется как-то более простым.
        Дизассемблерованный код изучать — не самое приятное занятие.
        Это так — просто мысли. Я картриджами для NES особо не интересовался ранее.
        • +1
          Недооцениваете Вы китайцев :)
  • +1
    Здесь категорически не хватает уютненьго одного известного дампера — cah4e3.shedevr.org.ru/dumping_2015.php
    • +1
      До Санчеза мне явно далеко. На мои просьбы о помощи он отреагировал как-то неоднозначно…
      • +4
        Это одиозная фигура, получившая широкую известность еще в те далёкие времена, когда ромы лежали только на pristavka.kulichki.net, a цвет эму-сцены обитал исключительно на emu-russia.km.ru/forum. И даже тогда Санч был не сильно охоч к помощи новичкам. Сейчас он активно принимает участие в разработке Demul и даже там резко отсекает любое проявление некомпетентности в вопросах Dreamcast.
        К сожалению, те люди, которые легко уживались с нубасами на эмураше сейчас воспринимают современных новичков весьма враждебно.
        • 0
          У Hardwareman, вроде, был аккаунт здесь, а сейчас не могу найти.
          • 0
            ХВМ куда проще в общении. На правильно поставленные вопросы он, зачастую, даёт развёрнутые адекватные ответы.
          • 0
            Никогда не было, теперь есть. Люди слезно попросили. :3
  • 0
    Кстати, интересно, по какому алгоритму из двух ромов склеивается файл .nes?
    • 0
      Там сначала идёт простенький заголовок на 16 байт, в котором указывается маппер, мирроринг, размер программной памяти, размер памяти с изображениями и прочие параметры. После него идут все данные по очереди. Погуглите структуру NES-файла, там ничего особенного.

      Вот тут у меня класс, который разбирает и собирает nes-файлы: github.com/ClusterM/famicom-dumper-client/blob/master/NesFile.cs
      • 0
        Понял, спасибо!
        • 0
          В свое время описывал в рамках своего проекта NES-файл. А в конце еще захотел сделать обратную операцию: сделать картридж. :)
      • 0
        А поясните, пожалуйста, для чего в NES-файле вообще указывать маппер? Ведь у эмуляторов нет ограничений по разрядности шины и данные в NES хранятся, насколько я понимаю, не постранично, а сплошным потоком.
        • 0
          Игра-то при этом умеет только с 16-разрядной шиной работать. Данные в NES-файлах хранятся именно постранично.
  • +2
    Круто. А вот нельзя ли сделать наоборот? Например: В офис программеров-олдфагов, выросших на денди, покупается теплая ламповая приставка. Но где брать картриджи? В сети полно дампов. Может ли быть некое устройство, с одной стороны которого втыкается флешка с дампами, а другой стороной устройство вставляется в приставку?
    • 0
      Да, можно. Я хотел сделать что-то подобное, да что уж там, до сих пор хочу. Приставка, пусть и китайский клон всё же как-то теплее и ламповее эмуляторов. Но вот со временем плохо.

      Само устройство-то не сложное — считываешь файл рома, по запросу приставки отдаёшь ей данные.
      Есть нюанс с мапперами, которые необходимо эмулировать. Впрочем, если ром играется на эмуляторе, значит, маппер известен как минимум этому эмулятору. Т.е. информацию найти можно.

      Ещё нюанс — выбор игры. Не скажу, что не решаемая проблема, но нужно написать как-минимум авто-генератор меню со списком файлов. А для этого уже требуются более глубокие знания, чем «протокол обмена информацией картриджа с приставкой».

      Хотя это всё теория.
    • 0
      Так есть уже. stuffpoint.ru/index.php?route=product/category&path=60 например. Только стоит заоблачно (и у китайцев не дешевле)
      • 0
        да, что-то с ценами у них беда прям. И список поддерживаемых мапперов небольшой
        • 0
          Ну, 135 мапперов поддерживается, 86 — нет. Не так и мало. (плюс, говорят, мапперы реализованы в софте => могут добавляться)
        • 0
          Курс вырос же.
          Брал в прошлом году там версии для Famicom и для Sega Genesis — пока на данный момент это самые функциональные картриджи.
          Для NES еще есть российская разработка: ramfactory.com/
          Ну и на их форуме можно почитать по поддержке мапперов.
          Ценник немного меньше, но все равно не маленький.
          • 0
            Что-то не вижу у них для NES, только для SNES и Megadrive
          • 0
            У меня значительно дешевле по деталям получается, если без мультирома. Хотя зачем мультиром на домашней консоли — я не знаю.
            • 0
              Вся прелесть в поддержке довольно большого количества мапперов.
              И удобстве использования.
              Залил на карту ромы, вставил в консоль и играешь.
              • 0
                Поддержку нужного маппера самому сделать не сложно, они все отлично документированы.
                Мультиром удобен для посиделок с друзьями. Если играть самому, то обычно достаточно записать какую-то одну игру.
                • 0
                  «Все» — имеется в виду нумерные, конечно.
                  И я не спорю, что мультиром и возможность использовать SD карту — это очень удобно. Но при такой цене и нынешнем положении в экономике многие задумаются — нужно ли оно.
    • 0
      Всё будет. Нам же ещё много серий для шоу снимать, а вы хотите всё и сразу :)
  • 0
    Первый раз вижу доходчивое объяснение, как работают мапперы. Я думал, что их реверсят аппаратно, а тут вполне себе оказывается, что дампинг страниц + дизассемблер вполне могут восстановить логику их работы.
    • 0
      Аппаратно тоже: forums.nesdev.com/viewtopic.php?t=8781
    • 0
      Можно и аппаратно. Иногда разбираешь картридж и видишь, что на нем, кроме «капель-ПЗУ», стоит микросхема — регистр. Можно бывает проследить связи регистра с сигналами и понять, как он управляется. Но в общем случае маппер может быть встроен в ту же каплю, где находится ПЗУ. Такое аппаратному реверсу тоже подлежит, но гораздо более затратно и трудоемко, чем дизассемблер.
  • +1
    Отлично. Очень хорошо выдержан баланс глубины изложения, при высоком уровне технической грамотности. Невозможно даже представить, что бы в современных СМИ появилось бы нечто подобное. Вам точно стоит развивать направление технического видеоблоггинга.
  • 0
    А возможно ли подключить картридж не к USB, а к LPT-порту? Это позволило бы сэкономить на микроконтроллерах и не связываться с разводкой платы.
    • 0
      Ног не хватит. Но можно попробовать использовать несколько логических схем.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.