Alcuni mesi fa, analizzando il Demo "Lost In Time" dei Covenant, mi sono
imbattuto in una routine parecchio "strana"
7300 A9 00 LDA #$00
7302 8D 00 08 STA $0800
7305 8D 01 08 STA $0801
7308 8D 02 08 STA $0802
730B 8D 03 08 STA $0803
730E 8D 04 08 STA $0804
....
....
7A94 8D 86 0A STA $0A86
7A97 8D 87 0A STA $0A87
7A9A 60 RTS
questa routine non fa altro che azzerare la memoria tra $0800 e $0a87, e lo
fa usando delle semplici STA e senza cicli. Tutto questo per velocizzare al
massimo l'esecuzione. Siamo di fronte a un cosidetto "unrolling" cioe'
l'espansione di un ciclo per fare in modo che questo impieghi meno tempo,
a discapito dell'occupazione in memoria e della leggibilita'.
Un ciclo come questo
LDA #$00
TAY
loop
STA $0800,y
STA $0900,y
INY
BNE loop
LDY #$87
loop2
STA $0A00,y
DEY
BPL loop2
RTS
effettua la stessa cosa in meno bytes, ma MOLTO piu' lentamente, perche' ogni
volta, oltre ad effettuare le STA deve perdere tempo per i controlli e i salti.
Infatti il demo in questione chiama la routine ad ogni interrupt, se sostituita
con questa mia prova, come volevasi dimostrare, va tutto a donnine allegre
L'inconveniente e' che la routine "unrolled" occupa molto spazio ma ancora
peggio NON viene compressa quasi per niente
clr7300-7a9a.prg ¦ 1949
clr7300-7a9a.Pucrunch.prg ¦ 1851
clr7300-7a9a.Crushed.prg ¦ 1622
clr7300-7a9a.Exomizer.prg ¦ 1355
Exomizer come al solito fa qualcosa meglio degli altri ma ancora non ci siamo,
se la routine fosse piu' lunga? Sempre peggio.
L'ideale sarebbe GENERARE in automatico la routine, lasciando la memoria libera
e ovviamente comprimibile.
; generate unrolled fillmem subroutine then jump to demo init. V2
; -=[iAN CooG/HokutoForce]=- for Covenant's "Lost in time" demo
; part 6.*
; example:
; *=$7300
; lda #$00
; sta $0800
; sta $0801
; ....etc...
; sta $0a87
; rts
*=$c000
cleanaddr=$0800
endaddr =$0a88
startcode=$7300
fillvalue=$0
jmpaddr =$1000
sei
lda #<startcode+2 ; prepare the values for the 1st STA
sta $fb
lda #>startcode
sta $fc
lda #<cleanaddr
sta $fd
lda #>cleanaddr
sta $fe
lda #$a9 ; prepare the LDA#$00
ldx #<fillvalue
sta startcode
stx startcode+1
ldy #$00
loop1
lda #$8d ; STA opcode
jsr sub1
lda $fd ; low byte
jsr sub1
lda $fe ; hi byte
jsr sub1
inc $fd
bne no
inc $fe
no
lda $fe
cmp #>endaddr
bne loop1
lda $fd
cmp #<endaddr
bne loop1
lda #$60 ;RTS opcode
sta ($fb),y
cli
jmp jmpaddr; start the demo
;---------------------------
sub1
sta ($fb),y
iny
bne lx
inc $fc
lx
rts
In soli 78 bytes genera la routine, e si puo' lasciare lo spazio $7300-7a9a libero con grande contentezza dei compressori.