Débloquer l’accès ASIC/RMR2 sur les modèles Amstrad GX/Plus

Bonjour !

Je suis tombé sur Programming:Unlocking ASIC. Des trucs vraiment sympas dans les routines optimisées ! :heart_eyes:

Et voici mon petit grain de sel sur le sujet.

Comme mentionné dans le fil de l’ancien forum en lien, c’est de la responsabilité de l’appelant de gérer les interruptions, donc exit tous les DI/EI ! -2 octets

Pour rappel, la séquence complète de déverrouillage du RMR2 à écrire sur le port d’E/S #BCxx est :
NZB, #00,#FF,#77...#8A, STATE (#CD), EOK

NZB : N’importe quelle valeur sauf zéro.
STATE : #CD va déverrouiller (toute autre valeur verrouillera).
EOK : Elle doit être envoyée pour sortir l’ASIC de sa séquence de déverrouillage et récupérer la sélection du registre CRTC. Il peut s’agir de n’importe quelle valeur.

La routine optimisée classique n’exploite pas certaines propriétés de la séquence de déverrouillage. Comme :

  • On place les données de la séquence juste après la fin de la routine, avec un RET, c’est-à-dire un opcode &C9, pas un zéro, hmm… ça m’a tout l’air d’un NZB ! : -1 octet
  • Pourquoi stocker la valeur EOK dans les données de la séquence ? Peu importe la valeur, on enverra ce qu’on trouve : -1 octet

Cela donne une version un peu plus compacte :

				; Send a 17 bytes sequence to I/O port #BCxx to unlock RMR2
				; register access. KISS approach using a table of raw values.
				;
				; Size: 28 bytes
				; Time: 178 µs
				;
				; Output:
				;  BC=&BC00
				;  Trashes HL and Flags 
rmr2_unlock:
				ld bc,&BC00+17
				ld hl,_rmr2_data_key
_rmr2_send_key		inc b
					outi
					dec c
					jr nz,_rmr2_send_key
_rmr2_data_key	ret		; This opcode is also used as SYNC/NZB value (#C9)
				db 0, &FF,&77,&B3,&51,&A8,&D4,&62,&39,&9C,&46,&2B,&15,&8A
_rmr2_data_lock	db 205	; 205 to Unlock, anything else to lock

				; The routine will over-read one byte at this location
				; to retrieve an EOK value, necessary for proper unlocking.

Et maintenant, avec ses 28 octets de long, cette routine très KISS fait passer les routines optimisées pour… Enfin bref, peu importe. (on vous aime quand même !)

Mais la réimplémentation du LFSR par @Urusergi m’a titillé la curiosité. Il y a tellement de façons et de bidouilles de bits pour implémenter ce petit truc LFSR qu’il pourrait y avoir des variations plus courtes quelque part…

…quelques jours, larmes et saignements de nez plus tard : eh bien, pas tant que ça finalement !
J’en ai trouvé une seule :

				; Software re-implementation of the LFSR logic described in
				; the Amstrad Patent (GB2243701A). It generates a 15 bytes
				; sequence as verified by the ASIC to unlock RMR2 access.
				;
				; Designed by Urusergi
				; Modified by Grim (shaving a single byte, pfew!)
				;
				; Size: 27 bytes
				; Time: 389 µs
				;
				; Output:
				;  BC=&BCFF
				;  Trashes HL and AF
rmr2_unlock:
				ld bc,&BCFF
				out (c),c ; SYNC/NZB
				out (c),0 ; SYNC/NUL
				ld a,c
_rmr2_send_key
					out (c),a
					ld h,a
					add hl,hl
					rra
					add hl,hl
					ld l,a
					xor h
					and &F7
					xor l
					add a,h
					and &88
					xor l
					cp c
					jr nz,_rmr2_send_key
				ret

J’ai essayé d’abandonner le (mignon) test de sortie cp c pour utiliser un flag à la place après le dernier xor l, mais sans succès pour l’instant. Le cp c survit ! :slight_smile:

1 « J'aime »

L’optimisation prématurée est la racine de tous les maux.

Vous n’avez besoin de déverrouiller l’ASIC qu’une seule fois. Il n’y a aucune raison sensée de le verrouiller à nouveau.

Économiser une poignée d’octets a extrêmement peu de chances d’apporter quoi que ce soit, sauf peut-être dans des scénarios bizarres du style démo 4K. Et même dans ce cas, le désavantage des machines Plus, qui ne disposent pas de routines ROM existantes à appeler pour des fonctionnalités de base comme celle-ci, anéantira généralement le moindre avantage par rapport à l’écriture de code CPC standard.

Je vois un cas d’usage potentiel pour le verrouillage de l’ASIC après la réinitialisation de certaines fonctionnalités. Ce scénario implique très probablement du code de démo CPC visant à être compatible avec le CRTC Type 3, tout en détournant intentionnellement le bit 5 du RMR du GateArray pour d’obscures raisons d’optimisation, ce qui pourrait causer des problèmes majeurs si l’ASIC reste déverrouillé.

Tu as donc raison, clairement aucune raison sensée :slight_smile:

Si ton code a conscience de l’ASIC, je pense que tu auras du mal à trouver un cas réaliste où tu dois envoyer une valeur qui perturbera RMR2. Et il est encore moins probable qu’une telle action l’emporte sur le surcoût lié au déverrouillage de l’ASIC la fois suivante où tu auras besoin de modifier l’une des fonctionnalités Plus.

C’est simplement l’un de ces scénarios qui n’a pas vraiment de sens.

Le democoding n’a pas besoin d’avoir du sens, tant que ça tourne vite. Surtout en beam-racing, on cherche généralement à entasser et bit-packer autant de données que possible dans les registres du Z80 (ils sont rapides) en les réutilisant et les détournant à mort. Et là, votre commande GA ne sert pas seulement à ça, mais agit aussi comme une adresse d’E/S fantôme pour un autre périphérique, contrôle des bits sur le Port C du PPI et tout le toutim. Chaque bit compte.

Seul votre code de démo d’initialisation du CPC doit prendre en compte l’ASIC (pour s’assurer que le matériel est stable avant de prendre la main), mais tout ce qui suit peut tranquillement considérer un CPC-GateArray où le bit 5 de commande n’a aucun effet.

Il ne s’agit donc pas de déverrouiller/verrouiller l’ASIC chaque fois qu’on a besoin d’y bidouiller quelque chose, on ne le fait qu’une seule fois. Il s’agit simplement de configurer correctement le matériel avant d’exécuter le code CPC principal (non-Plus). Il n’y a aucun surcoût à compenser ici.

Félicitations Grimmy ! :clap:

J’aurais parié ma c*** que ma routine ne pouvait pas être améliorée. Heureusement que je ne l’ai pas fait :sweat_smile:

Ça m’a bien fait rire :joy:. Ça me rappelle ces jours-là :face_with_spiral_eyes:

Je vois que @Longshot a aussi créé sa routine. Waouh ! Je savais qu’utiliser un mot double permettrait de compléter la séquence que la routine de Madram avait failli réussir, mais j’imaginais que ça prendrait beaucoup plus de place. Bravo !

Merci @Urusergi !

En effet, l’utilisation du double mot permet de la maintenir à 28 octets tout en restant totalement dynamique. Le principal avantage est qu’elle peut également reverrouiller l’ASIC à la volée via HL (sans patch RAM) et économise des cycles CPU (349 µs contre 389 µs).

Mais cette approche LFSR de 27/28 octets est vraiment une belle prouesse pour un déverrouillage ponctuel pur !

1 « J'aime »