Пишем CHIP-8 эмулятор с использованием Rust и WebAssembly (часть 2)
Запись от loothood размещена 25.12.2017 в 23:11
Показов 1753
Комментарии 0
|
(Исходную статью я разбил на две части. Оригинал) Первую часть перевода можно почитать тут Работа с памятью Создание интерфейса с помощью WebAssembly может быть довольно сложным. WebAssembly поддерживает только четыре базовых типа, поэтому передача чего-либо более сложного на границе WebAssembly/JavaScript требует некоторого кодирования/декодирования. WebAssembly и JavaScript работают с общей памятью, к которой оба имеют на чтение и изменение. Данные могут быть общими через общие ячейки памяти. Например, у эмулятора CHIP-8 всего 4Кб памяти, которая определена структурами и экспортируется следующим способом:
На стороне JavaScript, мы можем получить доступ к этой памяти с помощью exports.memory. С помощью функции get_memory, к 4Кб памяти CHIP-8 можно получить доступ так:
Загрузка ROM в память так же проста. Сброс CPU (сбрасывает регистры и т.д.), а затем происходит запись в массив programMemory:
Чтение дисплея или регистра значений использует тот же подход, что и выше. Немного Rust Я новичок в Rust(около двух недель), потому я не привожу много своего кода. Боюсь показаться глупым из-за очевидных ошибок. Мой опыт использования Rust очень вдохновляет. Язык гораздо более строгий, чем те языки что я использовал до этого. Это другой конец палки, если сравнивать его с JavaScript. Кроме того, Rust современен и элегантен. По-моему, самая сложная концепция, к которой придется привыкнуть - это концепция владения Rust. Я работал с несколькими методами управления памятью (сборщик мусора, автоматический подсчет ссылок), однако концепция владения Rust, где у вас есть единственное изменяемое связывание с ресурсом, нова для меня. Часть эмулятора CHIP-8, которая по-моему получилось особенно хорошо, это метод execute_opcode. Инструкции CHIP-8 имеют длину 16 бит, как описано в этой технической справочной информации. Для некоторых инструкций первый полубайт (4 бита) представляет код операции, а остальные полубайты кодируют данные кода операции. Например, операция «jump» обновляют счетчик программы с определенным адресом. Он кодируется как 0x1nnn, где первое значение 0x1 кодирует операцию перехода, а следующие три(nnn) - представляют адрес. Сопоставление шаблонов с диапазонами в Rust - идеальный инструмент для реализации этого. Вот пример, который использует соответствие диапазонов для реализации инструкции перехода:
Управление зависимостями Rust упаковывает в пакет(crates) повторно используемые компоненты, которыми управляет cargo. Это очень похоже на npm, CocoaPods и другие менеджеры пакетов. В моем проекте было несколько пакетов(crates), которые полезны для использования: - rand- генерация случайных чисел. - lazy_static - в Rust вы не можете вызвать функцию, чтобы построить статическое значение, поэтому вы не можете использовать функцию-конструктор. Ленивый статический макрос позволяет вам инициализировать статические переменные лениво, избегая этого ограничения. К сожалению, я столкнулся с трудностями при интеграции этих пакетов в мой проект. Пакеты имеют зависимость от платформы, потому их пришлось доработать чтобы подружить их с WebAssembly. Я нашел форк с некоторыми необходимыми изменениями, но изменения не все, которые были мне необходимы. В моем случае, я просто взял реализацию случайных чисел и скопировал в ской код и отказался от ленивой инициализации. Заключение Я в самом деле впечатлен языком Rust. Уверен что WebAssembly - отличная возможность по привлечению программистов для этого языка. В краткосрочной перспективе выбор языка для WebAssembly немного ограничен. Для веб разработчиков, которые хотят попробовать что-то новое, Rust выглядит как самый лучший вариант на данный момент. Код проекта на гитхаб | ||||||||||||||||||||||||||||||||||||||||
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 0
Комментарии


