home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / software / testi / corsoasm / sorgenti_darkcoder / skip / mask2.s < prev    next >
Encoding:
Text File  |  1998-02-19  |  13.9 KB  |  392 lines

  1.         ************************************
  2.         *       /\/\                       *
  3.         *      /    \                      *
  4.         *     / /\/\ \ O R B_I D           *
  5.         *    / /    \ \   / /              *
  6.         *   / /    __\ \ / /               *
  7.         *   ¯¯     \ \¯¯/ / I S I O N S    *
  8.         *           \ \/ /                 *
  9.         *            \  /                  *
  10.         *             \/                   *
  11.         *     Feel the DEATH inside!       *
  12.         ************************************
  13.         * Coded by:                        *
  14.         * The Dark Coder / Morbid Visions  *
  15.         ************************************
  16.  
  17. * ATTENZIONE:
  18. ; Questo sorgente e` basato sulla Lezione11h4.s del Corso di Randy
  19. ; Mostra come effettuare il mascheramento anche per posizioni verticali
  20. ; in TUTTO lo schermo. Commenti alla fine del sorgente
  21. ; I credits per il sorgente originale sono di Randy - RJ
  22. ; Ehi Randy spero che non te la prendi se miglioro il tuo lavoro!
  23. ; Friendship RULEZ! :)))) (The Dark Coder)
  24.  
  25.     SECTION    DK,code
  26.     incdir    "/include/"
  27.     include    MVstartup.s        ; Codice di startup: prende il
  28.                     ; controllo del sistema e chiama
  29.                     ; la routine START: ponendo
  30.                     ; A5=$DFF000
  31.  
  32.         ;5432109876543210
  33. DMASET    EQU    %1000001010000000    ; solo copper DMA
  34.  
  35. START:
  36.     lea    $dff000,a5
  37.     MOVE.W    #DMASET,$96(a5)        ; DMACON - abilita bitplane, copper
  38.                     ; e sprites.
  39.  
  40.     move.l    #COPPERLIST,$80(a5)    ; Puntiamo la nostra COP
  41.     move.w    d0,$88(a5)        ; Facciamo partire la COP
  42.     move.w    #0,$1fc(a5)        ; Disattiva l'AGA
  43.     move.w    #$c00,$106(a5)        ; Disattiva l'AGA
  44.     move.w    #$11,$10c(a5)        ; Disattiva l'AGA
  45.  
  46. mouse:
  47.     MOVE.L    #$1ff00,d1    ; bit per la selezione tramite AND
  48.     MOVE.L    #$13000,d2    ; linea da aspettare = $130, ossia 304
  49. Waity1:
  50.     MOVE.L    4(A5),D0    ; VPOSR e VHPOSR - $dff004/$dff006
  51.     ANDI.L    D1,D0        ; Seleziona solo i bit della pos. verticale
  52.     CMPI.L    D2,D0        ; aspetta la linea $130 (304)
  53.     BNE.S    Waity1
  54.  
  55.     btst    #2,$dff016    ; tasto destro premuto?
  56.     beq.s    Mouse2        ; se si non eseguire MuoviCopper
  57.  
  58.     bsr.s    MuoviCopper    ; Routine che sfrutta il mascheramento del WAIT
  59.  
  60. mouse2:
  61.     MOVE.L    #$1ff00,d1    ; bit per la selezione tramite AND
  62.     MOVE.L    #$13000,d2    ; linea da aspettare = $130, ossia 304
  63. Aspetta:
  64.     MOVE.L    4(A5),D0    ; VPOSR e VHPOSR - $dff004/$dff006
  65.     ANDI.L    D1,D0        ; Seleziona solo i bit della pos. verticale
  66.     CMPI.L    D2,D0        ; aspetta la linea $130 (304)
  67.     BEQ.S    Aspetta
  68.  
  69.     btst    #6,$bfe001    ; mouse premuto?
  70.     bne.s    mouse
  71.     rts
  72.  
  73. *****************************************************************************
  74.  
  75. MuoviCopper:
  76.     move    PosBarra(pc),d0    ; legge posizione Barra
  77.  
  78.     tst.b    SuGiu        ; Dobbiamo salire o scendere? se SuGiu e'
  79.                 ; azzerata, (cioe' il TST verifica il BEQ)
  80.                 ; allora saltiamo a VAIGIU, se invece e' a $FF
  81.                 ; (se cioe' questo TST non e' verificato)
  82.                 ; continuiamo salendo (facendo dei subq)
  83.     beq.w    VAIGIU
  84.  
  85.     cmp    #$34,d0        ; confronta con il limite in alto
  86.     sne    SuGiu        ; setta di conseguenza il flag
  87.  
  88. ; aggiorna posizione barra nella variabile e nella CLIST
  89.     move    PosBarra(pc),d0
  90.     subq    #1,d0
  91.     move    d0,PosBarra
  92.     move.b    d0,Barra    ; scrive byte basso nella copperlist
  93.  
  94. ; la seconda WAIT 255 deve essere attivata quando l'ultima riga della
  95. ; barretta si trova alla riga $FE, ovvero quando PosBarra=$fe-8
  96.     cmp    #$fe-8,d0
  97.     bne.s    .NoAttiva2        ; se la barretta inizia ad attraversare
  98.     move.b    #$ff,Attendi255_2    ; riga 255 abilita la seconda WAIT 255
  99.     bra.s    .change            ; salta il controllo di riga $100
  100. .NoAttiva2
  101.  
  102. ; la prima WAIT 255 deve essere attivata quando la prima riga della
  103. ; barretta si trova alla riga $ff
  104.     cmp    #$ff,d0
  105.     bne.s    .NoDisattiva1        ; se TUTTA la barretta ha attraversato 
  106.     move.b    #$00,Attendi255_1    ; riga 255, disattiva la prima WAIT 255
  107. .NoDisattiva1
  108.  
  109. .change
  110.     move    #$7f,d0
  111.     bsr    AdjustClist
  112.  
  113.     move    #$ff,d0
  114.     bsr    AdjustClist
  115.  
  116.     rts
  117.  
  118. VAIGIU:
  119.     cmp    #$114,d0    ; confronta con il limite in basso
  120.     seq    SuGiu        ; setta di conseguenza il flag
  121.  
  122. ; aggiorna posizione barra nella variabile e nella CLIST
  123.     move    PosBarra(pc),d0
  124.     addq    #1,d0
  125.     move    d0,PosBarra
  126.     move.b    d0,Barra    ; scrive byte basso nella copperlist
  127.  
  128. ; la seconda WAIT 255 deve essere disattivata quando l'ultima riga della
  129. ; barretta si trova alla riga $FF, ovvero quando PosBarra=$ff-8
  130.     cmp    #$ff-8,d0
  131.     bne.s    .NoDisattiva2    ; se la barretta inizia ad attraversare la
  132.     move.b    #0,Attendi255_2    ; riga 255 disabilita la seconda WAIT 255
  133.     bra.s    .change        ; salta il controllo di riga $100
  134. .NoDisattiva2
  135.  
  136. ; la prima WAIT 255 deve essere attivata quando la prima riga della
  137. ; barretta si trova alla riga $100
  138.     cmp    #$100,d0
  139.     bne.s    .NoAttiva1        ; se TUTTA la barretta ha attraversato 
  140.     move.b    #$ff,Attendi255_1    ; riga 255, attiva la prima WAIT 255
  141. .NoAttiva1
  142.  
  143. .change
  144.     move    #$80,d0
  145.     bsr    AdjustClist
  146.  
  147.     move    #$100,d0
  148.     bsr    AdjustClist
  149.  
  150.     rts
  151.  
  152.  
  153. Finito:
  154.     rts
  155.  
  156. ; variabili
  157. PosBarra    dc.w    $34    ; posizione barra
  158. SuGiu:        dc.b    0    ; flag direzione
  159.  
  160.  
  161. *******************************
  162. * Routine che corregge la CLIST
  163. * D0 - riga target, cioe` riga che delimita l'ingresso in una diversa
  164. * zona dello schermo.
  165.  
  166.     cnop    0,4
  167. AdjustClist
  168.     move    PosBarra(pc),d1    ; coordinata prima riga barra
  169.     move    d1,d2
  170.  
  171.     addq    #8,d2        ; posizione ultima riga barra (sono 9 righe)
  172.     cmp    d0,d2        ; confronta con riga target
  173.     blo.s    .exit        ; se minore, la barra si trova TUTTA
  174.                 ; al di sopra della riga target
  175.  
  176.     sub    d1,d0        ; sottrae la pos dalla riga target
  177.     blo.s    .exit        ; se D1>D0, la barra si trova TUTTA
  178.                 ; al di sotto della riga target
  179.  
  180.                 ; altrimenti la differenza ci dice
  181.                 ; quale riga della barra ha posizione uguale
  182.                 ; a quella della riga target.
  183.  
  184. ; in D0 c'e` indicato il numero d'ordine della WAIT da modificare:
  185. ; moltiplica per 12, offset tra 2 WAIT
  186.     asl    #2,d0
  187.     move    d0,d1
  188.     add    d0,d0
  189.     add    d1,d0
  190.  
  191.     lea    PrimaWaitMascherata,a0
  192.     bchg    #7,(a0,d0.w)
  193.     
  194. .exit
  195.     rts
  196.     
  197. *****************************************************************************
  198.  
  199.     SECTION    GRAPHIC,DATA_C
  200.  
  201. COPPERLIST:
  202.     dc.w    $100,$200
  203.     dc.w    $180,$000    ; Inizio la cop col colore NERO
  204.  
  205.     dc.w    $2c07,$FFFE    ; una piccola barretta fissa verde
  206.     dc.w    $180,$010
  207.     dc.w    $2d07,$FFFE
  208.     dc.w    $180,$020
  209.     dc.w    $2e07,$FFFE
  210.     dc.w    $180,$030
  211.     dc.w    $2f07,$FFFE
  212.     dc.w    $180,$040
  213.     dc.w    $3007,$FFFE
  214.     dc.w    $180,$030
  215.     dc.w    $3107,$FFFE
  216.     dc.w    $180,$020
  217.     dc.w    $3207,$FFFE
  218.     dc.w    $180,$010
  219.     dc.w    $3307,$FFFE
  220.     dc.w    $180,$000
  221.  
  222. Attendi255_1:
  223.     dc.w    $00E1,$FFFE    ; aspetta linea 255
  224.  
  225. BARRA:
  226.     dc.w    $3407,$FFFE    ; aspetto la linea $79 (WAIT NORMALE!)
  227.                 ; questo wait e' il "BOSS" dei wait
  228.                 ; mascherati seguenti, infatti lo seguono
  229.                 ; come degli scagnozzi: se questo wait
  230.                 ; scende di 1, tutti i wait mascherati
  231.                 ; sottostanti scendono di 1, eccetera.
  232.  
  233.     dc.w    $180,$300    ; inizio la barra rossa: rosso a 3
  234.  
  235. PrimaWaitMascherata:
  236.     dc.w    $00E1,$80FE    ; Questa WAIT attende la fine di una riga.
  237.                 ; Si tratta di una WAIT con posizione
  238.                 ; verticale mascherata. Poiche` questa
  239.                 ; istruzione va eseguita DOPO la riga
  240.                 ; $80, il bit alto (non mascherabile)
  241.                 ; deve essere settato a 1.
  242.  
  243.     dc.w    $0001,$FFFE    ; questa WAIT e` un istruzione "inutile"
  244.                 ; infatti non blocca mai il copper.
  245.                 ; Il suo scopo e` quello di far perdere
  246.                 ; un po' di tempo al copper in maniera che
  247.                 ; la seguente CMOVE venga eseguita quando
  248.                 ; il pennello elettronico ha iniziato la
  249.                 ; riga seguente.
  250.  
  251.     dc.w    $180,$600    ; rosso a 6
  252.  
  253.     dc.w    $00E1,$80FE    ; aspetta fine riga
  254.     dc.w    $0001,$FFFE    ; WAIT inutile che rallenta il copper
  255.  
  256.     dc.w    $180,$900    ; rosso a 9
  257.  
  258.     dc.w    $00E1,$80FE    ; aspetta fine riga
  259.     dc.w    $0001,$FFFE    ; WAIT inutile che rallenta il copper
  260.  
  261.     dc.w    $180,$c00    ; rosso a 12
  262.  
  263.     dc.w    $00E1,$80FE    ; aspetta fine riga
  264.     dc.w    $0001,$FFFE    ; WAIT inutile che rallenta il copper
  265.  
  266.     dc.w    $180,$f00    ; rosso a 15 (al massimo)
  267.  
  268.     dc.w    $00E1,$80FE    ; aspetta fine riga
  269.     dc.w    $0001,$FFFE    ; WAIT inutile che rallenta il copper
  270.  
  271.     dc.w    $180,$c00    ; rosso a 12
  272.  
  273.     dc.w    $00E1,$80FE    ; aspetta fine riga
  274.     dc.w    $0001,$FFFE    ; WAIT inutile che rallenta il copper
  275.  
  276.     dc.w    $180,$900    ; rosso a 9
  277.  
  278.     dc.w    $00E1,$80FE    ; aspetta fine riga
  279.     dc.w    $0001,$FFFE    ; WAIT inutile che rallenta il copper
  280.  
  281.     dc.w    $180,$600    ; rosso a 6
  282.  
  283.     dc.w    $00E1,$80FE    ; aspetta fine riga
  284.     dc.w    $0001,$FFFE    ; WAIT inutile che rallenta il copper
  285.  
  286.     dc.w    $180,$300    ; rosso a 3
  287.  
  288.     dc.w    $00E1,$80FE    ; aspetta fine riga
  289.     dc.w    $0001,$FFFE    ; WAIT inutile che rallenta il copper
  290.  
  291.     dc.w    $180,$000    ; colore NERO
  292.  
  293. Attendi255_2:
  294.     dc.w    $FFE1,$FFFE    ; aspetta linea 255
  295.  
  296.     dc.w    $2007,$FFFE    ; aspetto la linea $FD
  297.     dc.w    $180,$00a    ; blu intensita' 10
  298.     dc.w    $2107,$FFFE    ; linea seguente
  299.     dc.w    $180,$00f    ; blu intensita' massima (15)
  300.  
  301.     dc.w    $FFFF,$FFFE    ; FINE DELLA COPPERLIST
  302.  
  303.     end
  304.  
  305. In questo esempio mostriamo come usare il mascheramento della posizione
  306. verticale in TUTTO lo schermo. Abbiamo la solita barretta che stavolta si
  307. muove lungo tutto lo schermo. Come sappiamo per usare le WAIT con Y maschera-
  308. ta si deve porre il bit 8 della posizione specificata allo stesso valore della
  309. posizione verticale in cui vogliamo che l'istruzione venga eseguita.
  310. Per comodita`, nel seguito indicheremo come zona 1 dello schermo le righe
  311. da 0 a $7F, zona 2 le righe da $80 a $FF e zona 3 le righe da $100 in poi.
  312.  
  313. Se abbiamo delle copperlist dinamiche tali che una WAIT mascherata puo`
  314. essere eseguita in qualunque posizione dello schermo, l'unica possibilita`
  315. e` quella di modificare "al volo" le WAIT mascherate. Come abbiamo detto
  316. in skip1.s, rispetto al codice di Randy abbiamo sostituito delle WAIT
  317. mascherate DC.W $0007,$80FE con delle semplici e NON mascherate WAIT
  318. DC.W $0001,$FFFE che fanno la stessa cosa. In questo modo abbiamo dimezzato
  319. il numero di WAIT mascherate presenti nella CLIST e di conseguenza anche
  320. il numero di modifiche da fare! Nel nostro caso infatti dobbiamo modificare
  321. solo delle WAIT che aspettano la fine di una riga. Quando dobbiamo aspettare la
  322. fine di una riga nelle zone 1 o 3 dobbiamo avere DC.W $00E1,$80FE mentre nel
  323. caso in cui aspettiamo in zona 2 ci serve DC.W $80E1,$80FE.
  324. Quindi dobbiamo settare opportunamente il bit 8 di tale istruzione.
  325.  
  326. I piu` attenti si chiederanno subito:"Ma chi ce lo fa fare a sto' punto ad
  327. usare la WAIT mascherate se dobbiamo modificare comunque la CLIST?".
  328. L'osservazione e` giusta, infatti come ricorderete questo effetto puo`
  329. essere realizzato anche con WAIT non mascherate, e il vantaggio delle WAIT
  330. non mascherate e` proprio quello di non dover modificare TUTTE le WAIT ad ogni
  331. frame. Tuttavia le modifiche da apportare alle WAIT non mascherate sono molto
  332. minori. Infatti e` necessario invertire il bit 8 della posizione verticale
  333. di una WAIT SOLAMENTE quando tale WAIT passa da zona 1 a zona 2 (o viceversa)
  334. o quando passa da zona 2 a zona 3 (o viceversa), cosa che accade solo
  335. occasionalmente. Inoltre, se come in questo caso la barretta si sposta di 1
  336. sola riga ogni frame, e` evidente che di tutte le WAIT che compongono la
  337. barretta al massimo UNA SOLA WAIT passera` da una zona all'altra. Riassumendo,
  338. nel caso in cui utilizziamo delle WAIT non mascherate dobbiamo modificare
  339. TUTTE le WAIT AD OGNI frame. Con le WAIT NON mascherate invece modifichiamo
  340. UNA WAIT in POCHISSIMI frame. E` dunque evidente che le WAIT NON mascherate
  341. sono ancora molto vantaggiose.
  342.  
  343. Vediamo la realizzazione pratica. Come detto ogni volta che una WAIT transita
  344. da una zona ad un'altra dobbiamo cambiare un bit, ovvero possiamo semplicemente
  345. invertirlo. Nel passaggio da zona 2 a zona 3, abbiamo un problema in piu`:
  346. l'istruzione WAIT che aspetta la riga 255.
  347.  
  348. Vediamo per prima cosa come modificare le WAIT. Tutte le modifiche sono gestite
  349. da un'unica routine che va bene in tutti i casi, alla quale viene passato come
  350. parametro la riga "target" ovvero la riga che determina il passaggio da una
  351. zona ad un'altra. Tale routine determina l'EVENTUALE passaggio di una delle
  352. WAIT sopra la riga target e di conseguenza inverte lo stato del bit 8 della Y.
  353. Notate che se SCENDIAMO dalla zona 1 alla zona 2, la riga target e` $80,
  354. perche` non appena una WAIT viene eseguita sulla riga $80 il suo bit deve
  355. essere settato a 1. Se invece SALIAMO dalla zona 2 alla zona 1 la riga target
  356. diventa $7F, perche` non appena una WAIT viene eseguita sulla riga $80 il suo
  357. bit deve essere settato a 0.
  358. Ovviamente ad ogni iterazione la nostra routine (AdjustClist) deve essere
  359. eseguita 2 volte, una volta per controllare il passaggio da zona 1 a zona 2
  360. (o viceversa se andiamo nella direzione opposta) e una volta per controllare il
  361. passaggio da zona 2 a zona 3 (o viceversa se andiamo nella direzione opposta).
  362.  
  363. Si potrebbe obiettare che dover eseguire (2 volte) questa routine puo` far
  364. perdere il vantaggio di dover effettuare meno modifiche sulla CLIST (rispetto
  365. al caso delle WAIT NON mascherate), ma non e` cosi`: infatti questa routine
  366. ha un costo di esecuzione fisso, mentre nel caso delle WAIT NON mascherate
  367. il numero di modifiche da fare e` pari al numero di righe che compongono la
  368. barretta: pensate al caso di una barretta alta 60 righe!!
  369. Inoltre la routine e` cortissima e` viene eseguita in CACHE (se c'e`) e fa
  370. (eventualmente) un solo accesso alla CHIP (la modifica della clist), mentre
  371. nel caso NON mascherato ogni modifica di una WAIT e` un accesso in CHIP.
  372.  
  373. Come detto, il passaggio da zona 2 a zona 3 ci pone un altro problema.
  374. Nella copperlist in fatti c'e` una WAIT che attende la riga $FF (255).
  375. E` evidente che se la nostra barretta si trova piu` in alto, tale WAIT deve
  376. essere eseguita DOPO le istruzioni della barretta, mentre deve essere eseguita
  377. prima se la barretta si trova in zona 3. Per risolvere questo problema
  378. utilizziamo 2 WAIT che attendono tale riga, una prima e una dopo le istruzioni
  379. della barretta e ne abilitiamo una alla volta. Come facciamo per disabilitare
  380. e abilitare una WAIT? Semplice, basta modificarla mettendo come posizione Y 0
  381. invece che 255 per disabilitarla, e rimettere 255 per abilitarla.
  382. Notate che quando la barretta si trova in parte in zona 2 e in parte in
  383. zona 3, nessuna delle 2 WAIT deve essere abilitata, perche` l'attesa di riga
  384. 255 e` fatta dalle WAIT dalla barretta stessa. Quindi (nel caso in cui si
  385. scende da zona 2 a 3) quando la barretta si trova in zona 1 e 2 la prima WAIT
  386. e` disabilitata e la seconda abilitata. Nel momento in cui l'ultima riga della
  387. barra si trova alla riga $FF la WAIT dopo la barretta viene disabilitata,
  388. fintanto che la barra si trova a cavallo tra le 2 zone entrambe le wait restano
  389. disabilitate e quando la prima riga della barra si trova alla riga $100 la
  390. prima WAIT viene abilitata. Nel caso in cui si sale queste azioni si succedono
  391. in maniera opposta.
  392.