Portage de Lode Runner de la Colombie-Britannique à UKNC

En mars-mai de cette année, j'ai passé plusieurs semaines (le soir et le week-end) à porter le jouet Lode Runner du BK-0010 au UKSC.
Capture d'écran du menu porté:

Écran de jeu de la version portée:


BK-0010 est un ordinateur domestique de la fin des années 1980 et du début des années 1990, et en partie un ordinateur scolaire (classes KUVT-86). UKSC est un ordinateur scolaire des années 1990. BC et UKSC sont partiellement compatibles dans l'architecture et le système de commande - les deux ordinateurs remontent à la famille PDP-11.

Sélection de jeux


Jusqu'à cette année, je n'avais rien écrit de sérieux sous UKSC, mais je devais comprendre le code machine. Il y avait un désir d'écrire quelque chose, mais généralement j'ai de gros problèmes avec le temps libre, donc ça ne marcherait pas à partir de zéro. Et pour commencer, il vaut mieux prendre la tâche plus facilement. Lors du portage, la quantité de travail est généralement beaucoup moins importante que lors de l'écriture à partir de zéro - vous rencontrez principalement des problèmes d'incompatibilité entre les deux systèmes.

Sur le forum zx.pk.ru (l'un des sites où les fans de rétrocomputing en général et de machines compatibles PDP-11 en particulier se retrouvent), le participant hobot a salué la mise en œuvre de Lode Runner sur la Colombie - Britannique - c'était en fait la raison, pour commencer j'ai essayé de «regarder» le code du jouet , eh bien, je me suis impliqué.

Menu de la version originale:

L'écran de jeu de la version originale (sur le moniteur couleur):


Rétro-ingénierie


Quelques semaines le soir et le week-end, j'ai passé du temps à analyser et à démonter. Dans l' émulateur, BKBTL a ajouté la possibilité de collecter une trace , c'est-à-dire que chaque instruction est démontée et enregistrée dans un fichier texte.
Je fais un tour de la section qui m'intéresse avec l'enregistrement de la trace, puis je désactive la trace (sort & uniq) - j'obtiens des fragments de la logique. J'ajoute des commentaires à cela, j'obtiens progressivement un fichier commun.

Cela semble simple, mais en fait c'est un travail assez compliqué basé sur des conjectures et leur confirmation ou réfutation. Par exemple, on regarde que l'adresse 001756 avant le début du jeu reçoit la valeur 10, puis elle est décrémentée, lorsqu'elle atteint 0, le jeu se termine - apparemment c'est le nombre de vies. Nous en trouvons la confirmation, nous plaçons des commentaires sur le texte où se trouve cette adresse. Ceci est un exemple assez simple, dans des cas plus complexes, j'ai passé beaucoup de temps à comprendre ce qui se passait.

Lorsque le volume reçu est devenu assez important (plus de 40 Ko de texte, plus de 1500 lignes) et j'ai compris au moins en termes généraux ce qui se passait, comment il était stocké et affiché - j'ai commencé à réfléchir à la façon de le traduire au UKSC.

Ici, vous pouvez consulter la liste finale résultant du démontage:
github.com/nzeemin/uknc-loderunner/blob/master/original/loderunner.lst

Labyrinthe


Chaque labyrinthe est composé de 20 lignes de 30 blocs, soit un total de 600 blocs.
Le type de bloc est codé par un nombre de 0 à 7 - trois bits, triplet. Pour un mot de 16 bits, 5 triplets complets sont obtenus.
Lorsque vous travaillez avec des machines de type PDP-11, un système à 8 décimales est largement utilisé, il est donc très pratique d'utiliser des triplets.
En conséquence, chaque labyrinthe tient dans 240 octets.

Types de blocs:
;	0 -- 
;	1 --  
;	2 --  
;	3 -- 
;	4 -- 
;	5 -- 
;	6 -- 
;	7 -- 

Les sprites de ces objets sont classés dans l'ordre de numérotation des types de blocs. Lorsqu'un labyrinthe est décodé, en même temps une «image de labyrinthe» est créée dans la mémoire (par octet par bloc), et l'état initial du labyrinthe est dessiné à l'écran.

Organisation de l'écran


Sur le BC, l'écran est adressé directement en accédant à la mémoire, les lignes vont les unes après les autres, en fait c'est un "framebuffer", et je dirais que ça va - c'est très pratique pour programmer des graphiques. Ligne BC - 256 pixels couleur, 64 octets par ligne. Mais le nombre de pixels dans une rangée dépend de la façon dont vous avez connecté le moniteur:
s'il est en noir et blanc, il s'agit de 512 pixels n / b dans une rangée (1 bit par pixel, 8 pixels par octet),
et s'il s'agit de la sortie couleur , il s'agit alors de 256 pixels couleur par ligne (2 bits par pixel, 4 pixels par octet).

À l'UKSC, l'organisation de l'écran est complètement différente et beaucoup plus compliquée. L'écran repose sur trois blocs de mémoire, trois «plans». Et chaque pixel est de trois bits, un peu dans chaque plan - nous obtenons 8 couleurs. Au UKSC, nous avons plusieurs modes vidéo - 640 × 288, 320 × 288, 160 × 288, plus précisément, nous avons toujours exactement 288 lignes et vous pouvez appliquer votre propre diviseur à chaque ligne individuelle, en obtenant différentes résolutions horizontales. Pour l'unité centrale de traitement (CPU), les plans d'écran ne sont pas directement accessibles, uniquement via l'accès aux ports. De plus, seuls deux plans sur trois sont disponibles pour le CPU.

Dans ce cas, le mode 320 × 288 me convenait bien - la ligne est obtenue en 320 pixels couleur de 80 octets de long dans chacun des trois plans. Si vous utilisez deux plans, les pixels sont également en quadrichromie - presque comme sur un BC.

Synthèse


Il a commencé à écrire des exemples en assembleur de l'UKSC et était un peu déprimé - car le cycle «compilé - lié - lancé» est assez lent. Le problème est dans les outils. Il existe un assembleur croisé MACRO11, bien qu'il soit quelque peu bogué. Mais il n'y a pas de réticulant. Mais heureusement, il n'y a pas si longtemps, Patron a publié la console RT-11: zx-pk.ru/showthread.php?t=24755 - en fait, c'est un émulateur d'une machine compatible PDP11 qui interagit avec la ligne de commande du système d'exploitation comme avec un terminal. Ainsi, il est devenu possible de compiler et de lier les moyens natifs de RT-11. Je considère cela comme une véritable percée, accélérant considérablement le travail.

Après cela, les choses se sont bien passées, j'ai fait un dessin du cadre du terrain de jeu, dessiné des sprites, compris comment mélanger les bits dans les sprites (j'ai écrit un programme C # pour les mélanger), puis j'ai commencé à transférer les blocs du fichier partagé avec disasma vers les nouvelles sources en blocs. J'ai pris un vidage de mémoire du BC, alloué un bloc où se trouvent les niveaux, l'utilitaire RT11 DUMP a fait un manuel pour les niveaux.

Tout d'abord, j'ai transféré un bloc de code qui affiche le niveau, sur ce j'ai débogué la sortie des sprites. Puis il a commencé à transférer la logique du jeu. Ceux. en général, le transfert est presque un à un, à l'exception des endroits où passe l'écran. Par conséquent, il y a des endroits dans la logique où je ne comprends pas comment ils fonctionnent (le même enfer de l'IA), mais cela n'a pas d'importance - l'essentiel est qu'ils fonctionnent.

En conséquence, au début du mois de mai (lorsque le travail principal m'a absorbé à nouveau), une option de travail a été obtenue, bien que sans son.

Photo d'un jeu de travail sur une vraie machine (merci hobot):


Références


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


All Articles