Machine virtuelle sur l'ESP8266 pour exécuter des jeux

VM écrite par une main incertaine des sciences humaines dans l'environnement de programmation Arduino à l'aide de quickcode et de vélos. Et il existe également un compilateur à partir d'un langage de type C, écrit en JavaScript en utilisant les mêmes méthodes. Oui Vous pouvez déjà vous précipiter dans les commentaires, lancer des pierres. Eh bien, pour ceux qui sont toujours intéressés, je vous invite à continuer à lire.

Trolleybus à pain

En général, mon travail a déjà été un peu couvert par le respecté tormozedison ici . Mais à cette époque, il y avait plutôt un prototype sphérique dans le vide. Et maintenant, j'ai un appareil RomanS, qu'il m'a gentiment fourni pour des expériences absolument gratuites. Cet appareil s'appelle ESPboy. Il se distingue des autres métiers par sa compacité et sa fente d'expansion utilisant la puce MCP23017. Ici, vous pouvez en savoir plus sur lui.

Si quelqu'un est intéressé, comment une idée aussi étrange m'est venue à l'esprit en tant que machine virtuelle sur un microcontrôleur, alors vous pouvez la lire sous le spoiler.

Contexte
Une fois à l'école, j'ai été emporté par un joueur de jeu de yoyogames et, comme beaucoup, rivé dessus, je ne comprends pas quoi. Ces démos mal écrites et mal dessinées pouvaient encore se vanter auprès d'amis, mais sur Internet, elles se noyaient parmi des similaires. J'ai réalisé combien il était difficile d'écrire moi-même un jeu simple, sans parler d'un jeu sérieux dans lequel vous pourriez voler les vaches. Mais l'envie d'écrire des jeux n'a pas été perdue. Quand j'ai eu un téléphone portable, j'ai découvert Midlet Pascal et je me suis amusé avec pendant plusieurs années. Après tout, j'ai réalisé qu'écrire un jeu pour un appareil faible est plus facile que pour son grand frère plus puissant. Au moins, on pourrait toujours parler non pas de mains tordues, mais des capacités limitées de la plate-forme. Cependant, les joueurs de bouton ont laissé la place à des capteurs une autre chance de conquérir le monde a été manquée. Néanmoins, à un moment donné, j'ai réalisé que je pouvais raviver mes rêves en utilisant un microcontrôleur.

J'ai commencé par écrire un jeu sous arduino uno, où iriez-vous sans. Ensuite, elle était ma seule et j'étais très inquiète de sa performance. J'ai essayé de flasher le moins possible. Mais le chemin du râteau va par petits pas. Chaque petite modification du code le faisait clignoter encore et encore. Et j'ai décidé d'écrire une machine virtuelle empilée. Après tout, il y a d'énormes deux kilo-octets de RAM pour les octets de code et de données à bord. Mais comme c'était lent, mais pour une raison inconnue, la mémoire manquait constamment. Le fait est que tous mes vélos étaient avec des roues carrées et roulaient lentement. J'ai alors décidé d'écrire un émulateur de puce 8 sur Arduino Mega qui vient d'arriver de Chine. Bien sûr, j'ai alors voulu lui écrire un émulateur de gameboy, la première playstation et un supercalculateur plus facile. En conséquence, j'ai compris l'essentiel. La machine virtuelle chip-8 était très simple, trop simple. À tel point que lors de l'écriture de vos jeux pour la multiplication ou la division, vous deviez écrire un sous-programme lent séparé. Vous devez donc écrire votre VM, en vous débarrassant d'une faille fatale. A cette époque, plusieurs autres esp8266 sont arrivés, avec leur espace de 160MHz.

S'il vous semble qu'une machine virtuelle est un gaspillage de ressources, j'ai également réécrit mon émulateur chip-8 pour cela. Il s'est avéré une machine virtuelle dans une machine virtuelle sur un microcontrôleur. Vous pouvez probablement aller plus loin et écrire une machine de Turing sur la puce 8.

Spécifications du moteur de jeu ESP Little


Une machine virtuelle contient 16 registres de 16 bits chacun, un registre zéro est un pointeur de pile. Chaque instruction est codée sur deux octets, certaines instructions contiennent deux octets de données. Mémoire adressable 64 Ko. Dans le cas de l'ESP8266, 20 Ko sont disponibles. Le programme peut être téléchargé depuis SPIFFS et UART. Si vous le souhaitez, vous pouvez ajouter un téléchargement à partir d'une carte mémoire ou via WiFi. En plus des instructions arithmétiques habituelles et des instructions pour déplacer des données, il existe des instructions distinctes pour travailler avec les images-objets, l'écran et le son. Taille d'écran 128 par 128 pixels. À 16 couleurs par point, l'écran prend 8 Ko de mémoire, la même quantité de tampon pour dessiner des sprites et des particules. Bien que la bibliothèque TFT_eSPI que j'utilise soit capable de mettre à jour l'écran plus de 60 fois par seconde, j'ai dû me limiter à 20 images par seconde. Sinon, le temps processeur n'était pas suffisant pour la machine virtuelle. Vous pouvez dessiner des tuiles et 32 ​​sprites jusqu'à 128x128 pixels avec la possibilité de rotation et de mise en miroir. Pour économiser de la mémoire, vous pouvez utiliser des images mono-bit ou la compression RLE. Il y a la physique simplifiée: détection des collisions de sprites avec des sprites et des tuiles, résolution des collisions, gravité. L'écran est mis à jour ligne par ligne uniquement si une ligne a changé de pixels. La vitesse de la machine virtuelle, en fonction du nombre de lignes tracées dans le cadre, varie de 100 000 à 900 000 opérations par seconde. Vous pouvez utiliser différents écrans couleur, il y a un étirement doux de l'image dans les proportions souhaitées.


Certains des jeux écrits par moi peuvent être consultés ici .

En même temps que VM pour ESP8266, j'ai écrit un émulateur JavaScript pour le navigateur. Afin de ne pas modifier le bytecode manuellement, un simple assembleur a été ajouté, basé sur mon expérience avec l'assembleur pour le MOS6502. J'ai alors décidé d'ajouter une langue de niveau supérieur. Néanmoins, ma tâche principale était d'écrire rapidement des jeux simples, et non un long code d'assemblage de débogage. Il m'a semblé que l'écriture de votre compilateur serait plus facile que l'ajout de LLVM. Et je l'ai écrit en JavaScript, car je le connais pas aussi mal que d'autres langues. Pour le moment, il est loin de supporter les standards C, et lors de la compilation, vous pouvez facilement rencontrer une erreur incompréhensible dans un endroit incompréhensible. Mais c'est rapide, car il faut moins de 2000 lignes.

Et maintenant à la question, pourquoi ai-je écrit tout cela ici. Déjà maintenant, vous pouvez écrire et exécuter des jeux. Cependant, la perfection est encore loin. Si quelqu'un veut m'aider à finaliser l'ESP LGE ou à écrire mon propre jeu, je serai très heureux. Si vous pensiez que mon idée était intéressante et que vous vouliez en savoir plus, je me ferai un plaisir de répondre à vos questions. Je vous préviens, le code pour Arduino est assez difficile à lire. En partie parce que je suis autodidacte. En partie parce que j'ai essayé de réduire le nombre d'appels de fonction afin d'augmenter la vitesse de travail. En conséquence, de nombreuses fonctions contiennent d'énormes traces de code. Ne laissez donc pas les femmes enceintes et les enfants à l'écran. Petit à petit, je vais essayer de résoudre ce problème et d'améliorer la lisibilité.

Et pour ceux qui ont lu, un exemple de jeu. Il prend moins d'une centaine de lignes et moins de 1 Ko sous forme compilée.

int stickCount; char key,previouseKey,takenSticks; void redraw(){ int i; //   setcolor(2); //   for(i = 0; i < stickCount; i++) line(22 + i * 6, 74, 22 + i * 6, 84); //   setcolor(11); //  for(i = stickCount; i < 15; i++) line(22 + i * 6, 74, 22 + i * 6, 84); //     setcolor(1); //   delayredraw(); } void playersMove(){ //    ,     .  while(key == previouseKey){ key = getkey(); } while(key != KEY_LEFT && key != KEY_DOWN && key != KEY_RIGHT){ key = getkey(); } if(key & KEY_LEFT){ takenSticks = 1; }else if(key & KEY_DOWN){ takenSticks = 2; }else{ takenSticks = 3; } printf("%d, ", takenSticks); stickCount -= takenSticks; previouseKey = key; } void computersMove(){ if(stickCount % 4){ //   ,    takenSticks = stickCount % 4; }else{ //      takenSticks = 1 + random(1); } stickCount -= takenSticks; printf("%d, ", takenSticks); } void game(){ // stickCount = 15; clearscreen(); //       gotoxy(8,0); puts(""); gotoxy(2,1); puts(" 1,2  3 .  ,   . :\n"); // 27,25  26   printf(" %c 1 %c 2 %c 3", 27, 25, 26); gotoxy(0,12); redraw(); while(1){ playersMove(); if(stickCount <= 0){ gotoxy(3,8); puts(" "); return; } redraw(); computersMove(); redraw(); if(stickCount <= 0){ gotoxy(3,8); puts(" "); return; } } } void main(){ while(1){ game(); //  settimer(1,1000); while(gettimer(1)){} while(getkey() == 0){} previouseKey = key; } } 

Vous pouvez le tester immédiatement. Suivez le lien, puis cliquez sur compiler, puis exécutez. Si vous voulez en savoir plus sur les possibilités de l'IDE, vous pouvez lire le tutoriel . Merci de votre attention.

Source: https://habr.com/ru/post/fr459714/


All Articles