2015-09-27 14 views
6

Ho intenzione di utilizzare sprite software in modalità char multicolor per il mio nuovo progetto C64. La mia idea è di sovrapporre i dati sprite "bullet" ai dati delle tessere.Un modo migliore per aggiornare dinamicamente i dati delle tessere su Commodore 64

Penso di poter disporre di dati di tileset all'indirizzo "TILESET", dati di sprite all'indirizzo "SPRITE". E posso combinare queste due cose per preparare un proiettile con sfondo calcolato dinamicamente e memorizzare nell'indirizzo 'SUPERIMPOSTO'

Ho scritto il seguente codice e il conteggio dei cicli per verificare se è fattibile. E penso che non lo sia. Il ciclo mangia fino a 219 cicli. Quasi quattro linee raster. E non ho incluso altri calcoli necessari prima di questo ciclo. Come il calcolo degli indirizzi di destinazione.

Quando voglio 16 proiettili sullo schermo, ci vorranno 64 raster o 8 righe di caratteri. Quindi divento sospettoso. È questo il modo corretto? O ci sono altri modi più ottimizzati per fare lo stesso lavoro?

      cycles 
         --------- 
    ldy #$07    4 x1 = 4 
- LDA TILESET,x  3 x8 = 24 
    AND SPRITE,x  4 x8 = 32 
    STA SUPERIMPOSED,x 5 x8 = 40 
    dey     2 x8 = 16 
    cpy     4 x8 = 32 
    bne -    3 x8-1 = 71 
         ---------- 
         219 Cycle 

Sto considerando di ripetere pattern in background. In modo che io possa usare la stessa piastrella dei proiettili senza ricalcolare.

+0

Srotolare il ciclo per eliminare l'overhead al costo di un aumento del codice. Inoltre sembra che tu stia usando 'x' per l'indicizzazione ma' y' per il ciclo? – Jester

+0

Se il tuo sprite ha più di un pixel di dimensioni e vuoi essere in grado di posizionarlo su qualsiasi pixel hai bisogno di molto più codice, inclusa la possibilità di sovrapporre 2 o 4 caratteri (tessere). Se lo sprite è solo un pixel, puoi semplificare un po 'il codice. –

+0

@RossRidge Non ho ancora finito gli sprite. Quindi non sono sicuro delle dimensioni ma andrà attorno ai 4x4. – wizofwor

risposta

7

Come suggerisce Jester, come prima ottimizzazione basta ripetere lo lda, and, sta e dey otto volte. Elimina cpy e bne. Questo salverà immediatamente 103 cicli. Anche se si desidera mantenere il loop formale, notare che dey imposta il flag di zero in modo che non sia necessario lo cpy.

Come seconda ottimizzazione, prendere in considerazione uno sprite compilato. Invece di eseguire la lettura da sprite, x, avresti quei valori codificati direttamente nella tua routine, creando una routine distinta per ogni sprite. Questo avrebbe tagliato altri 16 cicli.

Detto questo, il tuo lda sarebbe 4 cicli in una tabella allineata, non 3. Quindi ci sono 8 che non hai tenuto conto. Ciò significa che srotolato più specializzato per il tuo sprite = 102 cicli (avendo omesso l'ultimo dey).

Senza conoscere l'architettura C64 e/o il resto del codice, se qualcuno ingerisce SUPERIMPOSED dalla pagina dello stack, prendere in considerazione la scrittura dell'output nello stack anziché tramite l'indirizzamento indicizzato. È sufficiente caricare s con un valore seme appropriato e memorizzare nuovi risultati tramite pha. Ciò consentirà di risparmiare due cicli per archivio al costo di 12 cicli aggiuntivi di installazione e ripristino.

Seguendo questo pensiero, se si ha la libertà di osservare queste tabelle, allora si consiglia di cambiare il loro formato - invece di una tabella che contiene tutti gli otto byte di TILESET, utilizzare otto tabelle, ognuna delle quali contiene un byte di esso. Ciò eliminerebbe la necessità di regolare y nel ciclo; basta usare una tabella di destinazione diversa in ciascuna iterazione srotolata.

Supponendo sia TILESET e SUPERIMPOSED può essere otto tabelle che si scende a:

LDA TILESET1, x 
AND #<value> 
STA SUPERIMPOSED1, x ; * 8 

[... LDA TILESET2, x ...] 

... che è un totale di 88 cicli. Se SUPERIMPOSED è lineare, ma nella pagina pila poi:

TSX 
TXA 
LDX #newdest 
TXS 
TAX    ; adds 10 

LDA TILESET1, y 
AND #<value> 
PHA    ; * 8 

[... LDA TILESET2, y ...] 

TXS    ; adds 2 

... che è di 84 cicli.

Dopo aggiunta:

Se siete disposti a premoltiplicazione dell'indice in x da 8, riducendo l'intervallo indicizzabile a 32 piastrelle, quindi si può procedere riempimento di una matrice di uscita lineare senza regolazione y, come da:

LDA TILESET, x 
AND #<value1> 
STA SUPERIMPOSED, x 

LDA TILESET+1, x 
AND #<value2> 
STA SUPERIMPOSED+1, x 

... etc ... 

Così avresti bisogno di otto copie di quella routine con diversi indirizzi di base tavolo ancora in grado di colpire 256 piastrelle di uscita. Supponendo che tu abbia 20 sprite, questo fa un totale di 20 * 8 = 160 copie della tua routine di plottaggio dello sprite, ognuna delle quali è probabilmente dell'ordine di 100 byte, quindi stai spendendo circa 16kb.

Se il tuo gioco è molto più pesante su un tipo di folletto che su altri - ad es. di solito sono due o tre astronavi che sparano migliaia di proiettili l'uno contro l'altro, quindi ovviamente è possibile ottimizzare in maniera molto selettiva e mantenere basso l'impatto totale.

Problemi correlati