owned this note
owned this note
Published
Linked with GitHub
# Astuces de puceaux.
## Façon foutrement efficace d'effectuer A := n - A.
cpl ; A := -1 - A
add n+1 ; compense -1
## CP HL,BC (stable, même flags qu'un CP classique)
Bien que n'étant pas le plus rapide, on appréciera la stabilité en temps-machine.
or a:sbc hl,bc:add hl,bc
Si le coeur vous en dit pas plus, vous pouvez empaqueter cela dans une MACRO.
On peut omettre le `OR A` si on est sûr de l'absence de retenue.
(Parenthèse enchantée) Sans doute etes-vous sûr au moment de l’écriture de l'état NC. Cependant cette supposition peut flencher au fil des remaniement de code, introduisant un bug. Aussi, je vous livre un conseil auxiliaire ; toute supposition de cette nature doit être vérifiée automatiquement. Ici, ça ressemblerait à :
```
fail = &be00 ; Breakpoint pour orgams.
if dev_checks
call c,fail ; !! expected NC for sbc below
end
sbc hl,bc:add hl,bc
```
En cas de bug ou de doute existentiel, passer `dev_checks = 1` pour vérifier l'ensemble des suppositions.
## Pile, poil, valve, vulve.
Généralement, l'utilisation de la pile pour lire/ecrire dans des tables ne fait pas bon menage avec les interruptions.
Je prends ici ma casquette de conseiller conjugal, pour vous aider à mieux conjuguer.
### Lors de l'ecriture :
* Remédiation 0: Ecrire par adresses décroissantes. C'est sûrement deja la cas, puisque dans ce scénario vous utilisez PUSH pour remplir votre table.
Le RST &38 de l'interruption et éventuels PUSH (par la routine sous interruption elle-mémé cette fois) vont alors "corrompre" une partie de la table **non encore mise à jour**. On s'en moque donc, du rire gras et insouciant qui traverse la rue en dehors des clous.
Attention, la corruption devient réelle lorsqu'on atteint le début de la table. Prévoir une zone tampon placée devant la table (juste un 1 mot si aucun PUSH ni CALL).
### Lors de la lecture :
* Remédiation 0: Là encore, s'en moquer effrontement pour des entrées à **usage unique** (dans le sens où la table sera reconstruite entre temps) : les entrées corrompues sont celles qui viennent d'etre utilisées, et vogue la galère.
* Remediation 0': Sans-doute êtes-vous une personne de goût (ou simplement nommee Goût), et votre entrée contient plusieurs mots dont seuls certains se voient rafraîchis. Auquel cas, alterner EI et DI, pour protéger les adresses sensible. Quand le but est de ne pas (trop) décaler le declenchement des interruption et d'assurer la première interruption pendant la VSYNC, il suffit de ne pas rester en DI pendant plus de 32 lignes.
* Remédiation 1: Elaborant l'idée précédente, merde j'ai oublié ce que je voulais dire.
* Remédiation 2: Backup. Lors de l'interruption, on connait l'adresse écrasée. On est donc en mesure de recalculer juste l'entrée en question. La routine sous int pourrait ressembler à :
```
int
; -- Sauvegarde contexte (pour eviter d'ecraser d'autres entrees).
ld (save_hl+1),hl
pop hl
ld (save_pc+1),hl
ld (save_sp+1),sp
ld sp,stack_int
push af:push de ; et plus si affinité
; -- Restore entry
ld hl,(save_sp+1)
; Imaginons que la table soit en 4002-4fff, et qu'il y ait un backup en 5002-6fff
dec hl
ld e,l:ld d,h
set 4,d
ld a,(de):ld (hl),a
dec de.dec hl
ld a,(de):ld (hl),a
; -- Restore context
pop de:pop af
save_hl ld hl,0
save_sp ld sp,0
ei
save_pc jp 0
```
Évidement, ce code peut se voir simplifié. Si le code interrompu n'utilise pas le registre `A`, nul besoin de sauvegarder `AF`, car `F` est inchangé.
S'il n'utilise pas les registres secondaires, encore mieux, car on n'aura même plus besoin de sauver `SP`.
Mode ninja : certains registres n'ont pas besoin de d'être sauvegardés, si les interruptions interviennent lors de sections soigneusement sélectionnées (`EI` temporaires). Là encore, très sujet aux bugs, on consolidera le code avec des assertions diverses.