1 Stella2 Stelle3 Stelle4 Stelle5 Stelle (1 votes, average: 5,00 out of 5)

Pallina che rimbalza in Assembly

(articolo dell’utente Emanuele Bonin)

Dopo anni che non toccavo l’asm del c64 (dimenticando tutto) tempo fa mi sono rimesso a fare piccoli inutili programmi acacademici per riprendere un po’ la mano. Il primo che presento è la classica pallina che rimbalza sullo schermo, ma quello che volevo fare in realtà era una specie di virus, cioè una pallina che rimbalzasse lasciando l’operatore libero di utilizzare il c64.

Quindi una volta fatta la routine bisognava inserirla tra le costole dell’interrupt del c64. In questo programma ho utilizzato tecniche molto basilari per compiere i calcoli, vedi la moltiplicazione facendo somme successive. Non ho la pretesa di insegnare nulla, per quello ci sono svariati manuali gratuiti in rete. Il fine è quello di mostrare semplici esempi da cui qualcuno potrebbe prendere spunto se a completo digiuno di programmazione assembler e di imparare io stesso qualcosa da quelli di voi che sono esperti e che si prenderanno la briga di trovare i molti punti ottimizzabili.

Ho usato CBM studio per scrivere il programma, ma penso sia adattabile ad altri programmi per assembler.

scnkey = $ff9f ; scan keyboard for keypress
screen = $0400 ; video default position
sys = $9e ; sys basic token
new = $A2 ; new basic token
scpos = $00fb ; $fb-$fc free zero location

; Add a basic line to start with a RUN
; 10 SYS 49152
; 20 New rem riga per evitare out of memory error rimette a posto il SOV
BASIC *=$801 ; BASIC
word BSYS
word $00A
byte sys ; $9E = SYS BASIC token
byte ' ' ; $20 = [space]
byte '49152'
byte $00 ; EOL

BSYS 
word BEND
word $00B
byte new ; $A2 = NEw BASIC token
byte $00 ; EOL

BEND

*=$C000 ; sys 49152
Start

sei ; disabilitazione interrupt
lda #$00 ; angolo in alto a sinistra
sta SCPos
lda #$04
sta SCPos+1
ldy #00 ; save char on current position
lda (SCPos),y
sta Saved
lda #<irq ; interuupt punta alla nostra routine
ldx #>irq
sta $314 ; salvo in $314/$315 (locazioni routine di interrupt)
stx $315 ; che sono
cli ; clear interrupt disable flag
rts
irq ; routine
php
pha
txa
pha
tya
pha
lda saved ; ristampo l'ultimo carattere
ldy #00
sta (SCPos),y
jsr IncDecX ; calcolo prossima xpos
jsr IncDecY ; calcolo prossima ypos
jsr XYtoSCPos ; screenpos = $0400 + xpos + ypos * 40
ldy #00 ; salvataggio carattere nella posizione corrente
lda (SCPos),y
sta Saved
lda #$51
ldy #00
sta (scpos),y ; stampa il pallino in xpos ypos
pla
tay
pla
tax
pla
plp
jmp $ea31 ; ritorno alla routine di interrupt standard

XYtoSCPos
lda ypos ; place ypos in factor1
sta factor1 ; lsb
lda #40 ; place 40 in factor1
sta factor2 ; lsb
lda #00 ; reset msb of factor1 & factor2
sta factor1+1 ; msb
sta factor2+1 ; msb
jsr Multiply ; ypos*40 => result
lda result ; place result in factor1
sta Factor1
lda Result+1
sta Factor1+1
lda xpos ; place xpos in factor2 (msb is #00)
sta Factor2
jsr sum16 ; xpos + result(=factor1=ypos*40) => result
lda result ; place result in factor1
sta Factor1
lda Result+1
sta Factor1+1
lda #<screen ; place $00 (lsb screen)in factor2
sta Factor2
lda #>screen ; place $04 (msb screen) in factor2+1
sta Factor2+1
jsr sum16 ; result + screen => result
lda result ; place result in scpos
sta SCPos
lda Result+1
sta SCPos+1
rts
Sum16
clc
Lda Factor1
adc Factor2
sta Result
Lda Factor1+1
adc Factor2+1
sta Result+1
rts
Multiply ; multiply factor1 * <factor2
lda #00
sta Result
sta Result+1
ldx Factor2
cpx #00
beq MultiplyEnd
lda Factor1
sta Result
lda Factor1+1
sta Result+1
LoopMul
dex
beq MultiplyEnd
clc
lda Result
adc Factor1
sta Result
lda Factor1+1
adc Result+1
sta Result+1
jmp LoopMul
MultiplyEnd
rts

IncDecX
lda #$01
ldx DirX
cpx #01
beq IFADDX
jmp IFSUBX
IFADDX
ldx XPos
cpx #39 ; reach max column so subtract 1
beq IFSUBX
ldy #$01
sty DirX
inc XPos
rts
IFSUBX
ldx XPos
cpx #00 ; reach min column so add 1
beq IFADDX
ldy #$ff
sty DirX
dec XPos
rts
IncDecY
lda #$01
ldx DirY
cpx #01
beq IFADDY
jmp IFSUBY
IFADDY
ldx YPos
cpx #24 ; reach max row so subtract 1
beq IFSUBY
ldy #$01
sty DirY
inc YPos
rts
IFSUBY
ldx YPos
cpx #00 ; reach min row so add 1
beq IFADDY
ldy #$ff
sty DirY
dec YPos
rts
Factor1 word $0000
Factor2 word $0000
Result word $0000
dirx byte $01 ; 01 forward ff backward
diry byte $01 ; 01 forward ff backward
XPos byte $11
YPos byte $10
Saved byte $00

 

Lascia un commento