;Codé par Denis Duplan pour Stash of Code (http://www.stashofcode.fr, stashofcode@gmail.com) en 2017. ;Ce(tte) oeuvre est mise à disposition selon les termes de la Licence (http://creativecommons.org/licenses/by-nc/4.0/) Creative Commons Attribution - Pas d’Utilisation Commerciale 4.0 International. ;Test du détournement de $6C pour mettre un code sous interruption VERTB. Le Copper attend le milieu de l'écran pour passer COLOR00 à $0F00 (rouge). Le CPU lit dans VPOSR et VHPOSR pour attendre le quart supérieur de l'écran, stocke $00F0 (vert) dans color, déclenche une interruption niveau 3 en positionnant VERTB dans INTREQ. Le gestionnaire de l'interruption passe COLOR00 à color (vert), stocke $000F (bleu) dans color, et acquitte l'événement en effaçant VERTB dans INTREQ. Pour finir, le hardware attend la fin de la trame (dépassement de la 313ème ligne en PAL), puis déclenche une interruption de niveau 3 en positionnant VERTB dans INTREQ. Le gestionnaire de l'interruption passe COLOR00 à color (bleu), stocke $000F (bleu) dans color - ça ne sert à rien, mais on ne l'inhibe pas en compliquant le code du gestionnaire par un test -, et acquitte l'événement en effaçant VERTB dans INTREQ. ;Le hardware positionne TOUJOURS le bit correspondant à un événement dans INTREQ. Toutefois, il ne génère une interruption CPU associée (par exemple, une interruption de niveau 3 pour l'événement VERTB) que si le bit correspondant est positionné dans INTENA. Par ailleurs, le hardware n'efface JAMAIS le bit dans INTREQ : c'est la tâche du gestionnaire de l'événement. En conséquence, si VERTB entraîne une interruption CPU mais que le gestionnaire d'interruption (vecteur 27 => adresse $6C) n'acquitte pas l'événement en effaçant VERTB dans INTREQ, ce gestionnaire est appelé en permanence car le hardware maintient l'interruption niveau 3 - le CPU rend la main, mais à peine. Noter qu'il est possible de générer un événement à la place du CPU en positionnant le bit correspondant dans INTREQ. Un test montre que lorsque VERTB est positionné manuellement (ie : move.w #$8020,INTREQ(a5)) durant la trame, le hardware n'en continue pas moins de le positionner à la fin de la trame. ;---------- Directives ---------- SECTION yragael,CODE_C ;---------- Constantes ---------- ;Registres VPOSR=$004 INTENA=$09A INTENAR=$01C INTREQ=$09C INTREQR=$01E DMACON=$096 DMACONR=$002 COLOR00=$180 COP1LCH=$080 COPJMP1=$088 ;Programme DISPLAY_Y=$2C DISPLAY_DY=256 COPSIZE=2*4+4 ;---------- Initialisations ---------- ;Empiler les registres movem.l d0-d7/a0-a6,-(sp) ;StingRay's stuff lea graphicsLibrary,a1 movea.l $4,a6 jsr -408(a6) ;OpenLibrary () move.l d0,graphicsBase move.l graphicsBase,a6 move.l $22(a6),view movea.l #0,a1 jsr -222(a6) ;LoadView () jsr -270(a6) ;WaitTOF () jsr -270(a6) ;WaitTOF () jsr -228(a6) ;WaitBlit () jsr -456(a6) ;OwnBlitter () move.l graphicsBase,a1 movea.l $4,a6 jsr -414(a6) ;CloseLibrary () moveq #0,d0 ;Default VBR is $0 movea.l $4,a6 btst #0,296+1(a6) ;68010+? beq _is68000 lea _getVBR,a5 jsr -30(a6) ;SuperVisor () move.l d0,VBRPointer bra _is68000 _getVBR: movec vbr,d0 rte _is68000: ;Couper le système jsr -132(a6) ;Allouer de la mémoire en CHIP mise à 0 pour la Copper list move.l #COPSIZE,d0 move.l #$10002,d1 jsr -198(a6) move.l d0,copperlist ;Couper les interruptions hardware et les DMA lea $DFF000,a5 move.w INTENAR(a5),intena move.w #$7FFF,INTENA(a5) move.w INTREQR(a5),intreq move.w #$7FFF,INTREQ(a5) move.w DMACONR(a5),dmacon move.w #$07FF,DMACON(a5) ;Détourner les vecteurs d'interruption movea.l VBRPointer,a0 lea $64(a0),a0 lea vectors,a1 REPT 6 ;Les interruptions hardware génèrent des interruptions de niveau 1 à 6 correspondant aux vecteurs 25 à 30 pointant sur les adresses $64 à $78 move.l (a0),(a1)+ move.l #_rte,(a0)+ ENDR ;Ecrire la Copper list move.l copperlist,a0 move.w #((DISPLAY_Y+(DISPLAY_DY>>1))<<8)!$0001,(a0)+ move.w #$FF00,(a0)+ move.w #COLOR00,(a0)+ move.w #$0F00,(a0)+ move.l #$FFFFFFFE,(a0)+ ;---------- Programme principal ---------- ;Activer la Copper list move.l copperlist,COP1LCH(a5) clr.w COPJMP1(a5) move.w #$8280,DMACON(a5) ;DMAEN=1, COPEN=1 ;Activer l'interruption VERTB movea.l VBRPointer,a0 move.l #_VERTB,$6C(a0) move.w #$C020,INTENA(a5) ;INTEN=1, VERTB=1 ;Boucle principale _loop: ;Attendre le premier quart de la hauteur de l'écran _wait0: move.l VPOSR(a5),d0 lsr.l #8,d0 and.w #$01FF,d0 cmpi.w #DISPLAY_Y+(DISPLAY_DY>>2),d0 blt _wait0 ;Déclencher une interruption VERTB move.w #$00F0,color move.w #$8020,INTREQ(a5) ;Attendre une ligne suivante _wait1: move.l VPOSR(a5),d0 lsr.l #8,d0 and.w #$01FF,d0 bne _wait1 ;Attendre la ligne 0 car le code prend moins de temps qu'il n'en faut au raster pour balayer les lignes DISPLAY_Y+DISPLAY_DY à 312 et donc reboucler sur la ligne 0 ;Tester la pression du bouton gauche de la souris btst #6,$BFE001 bne _loop ;---------- Finalisations ---------- ;Couper les interruptions hardware et les DMA move.w #$7FFF,INTENA(a5) move.w #$7FFF,INTREQ(a5) move.w #$07FF,DMACON(a5) ;Rétablir les vecteurs d'interruption movea.l VBRPointer,a0 lea $64(a0),a0 lea vectors,a1 REPT 6 move.l (a1)+,(a0)+ ENDR ;Rétablir les interruptions hardware et les DMA move.w dmacon,d0 bset #15,d0 move.w d0,DMACON(a5) move.w intreq,d0 bset #15,d0 move.w d0,INTREQ(a5) move.w intena,d0 bset #15,d0 move.w d0,INTENA(a5) ;Rétablir la Copper list lea graphicsLibrary,a1 movea.l $4,a6 jsr -408(a6) ;OpenLibrary () move.l d0,graphicsBase movea.l d0,a0 move.l 38(a0),COP1LCH(a5) clr.w COPJMP1(a5) ;StingRay's stuff movea.l view,a1 move.l graphicsBase,a6 jsr -222(a6) ;LoadView () jsr -462(a6) ;DisownBlitter () move.l graphicsBase,a1 movea.l $4,a6 jsr -414(a6) ;CloseLibrary () ;Rétablir le système jsr -138(a6) ;Libérer la mémoire movea.l copperlist,a1 move.l #COPSIZE,d0 jsr -210(a6) ;Dépiler les registres movem.l (sp)+,d0-d7/a0-a6 rts ;---------- Interruptions ---------- ;VERTB _VERTB: ; movem.l d0-d7/a0-a6,-(sp) ;Indispensable, mais à limiter aux registres modifiés move.w color,COLOR00(a5) move.w #$000F,color ;Acquitter l'événement VERTB move.w #$0020,INTREQ(a5) ; movem.l (sp)+,d0-d7/a0-a6 ;Indispensable, mais à limiter aux registres modifiés rte ;Inhibition _rte: rte ;---------- Données ---------- graphicsLibrary: DC.B "graphics.library",0 EVEN graphicsBase: DC.L 0 view: DC.L 0 intena: DC.W 0 intreq: DC.W 0 dmacon: DC.W 0 VBRPointer: DC.L 0 vectors: BLK.L 6 copperlist: DC.L 0 color: DC.W 0