<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rafael Leandro</title>
    <description>The latest articles on DEV Community by Rafael Leandro (@raafas).</description>
    <link>https://dev.to/raafas</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F658540%2F95475c82-8b3a-4601-86b5-75d48bf5a50e.png</url>
      <title>DEV Community: Rafael Leandro</title>
      <link>https://dev.to/raafas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/raafas"/>
    <language>en</language>
    <item>
      <title>Gerenciando versões iOS automaticamente sem ferramentas externas</title>
      <dc:creator>Rafael Leandro</dc:creator>
      <pubDate>Mon, 18 Nov 2024 15:31:30 +0000</pubDate>
      <link>https://dev.to/raafas/gerenciando-versoes-ios-automaticamente-sem-ferramentas-externas-3n8e</link>
      <guid>https://dev.to/raafas/gerenciando-versoes-ios-automaticamente-sem-ferramentas-externas-3n8e</guid>
      <description>&lt;h3&gt;
  
  
  TL;DR:
&lt;/h3&gt;

&lt;p&gt;Vai, apressadinho: &lt;code&gt;agvtool --help&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Capítulo 1: Um longo esperado reencontro
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7al238rcja89xtrpxo8g.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7al238rcja89xtrpxo8g.jpg" width="400" height="532"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Estava num pré-feriadão, tranquilo e feliz até precisar fazer uma release do SDK que mantenho no trabalho e o Fastlane estava quebrando o .xcodeproj.&lt;br&gt;
Esse script recebia uma versão por parâmetro mas eu queria deixar isso totalmente automatizado no CI, aproveitei esse momento para começar a saga de reescrever tudo e resolver tanto o projeto corrompido, como automatizar o incremento da versão.&lt;/p&gt;
&lt;h2&gt;
  
  
  Capítulo 2: O Confronto com os Orcs
&lt;/h2&gt;

&lt;p&gt;Utilizar Fastlane no meu contexto implica em gerenciar a versão do Ruby e do Fastlane, então novos desenvolvedores ou qualquer um do time que vá rodar o projeto precisariam configurar isso também, incluindo a máquina do CI.&lt;br&gt;
Como eu preciso apenas fazer o archive e enviar o SDK, não é necessário o Fastlane, a solução escolhida foi fazer tudo em shell script mesmo.&lt;/p&gt;
&lt;h2&gt;
  
  
  Capítulo 3: A Chegada em Mordor
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foggu4kz7zk2g1i8mtbii.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foggu4kz7zk2g1i8mtbii.jpg" alt="Image description" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  One script to rule them all
&lt;/h3&gt;

&lt;p&gt;Dividi em 3 etapas:&lt;br&gt;
1 - Descobrir a versão do projeto&lt;br&gt;
2 - Fazer o incremento da versão, seguindo a lógica das versões anteriores&lt;br&gt;
3 - Definir a versão no projeto&lt;/p&gt;

&lt;p&gt;Aqui o primeiro passo é descobrir qual a versão atual do projeto e para isso usei o &lt;a href="https://developer.apple.com/library/archive/qa/qa1827/_index.html" rel="noopener noreferrer"&gt;agvtool&lt;/a&gt;&lt;br&gt;
Para pegar a versão do projeto utilizo o &lt;code&gt;what-marketing-version&lt;/code&gt; e para pegar o build number &lt;code&gt;what-version&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;agvtool what-marketing-version&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fao599yvorztjht8bgdgh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fao599yvorztjht8bgdgh.png" alt="retorno da função agvtool what-marketing-version mostrando as versões em cada target" width="800" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Em shell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;agv_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;agvtool what-marketing-version&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;current_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$agv_output&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'Found CFBundleShortVersionString'&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 1 | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'s/.*of "([0-9]+\.[0-9]+\.[0-9]+)".*/\1/'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$current_version&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com o número da versão só fiz uma lógica para incrementar de acordo com o que meu projeto segue. Incrementa o patch até 9, depois passa para o minor até 9 e depois incrementa o major.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;increment_version&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="c"&gt;# Divide into (major, minor, patch)&lt;/span&gt;
    &lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'.'&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; major minor patch &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$version&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="c"&gt;# Increment the patch number, considering the limit of 9 &lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$patch&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-lt&lt;/span&gt; 9 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        &lt;span class="o"&gt;((&lt;/span&gt;patch++&lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="c"&gt;# If patch reaches 9, reset it to 0 and increment the minor number&lt;/span&gt;
        &lt;span class="nv"&gt;patch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$minor&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-lt&lt;/span&gt; 9 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
            &lt;span class="o"&gt;((&lt;/span&gt;minor++&lt;span class="o"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="c"&gt;# If minor reaches 9, reset it to 0 and increment the major number&lt;/span&gt;
            &lt;span class="nv"&gt;minor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$major&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-lt&lt;/span&gt; 9 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
                &lt;span class="o"&gt;((&lt;/span&gt;major++&lt;span class="o"&gt;))&lt;/span&gt;
            &lt;span class="k"&gt;fi
        fi
    fi

    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$major&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$minor&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$patch&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E finalmente, para atualizar a versão:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;get_version&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;new_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;increment_version &lt;span class="nv"&gt;$version&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
agvtool new-marketing-version &lt;span class="nv"&gt;$new_version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhuzgcsyehtgm6pgwropj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhuzgcsyehtgm6pgwropj.png" alt="Image description" width="482" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>braziliandevs</category>
      <category>ios</category>
      <category>automation</category>
      <category>cicd</category>
    </item>
    <item>
      <title>A importância de conhecer sobre UX como desenvolvedor e meu desespero na farmácia</title>
      <dc:creator>Rafael Leandro</dc:creator>
      <pubDate>Sat, 04 May 2024 02:04:27 +0000</pubDate>
      <link>https://dev.to/raafas/a-importancia-de-conhecer-sobre-ux-como-desenvolvedor-e-meu-desespero-na-farmacia-1d1m</link>
      <guid>https://dev.to/raafas/a-importancia-de-conhecer-sobre-ux-como-desenvolvedor-e-meu-desespero-na-farmacia-1d1m</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Quando atuei na Involves, tive a oportunidade de trabalhar com o &lt;del&gt;Fábio&lt;/del&gt; &lt;a href="https://www.linkedin.com/in/ericcmartins"&gt;Eric Martins&lt;/a&gt; e pude conhecer sobre UX mais de perto, opinar (até demais às vezes), trabalhar pela primeira vez na construção de um design system do zero, experimentações e o conhecimento mais importante como desenvolvedor: Heurísticas de usabilidade. A experiência que tive na Involves, com o time de design trabalhando ao lado e não sendo um processo à parte, foi fundamental. Parei de ver o design como algo estético e comecei a vê-lo como algo funcional. Eu não estava desenvolvendo apenas uma interface bonita, estava fazendo um produto que passava segurança ao usuário, que entregava performance, que era, na medida do possível, intuitivo e que qualquer um podia utilizar sem um manual. &lt;br&gt;
Pois bem, num belo fim de semana fui ao shopping e precisei pagar a minha conta na farmácia e o app do banco simplesmente não exibia nem o campo de senha e nem o botão para logar. Passado o desespero e medo de não conseguir pagar a conta, parei para entender o que estava acontecendo: Minha conexão estava ruim, o app estava demorando a se comunicar com o backend mas não tinha informação nenhuma sobre isso, fez um loading, entrou na tela de login e só exibia o campo de CPF. Então me lembrei das heurísticas de Nielsen e como essa situação poderia ter sido projetada.&lt;/p&gt;

&lt;h2&gt;
  
  
  Heurísticas de Nielsen
&lt;/h2&gt;

&lt;p&gt;Jakob Nielsen e Rolf Molich propuseram 10 heurísticas que devem ser levadas em consideração no desenvolvimento de interfaces. Seria como regras gerais para reduzir a carga cognitiva do usuário para que a jornada dele seja mais leve e aprimorada. As 10 heurísticas de Nielsen são:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Visibilidade do status do sistema;&lt;/li&gt;
&lt;li&gt;Correspondência entre o sistema e o mundo real;&lt;/li&gt;
&lt;li&gt;Liberdade e controle do usuário;&lt;/li&gt;
&lt;li&gt;Consistência e padrões;&lt;/li&gt;
&lt;li&gt;Prevenção de erros;&lt;/li&gt;
&lt;li&gt;Reconhecer ao invés de lembrar;&lt;/li&gt;
&lt;li&gt;Flexibilidade e eficiência;&lt;/li&gt;
&lt;li&gt;Estética e design minimalista;&lt;/li&gt;
&lt;li&gt;Auxiliar usuários a reconhecer, diagnosticar e recuperar erros;&lt;/li&gt;
&lt;li&gt;Ajuda e documentação.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  O problema
&lt;/h2&gt;

&lt;p&gt;O app bloqueia print, o mais próximo que consegui simular:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu826wvo5pcs5hist3u81.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu826wvo5pcs5hist3u81.jpeg" alt="Image description" width="800" height="1422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Com base nas heurísticas de Nielsen, temos aqui alguns problemas:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Visibilidade de estado do sistema&lt;/strong&gt;&lt;br&gt;
O sistema deve manter o usuário informado sobre o que está acontecendo, com feedback dentro de um tempo razoável. Por exemplo: Meu microfone, quando toco nele para mutar/desmutar ele fica aceso ou apagado, informando o estado. No caso do aplicativo, na abertura da tela o app apresenta um carregamento que deveria ser mantido até que realmente fosse concluído. Outro ponto foi o preenchimento do CPF, não houve qualquer feedback informando se eu tinha inserido um valor válido ou não, a impressão que tive foi que o CPF estava inválido e não liberou o campo de senha por isso.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reconhecimento ao invés de memorização&lt;/strong&gt;&lt;br&gt;
Ao esconder elementos em determinados contextos, o usuário é forçado a lembrar de mais informações, teria que lembrar onde o campo ou botão foi parar, como fazer para exibi-lo novamente. Essa abordagem gera mais dificuldade do que benefício para segurança. É importante para o usuário saber que a opção existe e por que não está disponível naquele momento, por exemplo: Os campos de senha e login poderiam estar visíveis com o botão de login numa cor diferente indicando que está desabilitado e um texto próximo informando do problema de conexão.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prevenção de erros&lt;/strong&gt;&lt;br&gt;
Todo esse cenário poderia ser evitado pensando na heurística de prevenção de erros. Melhor do que informar que o usuário cometeu um erro é impedir que ele cometa o erro. &lt;br&gt;
Nesse caso, já que o carregamento não tinha sido concluído, a tela de loading não deveria desaparecer, liberando a alteração do CPF. Fazendo isso, o sistema permite que o usuário cometa um deslize, por exemplo, acabe digitando o CPF errado, desmarque o campo que mantém o CPF salvo e não tenha o CPF no momento. Prevenir erros é crítico para uma boa experiência e usabilidade.&lt;/p&gt;

&lt;h2&gt;
  
  
  E eu, como desenvolvedor, o que tenho a ver com isso?
&lt;/h2&gt;

&lt;p&gt;Primeiramente, é importante que desenvolvedores e designers falem a mesma linguagem e tenham um entendimento comum do problema e da solução proposta. Conhecer as heurísticas, do ponto de vista de um desenvolvedor, ajuda a tomar decisões durante o desenvolvimento (conhecer os &lt;a href="https://medium.com/swlh/the-nine-states-of-design-5bfe9b3d6d85"&gt;estados de tela&lt;/a&gt; também me ajudou muito). Entender que o design não é apenas estética garante que o time de desenvolvimento entregue um produto melhor, pensado no usuário.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agradecimentos &amp;lt;3
&lt;/h2&gt;

&lt;p&gt;Obrigado Ericão pelo trabalho em conjunto durante o tempo na Involves e por revisar esse texto.&lt;br&gt;
Obrigado a minha digníssima Deborah por fazer o Pix me salvando na farmácia e por revisar o texto.&lt;/p&gt;

</description>
      <category>ux</category>
      <category>nielsen</category>
      <category>ui</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Como criar um emulador de jogos</title>
      <dc:creator>Rafael Leandro</dc:creator>
      <pubDate>Wed, 31 Jan 2024 16:33:26 +0000</pubDate>
      <link>https://dev.to/raafas/como-criar-um-emulador-de-jogos-3kn6</link>
      <guid>https://dev.to/raafas/como-criar-um-emulador-de-jogos-3kn6</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Tem TL;DR nesse post não apressadinho(a), mas tu pode pular para o tópico "Arquitetura".&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Quando eu era criança me lembro de achar em um dos computadores do laboratório de informática um emulador de GBA e uma ROM do Pokémon Yellow. Me lembro de ter feito uma cópia e levado pra casa, onde joguei por muitas horas.&lt;/p&gt;

&lt;p&gt;Sempre fui uma criança curiosa, que gostava de saber como as coisas funcionam. Isso foi muito incentivado pelo meu avô, que me dava uma chave de fenda e alguns eletrônicos para desmontar. Essa curiosidade foi evoluindo depois que ele me deu meu primeiro computador, como o sistema operacional funciona? Como o emulador roda um jogo de um console? Eu consigo fazer um igual?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy38p2vdh75eehbqg2twa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy38p2vdh75eehbqg2twa.png" alt="Pokémon Yellow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O tempo passou, aprendi a desenvolver, aprendi como muitas dessas coisas funcionam e hoje resolvi compartilhar um pouco das minhas anotações de como um emulador funciona.&lt;/p&gt;

&lt;h2&gt;
  
  
  CHIP-8
&lt;/h2&gt;

&lt;p&gt;O escolhido foi o CHIP-8, uma linguagem de interpretação criada nos anos 70 por Joseph Weisbecker. Foi utilizado para desenvolver jogos simples e ferramentas educacionais, hoje é conhecido por ser fácil de implementar e é frequentemente usado como uma introdução à emulação de sistemas mais complexos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1s46xvxbfnlq1k72o4ng.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1s46xvxbfnlq1k72o4ng.png" alt="Space Invaders no CHIP-8"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Arquitetura
&lt;/h2&gt;

&lt;p&gt;As informações de arquiteturas são muito importantes, os valores serão utilizados no código!&lt;/p&gt;

&lt;h3&gt;
  
  
  Memória
&lt;/h3&gt;

&lt;p&gt;Tem um total de 4.096 bytes (ou 4KB), mas desse total, os primeiros 512 bytes são reservados para o sistema.&lt;/p&gt;

&lt;h3&gt;
  
  
  Registradores
&lt;/h3&gt;

&lt;p&gt;Registradores são pequenas unidades de armazenamento dentro da CPU. São utilizados para realizar operações aritméticas, armazenar endereções e etc.&lt;br&gt;
Essa é uma parte importante do que será desenvolvido.&lt;/p&gt;

&lt;p&gt;Os tipos de registradores encontrados no CHIP-8:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Registradores de uso Geral (V0 a VF):
a. Possui 16 registradores de uso geral, numerados de V0 a VF.
b. Cada registrador é 1 byte (8 bits) e pode armazenar valores de 0 a 255.&lt;/li&gt;
&lt;li&gt;Registrador de uso de memória (I):

&lt;ol&gt;
&lt;li&gt;O registrador I é um registrador de 16 bits utilizado para armazenar endereços de memória.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;Registrador do ponteiro de programa (PC):

&lt;ol&gt;
&lt;li&gt;É um registrador de 16 bits que armazena o endereço da próxima instrução que vai ser executada.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;Registrador de ponto de retorno (Stack e SP):

&lt;ol&gt;
&lt;li&gt;O CHIP-8 possui uma pilha para armazenar o endereço de retorno durante chamadas de blocos (sub-rotinas)&lt;/li&gt;
&lt;li&gt;O registrador SP registra a posição atual na pilha&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;Registradores de estado (VF):

&lt;ol&gt;
&lt;li&gt;É utilizado como registrador de flags&lt;/li&gt;
&lt;li&gt;Algumas instruções modificam esse registrador para indicar condições especificas, como carry em operações de adição.
Esses registradores são cruciais para a implementação do emulador, eles que fornecem a capacidade de armazenar e manipular dados, controlar os fluxos de execução e interagir com a memória, algumas coisas ficam mais claras com a implementação dó código.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;h3&gt;
  
  
  Instruções
&lt;/h3&gt;

&lt;p&gt;As instruções são operações que a CPU, no caso o CHIP-8, consegue executar. Cada instrução é uma ação específica que a CPU deve realizar. Deixei pra apresentar a lista um pouco mais a frente, pra evitar sustos ainda nos conceitos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ciclo de máquina
&lt;/h3&gt;

&lt;p&gt;O ciclo pode ser resumido em poucos passos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Lê a instrução no endereço apontado pelo PC&lt;/li&gt;
&lt;li&gt;Decodifica a instrução para determinar qual operação deve ser executada.&lt;/li&gt;
&lt;li&gt;Executa a operação.&lt;/li&gt;
&lt;li&gt;Atualiza o PC para apontar para a próxima instrução.&lt;/li&gt;
&lt;li&gt;Volta para o passo 1 e repete o ciclo até o termino do programa.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Desenvolvendo o emulador
&lt;/h2&gt;

&lt;p&gt;Vou utilizar Swift, simplesmente porque é a linguagem que mais uso no dia-a-dia e tem uma leitura muito simples. Já desenvolvi &lt;a href="https://github.com/Raafas/CHIP8-Emulator" rel="noopener noreferrer"&gt;o emulador em C++&lt;/a&gt; mas a leitura pode ser um pouco mais complexa pra quem não conhece a linguagem. Aqui não vou falar sobre padrões de projeto, nem definir arquitetura do software, tudo vai ser feito pensando apenas na facilidade de leitura. Escolha a linguagem e adapta tudo pra ela :)&lt;/p&gt;

&lt;p&gt;Agora sabendo da arquitetura é preciso implementar os registradores, emular a memória, decodificar as instruções e implementar o ciclo de máquina.&lt;/p&gt;

&lt;p&gt;Primeiro os registradores. Criei uma classe com as variáveis para armazenar os registradores e uma função para incrementar o PC.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Registers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Registradores de Uso Geral (V0 a VF)&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;V&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;UInt8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;UInt8&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="nv"&gt;repeating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Registrador de Endereço de Memória (I)&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UInt16&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="c1"&gt;// Registrador do Contador de Programa (PC)&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;PC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UInt16&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x200&lt;/span&gt;  &lt;span class="c1"&gt;// Valor inicial por convenção&lt;/span&gt;

    &lt;span class="c1"&gt;// Registrador do Ponteiro da Pilha (SP)&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;SP&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UInt8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="c1"&gt;// Método para incrementar o Contador de Programa&lt;/span&gt;
    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;incrementPC&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;PC&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="c1"&gt;// O valor aqui é 2 porque as instruções são de 2 bytes&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Implementação da memória&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;

&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Foundation&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Memory&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="c1"&gt;// Tamanho da memória do CHIP-8 (4KB)&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;memorySize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;

    &lt;span class="c1"&gt;// Memória do CHIP-8&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;UInt8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;UInt8&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="nv"&gt;repeating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Chip8Memory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;memorySize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Decodificando as instruções&lt;/p&gt;

&lt;p&gt;Essa é a parte mais importante e trabalhosa de se fazer, decodificar e implementar as instruções é a parte central do emulador.&lt;/p&gt;

&lt;p&gt;O CHIP-8 possui um conjunto de 35 instruções, aqui uma tabela com as instruções e sua representação&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Código&lt;/th&gt;
&lt;th&gt;Instrução&lt;/th&gt;
&lt;th&gt;Descrição&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;00E0&lt;/td&gt;
&lt;td&gt;CLS&lt;/td&gt;
&lt;td&gt;Clear the display.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;00EE&lt;/td&gt;
&lt;td&gt;RET&lt;/td&gt;
&lt;td&gt;Return from a subroutine.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1nnn&lt;/td&gt;
&lt;td&gt;JP addr&lt;/td&gt;
&lt;td&gt;Jump to location nnn.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2nnn&lt;/td&gt;
&lt;td&gt;CALL addr&lt;/td&gt;
&lt;td&gt;Call subroutine at nnn.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3xkk&lt;/td&gt;
&lt;td&gt;SE Vx, byte&lt;/td&gt;
&lt;td&gt;Skip next instruction if Vx == kk.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4xkk&lt;/td&gt;
&lt;td&gt;SNE Vx, byte&lt;/td&gt;
&lt;td&gt;Skip next instruction if Vx != kk.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5xy0&lt;/td&gt;
&lt;td&gt;SE Vx, Vy&lt;/td&gt;
&lt;td&gt;Skip next instruction if Vx == Vy.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6xkk&lt;/td&gt;
&lt;td&gt;LD Vx, byte&lt;/td&gt;
&lt;td&gt;Set Vx = kk.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7xkk&lt;/td&gt;
&lt;td&gt;ADD Vx, byte&lt;/td&gt;
&lt;td&gt;Set Vx = Vx + kk.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8xy0&lt;/td&gt;
&lt;td&gt;LD Vx, Vy&lt;/td&gt;
&lt;td&gt;Set Vx = Vy.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8xy1&lt;/td&gt;
&lt;td&gt;OR Vx, Vy&lt;/td&gt;
&lt;td&gt;Set Vx = Vx OR Vy.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8xy2&lt;/td&gt;
&lt;td&gt;AND Vx, Vy&lt;/td&gt;
&lt;td&gt;Set Vx = Vx AND Vy.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8xy3&lt;/td&gt;
&lt;td&gt;XOR Vx, Vy&lt;/td&gt;
&lt;td&gt;Set Vx = Vx XOR Vy.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8xy4&lt;/td&gt;
&lt;td&gt;ADD Vx, Vy&lt;/td&gt;
&lt;td&gt;Set Vx = Vx + Vy, set VF = carry.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8xy5&lt;/td&gt;
&lt;td&gt;SUB Vx, Vy&lt;/td&gt;
&lt;td&gt;Set Vx = Vx - Vy, set VF = NOT borrow.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8xy6&lt;/td&gt;
&lt;td&gt;SHR Vx {, Vy}&lt;/td&gt;
&lt;td&gt;Set Vx = Vx SHR 1.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8xy7&lt;/td&gt;
&lt;td&gt;SUBN Vx, Vy&lt;/td&gt;
&lt;td&gt;Set Vx = Vy - Vx, set VF = NOT borrow.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8xyE&lt;/td&gt;
&lt;td&gt;SHL Vx {, Vy}&lt;/td&gt;
&lt;td&gt;Set Vx = Vx SHL 1.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9xy0&lt;/td&gt;
&lt;td&gt;SNE Vx, Vy&lt;/td&gt;
&lt;td&gt;Skip next instruction if Vx != Vy.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Annn&lt;/td&gt;
&lt;td&gt;LD I, addr&lt;/td&gt;
&lt;td&gt;Set I = nnn.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bnnn&lt;/td&gt;
&lt;td&gt;JP V0, addr&lt;/td&gt;
&lt;td&gt;Jump to location V0 + nnn.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cxkk&lt;/td&gt;
&lt;td&gt;RND Vx, byte&lt;/td&gt;
&lt;td&gt;Set Vx = random byte AND kk.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dxyn&lt;/td&gt;
&lt;td&gt;DRW Vx, Vy, nibble&lt;/td&gt;
&lt;td&gt;Display nibble-byte sprite at memory location I at (Vx, Vy), set VF = collision.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ex9E&lt;/td&gt;
&lt;td&gt;SKP Vx&lt;/td&gt;
&lt;td&gt;Skip next instruction if key with the value of Vx is pressed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ExA1&lt;/td&gt;
&lt;td&gt;SKNP Vx&lt;/td&gt;
&lt;td&gt;Skip next instruction if key with the value of Vx is not pressed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fx07&lt;/td&gt;
&lt;td&gt;LD Vx, DT&lt;/td&gt;
&lt;td&gt;Set Vx = delay timer value.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fx0A&lt;/td&gt;
&lt;td&gt;LD Vx, K&lt;/td&gt;
&lt;td&gt;Wait for a key press, store the value of the key in Vx.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fx15&lt;/td&gt;
&lt;td&gt;LD DT, Vx&lt;/td&gt;
&lt;td&gt;Set delay timer = Vx.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fx18&lt;/td&gt;
&lt;td&gt;LD ST, Vx&lt;/td&gt;
&lt;td&gt;Set sound timer = Vx.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fx1E&lt;/td&gt;
&lt;td&gt;ADD I, Vx&lt;/td&gt;
&lt;td&gt;Set I = I + Vx.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fx29&lt;/td&gt;
&lt;td&gt;LD F, Vx&lt;/td&gt;
&lt;td&gt;Set I = location of sprite for digit Vx.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fx33&lt;/td&gt;
&lt;td&gt;LD B, Vx&lt;/td&gt;
&lt;td&gt;Store BCD representation of Vx in memory locations I, I+1, and I+2.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fx55&lt;/td&gt;
&lt;td&gt;LD [I], Vx&lt;/td&gt;
&lt;td&gt;Store registers V0 through Vx in memory starting at location I.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fx65&lt;/td&gt;
&lt;td&gt;LD Vx, [I]&lt;/td&gt;
&lt;td&gt;Read registers V0 through Vx from memory starting at location I.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fx75&lt;/td&gt;
&lt;td&gt;LD R, Vx&lt;/td&gt;
&lt;td&gt;Store V0 through Vx in the RPL user flags.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Implementei uma classe que vai ficar responsável por isso&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Instructions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;registers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Registers&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;registers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Registers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;registers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;registers&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;executeInstruction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;withOffset&lt;/span&gt; &lt;span class="nv"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UInt16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;opcodeType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opcode&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xF000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;(opcode &amp;amp; 0xF000)&lt;/strong&gt;: Realiza uma operação bitwise AND entre &lt;strong&gt;&lt;code&gt;opcode&lt;/code&gt;&lt;/strong&gt; e a máscara &lt;strong&gt;&lt;code&gt;0xF000&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;
Operações bitwise são utilizados quando precisamos realizar operações em nível de bits. O operador &amp;amp; (AND) compara dois valores utilizando suas representações binárias, cada bit é comparado e retorna 1 quando os bits forem iguais, caso contrário retorna 0.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&amp;gt;&amp;gt; 12&lt;/strong&gt;: Desloca para a direita 12 posições, movendo o resultado para as posições mais baixas , sendo os bits menos significativos do resultado (LSB).&lt;/p&gt;

&lt;p&gt;Com esse valor, é possível saber qual o tipo de instrução deve ser executada. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;

&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;opcodeType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mh"&gt;0x0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;opcode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mh"&gt;0x00E0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// CLS - Clear the display&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Na tabela de instruções 00E0 representa a instrução para limpar a tela, então aqui deve se implementar a chamada para esse método.&lt;/p&gt;

&lt;p&gt;E para cada uma das instruções deve ser feito isso. Como o código ficaria muito grande e esse texto já está maior do que eu esperava, o link para o repositório do Github com o projeto vai está disponível (assim espero) no fim do artigo.&lt;/p&gt;

&lt;p&gt;Ciclo de máquina&lt;/p&gt;

&lt;p&gt;Fiz uma classe responsável por centralizar tudo, a inicialização da memória, dos registradores e das instruções. Essa classe também vai controlar o ciclo de máquina, que como visto anteriormente: Lê e decodifica a instrução, executa a operação e atualiza o PC. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Chip8Cpu&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;registers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Registers&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;instructionDecoder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Instructions&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Memory&lt;/span&gt;

    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Chip8Cpu&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;registers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Registers&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;instructionDecoder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Instructions&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Memory&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;runCycle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;opcode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;registers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pc&lt;/span&gt;
        &lt;span class="n"&gt;instructionDecoder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executeInstruction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;registers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;registers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;opcode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;opcode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;registers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;incrementPC&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Renderização gráfica&lt;/p&gt;

&lt;p&gt;E por fim, a parte mais especifica de cada plataforma. Na primeira versão que fiz, desenvolvendo em C++ foquei em desenvolver algo multiplataforma, então usei o GLUT para a parte gráfica. Mas aqui o objetivo é explicar o funcionamento, então&lt;/p&gt;

&lt;p&gt;A tela do CHIP-8 é uma matriz de 64x32 pixels, esse pixel pode estar ligado ou desligado. Na implementação caso o pixel esteja desligado tem a cor preta, se estiver ligado tem a cor branca.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;

&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;renderScreen&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;pixelValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;registers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pixelValue&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s"&gt;"[*]"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"[ ]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;terminator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Essa função exibe [*] quando desligado e [ ] ligado. Aqui deve ser implementada a view na plataforma escolhida.&lt;/p&gt;

&lt;p&gt;Agora já é possível testar o que foi feito, basta apenas carregar a rom na memória, passando a URL do arquivo: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;romData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="kt"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;contentsOf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;romBytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;UInt8&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;romData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;registers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;subrange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="o"&gt;..&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;rom&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;romBytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Por convenção a rom é carregada a partir do byte 512.&lt;br&gt;
O resultado é a tela abaixo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbeq8puej1qseur24clec.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbeq8puej1qseur24clec.png" alt="Emulador CHIP8 sem as fontes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O CHIP8 possui também um conjunto fixo de sprites que representam os números em hexadecimal.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;

&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;Font&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;FontSet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;UInt8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 0&lt;/span&gt;
        &lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
        &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 2&lt;/span&gt;
        &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 3&lt;/span&gt;
        &lt;span class="mh"&gt;0x90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 4&lt;/span&gt;
        &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 5&lt;/span&gt;
        &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 6&lt;/span&gt;
        &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 7&lt;/span&gt;
        &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 8&lt;/span&gt;
        &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 9&lt;/span&gt;
        &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// A&lt;/span&gt;
        &lt;span class="mh"&gt;0xE0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xE0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xE0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// B&lt;/span&gt;
        &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// C&lt;/span&gt;
        &lt;span class="mh"&gt;0xE0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xE0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// D&lt;/span&gt;
        &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// E&lt;/span&gt;
        &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xF0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;  &lt;span class="c1"&gt;// F&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Antes do carregamento da ROM é só adicionar as fontes na memória&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;

&lt;span class="n"&gt;registers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;subrange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;Font&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;FontSet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Font&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;FontSet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;E agora as fontes são carregadas:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjzx406oneirweng0hsxh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjzx406oneirweng0hsxh.png" alt="Emulado CHIP8 com as fontes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para mapear os controles basta implementar as instruções no offset &lt;strong&gt;0xE&lt;/strong&gt; e com isso temos um emulador CHIP-8 com o funcionamento básico.&lt;/p&gt;

</description>
      <category>chip8</category>
      <category>emulaçao</category>
      <category>programação</category>
      <category>jogos</category>
    </item>
    <item>
      <title>Evitando conflitos no Xcode</title>
      <dc:creator>Rafael Leandro</dc:creator>
      <pubDate>Fri, 15 Oct 2021 00:32:13 +0000</pubDate>
      <link>https://dev.to/raafas/evitando-conflitos-no-xcode-3bda</link>
      <guid>https://dev.to/raafas/evitando-conflitos-no-xcode-3bda</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;O objetivo desse texto é mostrar como resolvi alguns problemas no meu time utilizando o &lt;a href="https://tuist.io"&gt;Tuist&lt;/a&gt; para gerar projetos e workspaces do Xcode e que com isso nós evitamos conflitos na hora do merge, resolvemos problemas para gerenciar dependências e também podemos padronizar configurações dos projetos e abrir individualmente o projeto que vai ser alterado (modo foco).&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalação
&lt;/h2&gt;

&lt;p&gt;A instalação é muito simples, basta executar o comando no terminal:&lt;br&gt;
&lt;code&gt;curl -Ls https://install.tuist.io | bash&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Criando um projeto novo
&lt;/h2&gt;

&lt;p&gt;Se for um novo projeto a utilização do Tuist é super simples.&lt;br&gt;
Basta criar uma pasta e executar o &lt;code&gt;tuist init&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir MyApp
cd MyApp
tuist init --platform ios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O comando init irá gerar os arquivos base, &lt;code&gt;Info.plist&lt;/code&gt;, &lt;code&gt;AppDelegate.swift&lt;/code&gt;, arquivos de teste e o &lt;code&gt;Project.swift&lt;/code&gt; que contém as configurações do projeto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migrando um projeto existente
&lt;/h2&gt;

&lt;p&gt;A migração no meu caso foi tranquila porque o projeto é simples e tenho um Workspace com vários projetos que dependem do Core e uma única dependência externa em um Target de teste.&lt;/p&gt;

&lt;p&gt;Comecei migrando o Core, porque precisava definir a dependência dele nos outros projetos, resolvi todas as outras dependências e por último configurei o Workspace.&lt;br&gt;
Na pasta de cada projeto criei o arquivo &lt;code&gt;Project.swift&lt;/code&gt;, no diretório raíz o &lt;code&gt;Workspace.swift&lt;/code&gt;e a pasta &lt;code&gt;Tuist&lt;/code&gt; com o arquivo &lt;code&gt;Dependencies.swift&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Configurações do projeto
&lt;/h2&gt;

&lt;p&gt;O &lt;a href="https://docs.tuist.io/manifests/project"&gt;Project.swift&lt;/a&gt; contém a configuração do projeto. É nesse arquivo onde são definidos nome, organização, targets, schemas, entre outras coisas.&lt;/p&gt;

&lt;p&gt;Comecei fazendo o import do framework &lt;code&gt;ProjectDescription&lt;/code&gt; esse arquivo deve inicializar uma variável do tipo &lt;code&gt;Project&lt;/code&gt; que pode ter qualquer nome, mas a recomendação da documentação é nomear como &lt;code&gt;project&lt;/code&gt; mesmo.&lt;/p&gt;

&lt;p&gt;Um project precisa obrigatoriamente dos parâmetros: &lt;code&gt;name&lt;/code&gt; e &lt;code&gt;targets&lt;/code&gt; que é um array do tipo Target.&lt;/p&gt;

&lt;p&gt;No Target é especificado o nome, plataforma, tipo do produto, bundle e os arquivos de código.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Target&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"App"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nv"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iOS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nv"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nv"&gt;bundleId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"com.rafa.example"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nv"&gt;infoPlist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Info.plist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nv"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Sources/**"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nv"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;project&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Project&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"MyProject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Dependências externas
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;A integração com dependências externas ainda está em alpha, como é avisado na &lt;a href="https://docs.tuist.io/guides/third-party-dependencies/"&gt;documentação&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No momento que estou escrevendo esse texto a integração com Cocoapods ainda não é suportada. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Cada projeto pode ter suas dependências configuradas individualmente, basta criar a pasta &lt;code&gt;Tuist&lt;/code&gt; com o arquivo &lt;code&gt;Dependencies.swift&lt;/code&gt; dentro dela.&lt;br&gt;
No meu caso, fiz isso na pasta raiz do projeto porque tenho uma única dependência externa.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;ProjectDescription&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Dependencies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;carthage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;github&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Alamofire/Alamofire"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;requirement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"5.0.4"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="nv"&gt;swiftPackageManager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"https://github.com/Alamofire/Alamofire"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;requirement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upToNextMajor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"5.0.0"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="nv"&gt;platforms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iOS&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feito isso baixe as dependências rodando&lt;br&gt;
&lt;code&gt;tuist dependencies fetch&lt;/code&gt;. Uma pasta chamada Dependencies será criada e o código será baixado nela.&lt;/p&gt;

&lt;p&gt;De volta ao &lt;code&gt;Project.swift&lt;/code&gt; é necessário registrar no Target a dependência baixada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Target&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"App"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nv"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iOS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nv"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nv"&gt;bundleId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"com.rafa.example"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nv"&gt;infoPlist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Info.plist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nv"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Sources/**"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nv"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;external&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Alamofire"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configurações do Workspace
&lt;/h2&gt;

&lt;p&gt;Por padrão o &lt;code&gt;tuist generate&lt;/code&gt; cria um Workspace com o mesmo nome do projeto e já inclui as dependências.&lt;br&gt;
No meu caso os projetos estão num monorepo, então preciso configurar um Workspace e adicionar todos os projetos nele.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;ProjectDescription&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;workspace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Workspace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"ProjectWorkspace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s"&gt;"Project1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"Project2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"Project3"&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="nv"&gt;schemes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por padrão os &lt;a href="https://docs.tuist.io/manifests/project#scheme"&gt;schemas&lt;/a&gt; são gerados automaticamente, mas podem ser personalizados para configurar as ações de cada um.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gerando os arquivos
&lt;/h2&gt;

&lt;p&gt;A configuração é essa, dependendo do tamanho do projeto pode ser um pouco cansativa mas os ganhos são compensatórios. &lt;/p&gt;

&lt;p&gt;Depois de tudo configurado, é só rodar o &lt;code&gt;tuist dependencies fetch&lt;/code&gt; para baixar as dependências e depois &lt;code&gt;tuist generate&lt;/code&gt; para gerar os projetos/workspaces.&lt;/p&gt;

&lt;p&gt;Testei outras ferramentas mas resolvi adotar o Tuist por utilizar Swift e não Yaml, possibilidade de fazer cache dos módulos, cache dos testes, screenshot de dependências e por considerar a adoção fácil no projeto em que trabalho.&lt;br&gt;
Finalizei implementando o &lt;a href="https://github.com/bloomberg/xcdiff"&gt;xcdiff&lt;/a&gt; evitando que o &lt;code&gt;.xcodeproj&lt;/code&gt; fosse alterado manualmente.&lt;/p&gt;

&lt;p&gt;E é isso! :)&lt;/p&gt;

&lt;h3&gt;
  
  
  Links úteis
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://tuist.io/"&gt;Tuist.io&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.tuist.io/"&gt;Tuist docs&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/bloomberg/xcdiff"&gt;xcdiff&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>xcode</category>
      <category>git</category>
      <category>tuist</category>
    </item>
    <item>
      <title>Swift além do iOS e do macOS - Parte 1</title>
      <dc:creator>Rafael Leandro</dc:creator>
      <pubDate>Thu, 15 Jul 2021 14:26:41 +0000</pubDate>
      <link>https://dev.to/raafas/swift-alem-do-ios-e-do-macos-parte-1-596m</link>
      <guid>https://dev.to/raafas/swift-alem-do-ios-e-do-macos-parte-1-596m</guid>
      <description>&lt;p&gt;Eu trabalho com desenvolvimento iOS e não costumo fazer nada no backend, o que é um problema em projetos pessoais. Não quis investir tempo estudando JS e seus frameworks (não tenho nem espaço pro cache do npm) e comecei a procurar uma solução mais prática, foi aí que encontrei o Vapor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalação
&lt;/h2&gt;

&lt;p&gt;🍎 A instalação do Vapor é feita através do &lt;a href="https://brew.sh"&gt;homebrew&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;vapor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para ter certeza que a instalação foi feita corretamente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;vapor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E essa deve ser a saída:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Usage: vapor &amp;lt;&lt;span class="nb"&gt;command&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

Vapor Toolbox &lt;span class="o"&gt;(&lt;/span&gt;Server-side Swift web framework&lt;span class="o"&gt;)&lt;/span&gt;

Commands:
       build Builds an app &lt;span class="k"&gt;in &lt;/span&gt;the console.
       clean Cleans temporary files.
      heroku Commands &lt;span class="k"&gt;for &lt;/span&gt;working with Heroku
         new Generates a new app.
         run Runs an app from the console.
             Equivalent to &lt;span class="sb"&gt;`&lt;/span&gt;swift run &lt;span class="nt"&gt;--enable-test-discovery&lt;/span&gt; Run&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
  supervisor Commands &lt;span class="k"&gt;for &lt;/span&gt;working with Supervisord
       xcode Opens an app &lt;span class="k"&gt;in &lt;/span&gt;Xcode.

Use &lt;span class="sb"&gt;`&lt;/span&gt;vapor &amp;lt;&lt;span class="nb"&gt;command&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;--help&lt;/span&gt;,-h]&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;more information on a command.
Error: Missing &lt;span class="nb"&gt;command&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🐧 No Linux é necessário que o Swift 5.2 (ou superior) esteja instalado.&lt;br&gt;
A instalação é feita compilando o toolchain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/vapor/toolbox.git
&lt;span class="nb"&gt;cd &lt;/span&gt;toolbox
git checkout &amp;lt;versao&amp;gt;
make &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Hello, Vapor.
&lt;/h2&gt;

&lt;p&gt;Criando um novo projeto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vapor new first-project &lt;span class="nt"&gt;-n&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;first-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A flag &lt;code&gt;-n&lt;/code&gt; responde não automaticamente para todas as perguntas feitas depois de clonar o template.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CFWKRJBn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ncz20gy8q41qk10z6se.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CFWKRJBn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ncz20gy8q41qk10z6se.png" alt="Captura de Tela 2021-07-15 às 11.13.32"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rodando o primeiro projeto:&lt;br&gt;
🍎 no macOS&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vapor xcode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🐧 no Linux&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;swift run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se tudo ocorrer bem, a saída no console deve ser essa:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ INFO ] Server starting on http://127.0.0.1:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E pra testar, basta abrir o endereço no navegador.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kIseR2O6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s1brwxm8u05dlgkfkchp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kIseR2O6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s1brwxm8u05dlgkfkchp.png" alt="Captura de Tela 2021-07-15 às 11.23.05"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>swift</category>
      <category>backend</category>
      <category>vapor</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
