C64 ASEMBLER (C64 ASSEMBLY) – LEKCIJA 7
C64 ASEMBLER (C64 ASSEMBLY) – LEKCIJA 7
Dobrodošli u lekciju 7 male škole programiranja u asembleru na Commodore 64.
Napomene, saveti i objašnjenja
Za poslednju lekciju smo pripremili jednu prostu video igru u asembleru na kojoj ćemo objasniti većinu naučenih asemblerskih naredbi, važne adrese i sl. Takođe ćemo uporediti dužine i brzine izvršavanja asemblerskog sa sličnim bejzik programom.
Možda će vam se na prvi pogled činiti da program ima veliki broj programskih linija u odnosu na bejzik programe iste namene ali imajte u vidu da prilikom kompajliranja mašinski kod zauzima dosta manju memoriju, a što se tiče brzine izvršavanja one su više stotina, pa i hiljade puta veće od ekvivalentnih bejzik programa (zavisno od vrste programa).
Veoma važno objašnjenje/savet za snimanje programa
Kada završimo sa unošenjem našeg asemblerskog programa (koji smo dali u današnjem primeru) i isti kompajliramo i startujemo da bi smo videli da li radi sve kako treba, ovo je način kako da radnu/izvršnu verziju direktno snimimo na disketu sa startovanjem preko programske linije u bejziku.
Prilikom kompajliranja našeg asemblerskog programa sa komandom turbo asemblera ←3 zapišimo vrednost njegove krajnje adrese / last adress (do koje memorijske lokacije se prostire).
U današnjem primeru krajnja adresa je heksadecimalna memorijska lokacija $13ee (možda kod vas ne bude tačno ova adresa pogotovu ako izvršite neke promene ili prilikom unosa teksta ispisa u programu, unesete višak ili manjak razmaka između karaktera ili znaka navoda, dodate ili oduzmete tekst i sl. što sve utiče na vrednost krajnje adrese za nekoliko bajta gore ili dole). Isto tako možemo za krajnju adresu uzeti bilo koju veću adresu (ako tako radimo onda je najbolje uzeti nekoliko bajta više od stvarne).
Preračunajmo niži bajt $ee u decimalnu vrednost gde dobijamo iznos 238, a onda i viši bajt $13 gde dobijamo iznos 19.
Ukoliko smo i dalje u turbo asembleru dajemo ←1 i prelazimo u bejzik. Kada smo u bejziku kucamo naredbu za restartovanje sistema SYS 64738.
Zatim treba otkucati bejzik programsku liniju 10 SYS adresa_početka_našeg_programa u decimalnom obliku, a u našem slučaju:
10 SYS 4096
Unesimo sada naredbu POKE 45,238 (niži bajt kraja našeg mašinskog programa), a onda POKE 46,19 (viši bajt kraja našeg mašinskog programa). Time smo sistemu rekli da želimo da prilikom snimanja memorije obuhvati memorijske adrese od početka bejzik programa $0801/2049 (u našem slučaju jedine bejzik programske linije) do kraja našeg mašinskog programa u našem slučaju $13ee/5102 (u stvari u memorijskim adresama 43 i 44 nalaze se niži i viši bajt početka bejzik programa ($0801/2049), dok memorijska adresa 45 i 46 sadrže niži i viši bajt kraja bezik programa čijom promenom njihove vrednosti na adresu kraja našeg mašinskog programa smo naterali sistem da misli da je sve ovo bejzik program).
Sada nam ostaje još da snimimo naš program na pravu ili virtualnu disketu sa sledećom naredbom:
SAVE „ime programa“,8,1 (npr.SAVE „FORMULA“,8,1)
Snimiće se memorija počev od adrese početka bejzik programske linije ($801) do kraja našeg mašinskog programa ($13ee), a kada sledeći put damo naredbu za učitavanje LOAD „FORMULA“,8,1 učitaće se bejzik programska linija koja služi za startovanje, kao i ceo naš mašinski program (naravno bez izvornog koda i turbo asemblera).
Kada se program učita ostaje nam da damo naredbu RUN i isti će se startovati (ako koristimo emulator sa direktnim pristupom na željeni program isti će se učitati i odmah startovati).
Na ovaj način možemo snimiti bilo koji mašinski program koji radimo sa startovanjem istog preko bejzik programske linije.
Važnost početne adrese smeštanja kompajliranog mašinskog programa
Mogli smo prilikom rada sa asemblerom umesto početne adrese $1000/4096 da damo i nižu adresu prevođenja i smeštanja (koja ne sme da se preklopi sa memorijskim zauzećem bejzik programa) npr.$0810/2064 čime bi smo uštedeli dosta memorije (oko 2 kilobajta) što je veoma važno kada radimo sa velikim mašinskim programima (inače bi ova memorija ostala neiskorišćena) i naravno time štedimo memoriju diskete na kojoj snimamo. Pošto je naš primer samo kratak program koji ćemo raditi na emulatoru ova ušteda nam nije bitna.
Takođe ako želimo da radimo mešanu verziju programa (jedan deo u bejziku a drugi u mašincu) preporuka je da se prvo uradi bejzik deo, vidi koliko memorije zauzima, a onda odradi mašinski deo koji će se prevesti/smestiti što je bliže moguće memorijskoj adresi kraja bejzik programa (naravno treba voditi računa ukoliko bude potrebno da se učine ispravke ili dodavanje dodatnih naredbi u bejzik programu da ne bi došlo do preklapanja programa). Kraj bejzik programa utvrđujemo kucanjem naredbe PRINT PEEK(45)+PEEK(46)*256
Uporedni pregled kompajliranog i izvornog koda asemblerskog programa
Da bi smo videli kako izgleda izvorni kod preveden na mašinski u turbo asembleru dajemo ←4 (prikaz prevođenja) gde će se pojaviti pitanje „print-file:“, a zatim kucamo „*“ (prikaz na ekranu) i pretisnimo return/enter. Kada ovo uradimo mašinski kod (u obliku adrese, koda naredbe i kodova parametra ukoliko ih naredba poseduje) prikazaće se sa leve strane ekrana u heksadecimalnom obliku, a izvorni kod će se prikazati sa desne strane ekrana i sve će se izlistati od početka do kraja programa. Listanje možemo usporiti pritiskom na control taster (tab kod emulatora).
Primer asemblerskog programiranja
A sada o samoj igri. Potrebno je svojom formulom prevesti 9 puta do kraja ekrana na dole (kada se formula pojavljuje na vrhu ekrana). Smetala su dva kvadrata koji se brzo kreću od leve do desne strane ekrana i ako se sudarite sa njime igri je kraj. Ukoliko odradite 9 kruga pobeđujete. Komadne za upravljanje biće „A“-levo,“D“-desno,“W“-gore,“S“-dole. Takođe postoji i primitivni zvučni efekat kao i ispis bodova na ekranu.
Učitajmo turbo asembler i startujemo ga sa SYS 36864. Imajte u vidu da se u turbo asembleru sve piše malim slovima ali u ovom primeru su data velika radi lakšeg snalaženja. Kucamo sledeći kod:
*= $1000
Počinjemo kompajliranje i smeštaj našeg mašinskog programa od adrese $1000 (4096) – početna adresa programa
ISPISI = $FFD2
Dajemo labeli „ispisi“ vrednost od $ffd2 koja memorijska adresa sadrži sistemski podprogram za izvršavanje petascii koda koji se nalazi u akumulatoru, potpuni ekvivalent bejzik naredbe PRINT CHR$(A) koja i koristi ovaj podprogram. Ovu labelu dajemo samo radi primera. Sve ostale bitne adrese ispisivaćemo direktno u programu
POCETAK
Mesto skoka na početak programa. Imajte u vidu da turbo asembler (kao i drugi asembleri) svako mesto skoka, podprograma, memorijske lokacije opisa bajtova ili teksta preračunava u memorijske adrese prilikom prevođenja koje će se kasnije zavisno od situacije koristiti u naredbama uslovnih i bezuslovnih skokova kao i u naredbama čitanja i smeštanja podataka.
LDA #147
Unosimo decimalnu vrednost 147 u akumulator. Ova vrednost je petascii kod karaktera za brisanje ekrana. Želimo da pokažemo da možemo unositi po želji decimalnu, heksadecimalnu ($) ili binarnu (%) vrednost u turbo asembleru i tako ćemo raditi nadalje u programu koristeći sve brojne sisteme.
JSR ISPISI
Odlazimo na sistemski podprogram koji se nalazi na memorijskoj adresi $ffd2 datoj u labeli „ispisi“ koji, kao što smo rekli, izvršava petascii kod koji se nalazi u akumulatoru, u našem slučaju ekvivalent bejzik naredbe PRINT CHR$(147) / briše ekran i postavlja kurzor na početak. Ovo smo uradili da bi smo vam pokazali da u svakom trenutku možemo iskoristiti mašinske podprograme koji postoje u sistemu računara (koji se koriste prilikom rada standardnog bejzik programa i samog sistema)
LDX #0
Učitavamo nulu u registar X koji će nam poslužiti kao brojač
JSR POCETEKRAN
Odlazak na podprogram koji nam ispisuje uputstvo na početnom ekranu i čeka da se pretisne neki taster da bi igra krenula
LDA #$93
Ponovo u akumulator unosimo petascii kod ovog puta kao heksadecimalni broj $93 (147) za brisanje ekrana
JSR ISPISI
Ponovo odlazimo na sistemski podprogram da bi smo izvršili petascii kod dat u akumulatoru
LDA #8
Unosimo u akumulator vrednost 8 koja će nam biti narandžasta boja okvira i pozadine
STA $D020
Smeštamo vrednost akumulatora u memorijsku lokaciju za boju okvira
STA $D021
Smeštamo vrednost akumulatora u memorijsku lokaciju za boju pozadine
LDX #0
Praznimo registar X. Uvek kada u akumulator ili registar unesemo vrednost nula kažemo da ga „praznimo“, „čistimo“ ili „brišemo“.
LDA #0
Čistimo akumulator.
STA $d010
Stavljamo vrednost iz akumulatora u registar koji sadrži deveti bit X kordinata sprajtova samim tim ga resetujući (ovo je potrebno kada odigramo prvu igru i želimo da odigramo novu da bi smo sprajtove vratili na početni položaj)
LDA #48
Unosimo vrednost 48 u akumulator. Ova vrednost je petascii/ekranski kod za karakter „0“ koji će nam biti brojač bodova.
STA BOD
Stavljamo vrednost iz akumulatora u BOD. Šta ovo znači? Na kraju programa smo dali naziv ove nazovimo programske promenljive (mesto čitanja i smeštanja). Pored naziva BOD u programu smo stavili komandu turbo asemblera .byte koja nam na toj memorijskoj adresi stvara bajt željene početne vrednosti koji možemo po potrebi čitati ili menjati. Nama će služiti za smeštaj vrednosti bodova u petascii kodu
JSR PRIPZVUK
Skačemo na podprogram za pripremu i reprodukciju zvuka
JSR POZADINA
Skačemo na podprogram za pripremu pozadine
JSR POZSKROL
Skačemo na podprogram za skrolovanje neprijateljskih kvadrata/smetala
LDA #0
Brišemo akumulator. Akumulator će nam kao i obično služiti za čitanje memorijskih lokacija kao i za smeštanje vrednosti na istima. Takođe će nam služiti za smeštaj ekranskog ili petascii koda u željenu memorijsku adresu i sve ostalo što nam je bitno kod manipulacije memorije (akumulator je najbitniji registar koji može neke stvari koje drugi registri ne mogu kao npr.smeštanje vrednosti na stek, prebacivanje vrednosti između registra, preindeksiranje i postindeksiranje šesnaestobitnih adresa, itd.)
TAX
Prenosimo vrednost nula iz akumulatora u registar X i na taj način ga čistimo. Ovaj registar će nam najviše koristiti kao brojač. Takođe će nam koristiti za proveru vrednosti na željenim memorijskim lokacijama. Ovde kao primer koristimo naredbu za premeštanje. Naravno mogli smo da koristimo i naredbu za učitavanje vrednosti LDX #0 za istu stvar. Obratite pažnju da smo ovim uštedeli jedan bajt jer naredba za učitavanje vuče dva bajta memorije dok naredba za premeštanje samo jedan
TAY
Premeštamo vrednost nula iz akumulatora u registar Y što znači da i njega brišemo. Koristiće nam kao drugi brojač i za potrebna ispitivanja vrednosti memorije
OPET
Mesto skoka koje će nam služiti prilikom formiranja prvog sprajta
LDA SPRAJT1,X
Čitamo vrednost sa memorijske lokacije „sprajt1“ u akumulator uvećanu za brojač registra X. U programu postoji sekcija „sprajt1“ koja se prilikom prevođenja automatski pretvara u memorijsku adresu gde je opis našeg prvog multikolor sprajta datog pomoću turbo asemblerske komande .byte (ukupno 63 bajta / 3×21)
STA 832,X
Stavljamo vrednost akumulatora počev od memorijske lokacije 832 (13 blok memorije za smeštaj sprajta 64×13) uvećano za vrednost registra X i na ovaj način prebacujemo opis prvog sprajta u blok memorije za čuvanje sprajta bajt po bajt (sve informacije o radu sa sprajtovima imate u lekciji 5 standardnog bejzika)
INX
Uvećavamo vrednost registra X za jedan koji uvećava adresu smeštanja i broji bajtove sprajta
CPX #63
Proveravamo da li je registar X dostigao vrednost od 63 koliko bajta je potrebno za opis sprajta
BNE OPET
Ukoliko nije idemo na mesto skoka/početak petlje za unos prvog sprajta dok se svaki bajt ne prebaci/kopira u memoriju koja služi za čuvanje i prikazivanje istog
LDX #0
Praznimo registar X i spremamo za unos opisa drugog sprajta
OPET2
Mesto skoka koje će nam služiti prilikom prenosa opisa drugog sprajta
LDA SPRAJT2,X
Čitamo vrednost sa memorijske lokacije „sprajt2“ u akumulator uvećanu za brojač registra X. U programu takođe postoji sekcija „sprajt2“ gde je opis našeg drugog multikolor sprajta datog pomoću turbo asemblerske komande .byte (ukupno 63 bajta / 3×21). Opis za drugi će nam poslužiti i za treći sprajt
STA 896,X
Stavljamo vrednost akumulatora počev od memorijske lokacije 896 (14 blok memorije za smeštaj sprajta 64×14) uvećano za vrednost registra X i na ovaj način prebacujemo opis drugog (koji će služiti i za treći sprajt) u blok memorije za čuvanje i prikaz istog
INX
Uvećavamo vrednost registra X za jedan koji uvećava adresu smeštanja i broji bajtove opisa sprajta
CPX #63
Proveravamo da li je registar X dostigao vrednost od 63 koliko bajta je potrebno za opis ovog sprajta
BNE OPET2
Ukoliko nije idemo na mesto skoka za drugi sprajt dok se svaki bajt ne prebaci u memoriju koja služi za čuvanje i prikaz ovog sprajta
LDA #$0D
Sada dolazimo do uključenja i početnog smeštaja sprajtova na ekranu. Unosimo vrednost $0d (13) u akumulator. Ova vrednost će objasniti sistemu u kom bloku je smešten opis prvog sprajta
STA $07F8
Smeštamo vrednost iz akumulatora u memorijsku adresu $07f8 (2040) koja daje sistemu informaciju u kom bloku je smešten opis prvog sprajta (blok 13)
LDA #$01
Unosimo vrednost 1 u akumulator. Ova vrednost će nam uključiti prvi sprajt. Ne moramo ovo raditi sada možemo na kraju uključiti sva tri sprajta ali dajemo za primer uključenja sprajt po sprajt
STA $D015
Smeštamo vrednost akumulatora u memorijsku adresu $d015 (53269) koja će nam uključiti visokorezolucijsku opciju za prvi sprajt (bit po sprajtu)
STA $D01C
Smeštamo vrednost akumulatora u memorijsku adresu $d01c (53276) koja će nam uključiti multikolor opciju za prvi sprajt (bit po sprajtu)
LDA #$71
Unosimo vrednost $71 (113) u akumulator
STA $D000
Smeštamo vrednost akumulatora u memorijsku adresu $d000 (53248) koja nam predstavlja X kordinatu za prvi sprajt
STA $D001
Smeštamo istu vrednost akumulatora u memorijsku adresu $d001 (53249) koja nam predstavlja Y kordinatu za prvi sprajt
LDA #$01
Unosimo vrednost 1 u akumulator
STA $D025
Stavljamo vrednost akumulatora (1-bela boja) u memorijsku adresu $d025 (53285) koja predstavlja prvu zajedničku multikolor boju kombinacije tačaka (01) svih sprajtova
LDA #$02
Unosimo vrednost 2 u akumulator
STA $D026
Stavljamo vrednost akumulatora (2-crvena boja) u memorijsku adresu $d026 (53286) koja predstavlja drugu zajedničku multikolor boju kombinacije tačaka (11) svih sprajtova
LDA #$03
Unosimo vrednost 3 u akumulator
STA $D027
Stavljamo vrednost akumulatora (3-svetlo plava boja) u memorijsku adresu $d027 (53287) koja predstavlja posebnu boju za prvi sprajt kombinacije tačaka multikolor sprajta (10-jedina boja kombinacije tačaka različita kod svakog sprajta). Ova adresa se takođe koristi za boju prvog sprajta visoke rezolucije
LDA #$0E
Unosimo vrednost $0e (14) u akumulator.
STA $07F9
Smeštamo vrednost iz akumulatora u memorijsku adresu $07f9 (2041) koja daje sistemu informaciju u kom bloku je smešten opis drugog sprajta (blok 14)
LDA #$03
Unosimo vrednost 3 u akumulator. Ova vrednost će nam uključiti prvi (koji je već uključen i ostaće uključen) i drugi sprajt.
STA $D015
Smeštamo vrednost akumulatora u memorijsku adresu $d015 (53269) koja će nam uključiti visokorezolucijsku opciju za prvi i drugi sprajt (bit po sprajtu)
STA $D01C
Smeštamo vrednost akumulatora u memorijsku adresu $d01c (53276) koja će nam uključiti multikolor opciju za prvi i drugi sprajt (bit po sprajtu)
LDA #$A0
Unosimo vrednost $a0 (160) u akumulator
STA $D002
Smeštamo vrednost akumulatora u memorijsku adresu $d002 (53250) koja nam predstavlja X kordinatu za drugi sprajt
LDA #$90
Unosimo vrednost $90 (144) u akumulator
STA $D003
Smeštamo vrednost akumulatora u memorijsku adresu $d003 (53251) koja nam predstavlja Y kordinatu za drugi sprajt
LDA #$05
Unosimo vrednost 5 u akumulator
STA $D028
Stavljamo vrednost akumulatora (5-zelena) u memorijsku adresu $d028 (53288) koja predstavlja posebnu boju za drugi sprajt kombinacije tačaka multikolor sprajta (10-jedina boja kombinacije tačaka različita kod svakog sprajta). Ova adresa se takođe koristi za boju drugog sprajta visoke rezolucije
LDA #$0E
Unosimo vrednost $0e (14) u akumulator. Ova vrednost će objasniti u kom bloku je smešten opis trećeg sprajta (biće isti opis kao i kod drugog)
STA $07FA
Smeštamo vrednost iz akumulatora u memorijsku adresu $07fa (2042) koja daje sistemu informaciju u kom bloku je smešten opis trećeg sprajta (blok 14)
LDA #$07
Unosimo vrednost 7 u akumulator. Ova vrednost će nam uključiti prvi i drugi (koji su već uključeni i ostaće uključeni) i treći sprajt.
STA $D015
Smeštamo vrednost akumulatora u memorijsku adresu $d015 (53269) koja će nam uključiti visokorezolucijsku opciju za prvi, drugi i treći sprajt (bit po sprajtu)
STA $D01C
Smeštamo vrednost akumulatora u memorijsku adresu $d01c (53276) koja će nam uključiti multikolor opciju za prvi,drugi i treći sprajt (bit po sprajtu)
LDA #$05
Unosimo vrednost 5 u akumulator
STA $D004
Smeštamo vrednost akumulatora u memorijsku adresu $d004 (53252) koja nam predstavlja X kordinatu za treći sprajt
LDA #$E0
Unosimo vrednost $e0 (224) u akumulator
STA $D005
Smeštamo vrednost akumulatora u memorijsku adresu $d005 (53253) koja nam predstavlja Y kordinatu za treći sprajt
LDA #$07
Unosimo vrednost 7 u akumulator
STA $D029
Stavljamo vrednost akumulatora (7-žuta) u memorijsku adresu $d029 (53289) koja predstavlja posebnu boju za treći sprajt kombinacije tačaka multikolor sprajta (10-jedina boja kombinacije tačaka različita kod svakog sprajta). Ova adresa se takođe koristi za boju trećeg sprajta visoke rezolucije
UPRAVLJANJE
Glavno mesto skoka od koga krećemo sa upravljanjem našeg sprajta (formule) i na koje ćemo se stalno vraćati u toku u programa
LDA $D01E
Učitavamo vrednost iz memorijske adrese registra detekcije sudara sprajtova. Ovde još ne radimo ispitivanje da li je došlo do sudara između njih. Problem je što detekcija sudara ima grešku (bag) i na ovaj način kada očitamo ovu adresu pre detekcije praznimo/resetujemo njenu vrednost (ne pomaže direktno unošenje vrednosti 0 u istoj / služi samo za čitanje). Ako ovo ne uradimo često će se po pokretanju nove igre odmah registrovati sudar sprajtova iako do istog nije došlo i igra će se odmah završiti porazom
JSR POZSKROL
Idemo na podprogram za skrolovanje neprijateljskih kvadrata
JSR USPORI
Idemo na podprogram za usporavanje brzine izvršenja mašinskog programa. Ovo je neophodno jer zbog velike brzine mašinskog izvršavanja dobili bismo samo mrlje prilikom kretanja sprajtova koje nebismo mogli da kontrolišemo (čak ni da vidimo u većini njihovih kretanja)
JSR ZVUK
Odlazimo na podprogram za emitiranje zvuka motora
JSR ISPIS
Idemo na podprogram za ispis broja bodova i za proveru da li je došlo do 9 prelaza formule preko ekrana čime bi smo uspešno završili igru
JSR SUDAR
Idemo na podprogram za detekciju sudara između sprajtova
LDX 197
Učitavamo u registar X vrednost sa memorijske lokacije 197 koja služi za očitavanje tastature.
CPX #10
Upoređujemo da li je vrednost X registra 10 koji broj predstavlja pretisnuti taster „A“
BEQ SMANJIX
Ukoliko jeste skačemo na mesto skoka za umanjenje X kordinate prvog sprajta/formule (kretanje ulevo)
CPX #18
Upoređujemo da li je vrednost X registra 18 koji broj predstavlja pretisnuti taster „D“
BEQ UVECAJX
Ukoliko jeste skačemo na mesto skoka za uvećanje X kordinate prvog sprajta (kretanje udesno)
CPX #9
Upoređujemo da li je vrednost X registra 9 koji broj predstavlja pretisnuti taster „W“
BEQ SMANJIY
Ukoliko jeste skačemo na mesto skoka za umanjenje Y kordinate prvog sprajta (kretanje na gore)
CPX #13
Upoređujemo da li je vrednost X registra 13 koji broj predstavlja pretisnuti taster „S“
BEQ UVECAJY
Ukoliko jeste skačemo na mesto skoka za uvećanje Y kordinate prvog sprajta (kretanje na dole)
JSR POZSKROL
Idemo ponovo na podprogram za skrolovanje neprijateljskih kvadrata (iz razloga ubrzavanja skrolovanja neprijateljskih kvadrata u odnosu na brzinu kretanje formule)
JMP UPRAVLJANJE
Skačemo natrag na mesto skoka početka upravljanja čime pravimo beskonačnu petlju dok se neki od uslova pobede ili poraza ne ispune
SMANJIX
Mesto skoka za smanjenje X kordinate prvog sprajta
DEC $D000
Umanjujemo za jedan X kordinatu prvog sprajta
LDA $D010
Učitavamo u registar X vrednost iz registra $d010 u kome se nalazi deveti bit X kordinate sprajta
AND #%0000001
Radimo logičku operaciju nad stanjem vrednosti u akumulatoru u kojoj ćemo potvrditi da li je setovan nulti bit (9 bit prvog sprajta). Kada damo naredbu AND (logičko množenje I) gde su svi bitovi osim nultog nula vrednost akumualtora će biti jedan samo ako je nulti bit već setovan
CMP #1
Proveravamo vrednost u akumulatoru. Ukoliko je 1 deveti bit je setovan važi opseg X kordinate prvog sprajta od 256 do 511 (vidljivo je do 343)
BEQ PROVERIX
Ukoliko je akumulator jednak 1 to znači da je 9 bit setovan tako da idemo na mesto skoka koje proverava kordinatu X i ukoliko je ona nula isključuje 9 bit sprajta
LDX $D000
Učitavamo u registar X vrednost iz registra $d000 kordinate X prvog sprajta
CPX #14
Proveravamo da li je vrednost u registru X jednaka 14.
BEQ STANIX
Ukoliko je vrednost X jednaka 14 idemo na mesto skoka koje će blokirati dalje kretanje formule prema levoj strani ekrana
JMP UPRAVLJANJE
Vraćamo se na glavno mesto skoka
PROVERIX
Mesto skoka za proveru da li je kordinata horizontale X jednaka 0
LDX $D000
Učitavamo u registar X vrednost memorijske lokacije $d000/53248 koja sadrži X kordinatu prvog sprajta
CPX #0
Ispitujemo da li je vrednost u registru 0 što znači da se vraćamo u zonu kontrole X kordinate prvog sprajta (0-255) pa iz tog razloga treba da isključimo 9-bit ovog sprajta (+256)
BEQ RESETUJX
Ukoliko jeste odlazimo na mesto skoka gde ćemo resetovati 9-bit prvog sprajta
JMP UPRAVLJANJE
Vraćamo se na glavno mesto skoka
RESETUJX
Mesto skoka gde će se resetovati deveti bit X kordinate prvog sprajta
LDA $D010
Učitavamo u akumulator stanje memorijske lokacije $d010 gde se nalaze 9-bit za sve sprajtove (bit po sprajtu 0-7)
AND #%11111110
Radimo logičku operaciju nad stanjem vrednosti u akumulatoru u kojoj ćemo resetovati nulti bit (9 bit prvog sprajta). Kada damo naredbu AND (logičko množenje I) gde su svi bitovi osim prvog jedinice neće biti promene stanja kod ostalih sprajtova (0*1=0 i 1*1=1) dok će se bit prvog sprajta resetovati (1*0=0)
STA $D010
Smeštamo vrednost akumulatora u memorijsku lokaciju $d010 (9-bit svih sprajtova/bit po sprajtu 0-7) i time brišemo/resetujemo 9-bit prvog sprajta
LDA #255
Unosimo vrednost 255/$ff u akumulator pošto smo poništili 9-bit prvog sprajta koji teži 256/$100 i na taj način imamo glatki prelaz pomeranje sprajta ulevo iz zone gde je bio setovan 9-bit (256+255) u normalnu zonu koju kontroliše X kordinata prvog sprajta (0-255)
STA $D000
Smeštamo vrednost akumulatora u memorijsku lokaciju X kordinate prvog sprajta
JMP UPRAVLJANJE
Vraćamo se na glavno mesto skoka
STANIX
Mesto skoka koje će blokirati dalje kretanje formule u levo
LDA #15
Unosimo u akumulator vrednost 15
STA $D000
Smeštamo vrednost iz akumulatora u memorijsku lokaciju X kordinate prvog sprajta i na taj način ne dozovoljavamo dalje pomeranje prvog sprajta (formule) ulevo inače bi se isti izgubio na levoj strani ekrana
JMP UPRAVLJANJE
Vraćamo se na glavno mesto skoka
UVECAJX
Mesto skoka uvećanja X kordinate prvog sprajta
INC $D000
Uvećavamo vrednost memorijske lokacije kordinate X prvog sprajta za jedan
BEQ SETUJX
Ukoliko smo putem uvećanja X kordinate prvog sprajta stigli do nule (0-255-0 ciklični tok uvećanja vrednost bajta) odlazimo na mesto skoka gde setujemo 9-bit prvog sprajta tako da isti može nastaviti putanju od 256 tačke.
LDA $D010
Učitavamo u akumulator vrednost memorijske lokacije stanja 9-bita svih sprajtova
AND #%00000001
Radimo logičku operaciju nad stanjem vrednosti u akumulatoru u kojoj ćemo potvrditi da li je setovan nulti bit (9 bit prvog sprajta). Kada damo naredbu AND (logičko množenje I) gde su svi bitovi osim nultog nula vrednost akumualtora će biti jedan samo ako je nulti bit već setovan
CMP #1
Proveravamo da li akumulator sadži vrednost 1 što znači da je 9-bit prvog sprajta setovan
BEQ PROVERI
Ukoliko je vrednost akumulatora jednaka jedinici skačemo na mesto skoka za proveru da li je sprajt blizu izlaska iz vidljivog okvira sa desne strane ekrana
JMP UPRAVLJANJE
Vraćamo se na glavno mesto skoka
SETUJX
Mesto skoka gde setujemo 9-bit X kordinate prvog sprajta
LDA $D010
Učitavamo u akumulator vrednost memorijske lokacije stanja 9-bita svih sprajtova
ORA #%00000001
Radimo logičku operaciju nad stanjem vrednosti u akumulatoru u kojoj ćemo setovati nulti bit (9 bit prvog sprajta). Kada damo naredbu ORA (logičko sabitanje ILI) gde je samo nulti bit jedinica a ostali nula neće biti promene kod ostalih sprajtova (0+0=0, 0+1=1) dok će bit nultog sprajta biti setovan (1+0=1)
STA $D010
Smeštamo vrednost akumulatora u memorijsku lokaciju $d010 (9-bit svih sprajtova/bit po sprajtu 0-7) i time setujemo 9-bit prvog sprajta
JMP UPRAVLJANJE
Vraćamo se na glavno mesto skoka
PROVERI
Mesto skoka provere da li je X kordinata prvog sprajta zajedno sa 9-bitom dostigla desnu ivicu ekrana
LDX $D000
Učitavamo u registar X vrednost memorijske lokacije X kordinate prvog sprajta (nemojte mešati registar X sa X kordinatom sprajta)
CPX #71
Proveravamo da li je u registar X vrednost 71 što znači da zajedno sa 9-bitom dostižemo vidljivu ivicu sprajta na desnoj strani ekrana
BEQ STANIX2
Ukoliko je vrednost u registru X jednaka 71 skačemo na mesto skoka gde će se zaustaviti dalje kretanje sprajta formule udesno
JMP UPRAVLJANJE
Vraćamo se na glavno mesto skoka
STANIX2
Mesto skoka koje zaustavlja dalje kretanja sprajta formule udesno
LDA #70
Unosima u akumulator vrednost 70
STA $D000
Stavljamo vrednost iz akumulatora u memorijsku lokaciju X kordinate prvog sprajta i na taj način sprečavamo njegovo kretanje nadalje udesno i samim tim njegovog nestanka sa desne strane ekrana
JMP UPRAVLJANJE
Vraćamo se na glavno mesto skoka
SMANJIY
Mesto skoka za smanjivanje vrednosti Y kordinate prvog sprajta
DEC $D001
Umanjujemo za jedan vrednost u memorijskoj lokaciji Y kordinate prvog sprajta
JMP UPRAVLJANJE
Vraćamo se na glavno mesto skoka
UVECAJY
Mesto skoka za uvečanje vrednosti Y kordinate prvog sprajta
INC $D001
Uvećavamo za jedan vrednost u memorijskoj lokaciji Y kordinate prvog sprajta (ukoliko pređe vrednost 255 vratiće sa na početak ekrana iz razloga cikličnog uvećanja vrednosti 0-255-0)
LDA $D001
Unosimo u akumualtor vrednost memorijske lokacije Y kordinate prvod sprajta
CMP #$FF
Ispitujemo da li je vrednost u akumulator $ff/255 što znači da je prvi sprajt izašao iz vidljivog polja ekrana na dole
BEQ UVECAJBOD
Ukoliko je vrednost u akumulatoru $ff/255 uvećavamo vrednost boda za 1
JMP UPRAVLJANJE
Vraćamo se na glavno mesto skoka
UVECAJBOD
Mesto skoka za uvećanje broja bodova (koliko je puta sprajt formule izašao iz ekrana na dole)
INC BOD
Uvećavamo memorijslku lokaciju koja sadrži jedan bajt počev od petascii koda za 0 (48) za jedan
JMP UPRAVLJANJE
Vraćamo se na glavno mesto skoka
USPORI
Mesto skoka za usporenje izvršenja mašinskog programa. Ovaj deo programa je veoma bitan jer inače je kretanje sprajtova izuzetno brzo da je neupotrebljivo za igru. Ako želite da vidite koliko brzo stavite ovde naredbu RTS koja će odmah vratiti tok programa u glavni program bez usporenja
NOP
Naredba koja nema funkciju osim da povećava tok programa za jedan. Ovde je koristimo jer dobijamo delić usporenja
NOP
Još jedna naredbe bez funkcije osim veoma malog usporenja mašinskog programa. Bez obzira na ovo pošto su ove dve NOP naredbe date u ciklusu imaju neki uticaj na smanjenje brzine izvršavanja programa
INY
Ovde imamo uvećanje registra Y (u ovom slučaju programskog brojača) za jedan
BNE USPORI
Skok na početak mesta skoka usporavanja sve dok registar Y ne odbroji 255 ciklusa što pravi ono pravo usporavanje programa
RTS
Povratak na glavni program
SPRAJT1
Opis izgleda prvog sprajta
.BYTE 0,0,0
.BYTE 0,0,0
.BYTE 63,0,252
.BYTE 63,170,252
.BYTE 63,170,252
.BYTE 63,150,252
.BYTE 63,150,252
.BYTE 63,150,252
.BYTE 63,150,252
.BYTE 0,150,0
.BYTE 0,150,0
.BYTE 0,150,0
.BYTE 0,150,0
.BYTE 63,150,252
.BYTE 63,190,252
.BYTE 63,190,252
.BYTE 63,190,252
.BYTE 63,170,252
.BYTE 63,40,252
.BYTE 63,0,252
.BYTE 0,0,0
Ovde imamo 63 bajta koji čine opis/definiciju izgleda prvog sprajta (formule) koju vodi igrač
SPRAJT2
Opis izgleda drugog sprajta (koji opis će poslužiti i za treći sprajt)
.BYTE 255,255,255
.BYTE 255,255,255
.BYTE 250,170,175
.BYTE 250,106,175
.BYTE 250,85,175
.BYTE 250,85,175
.BYTE 250,85,175
.BYTE 250,85,175
.BYTE 250,65,175
.BYTE 250,65,175
.BYTE 250,65,175
.BYTE 250,65,175
.BYTE 250,65,175
.BYTE 250,85,175
.BYTE 250,85,175
.BYTE 250,85,175
.BYTE 250,85,175
.BYTE 250,170,175
.BYTE 250,170,175
.BYTE 255,255,255
.BYTE 255,255,255
Imamo ponovo 63 bajta koji čine opis/definiciju izgleda drugog sprajta (šarenog kvadrata/smetala) koji opis će poslužiti i za treći sprajt
POZSKROL
Podprogram za povećanje horizontalne X kordinate drugog sprajta kvadrata/smetala
JSR POZSKROL2
Poziv podprograma za kretanje trećeg sprajta kvadrata/smetala
INC $D002
Uvećavamo memorijsku lokaciju X kordinate drugog sprajta/kvadrata za jedan
BEQ UVECAJ41
Ukoliko je vrednost ove memorijske lokacije 0 (ciklično uvećanje 0-255-0) skačemo na setovanje 9 bita drugog sprajta
LDA $D010
Učitavamo u akumulator vrednost memorijske lokacije stanja 9-bita svih sprajtova
AND #%00000010
Radimo logičku operaciju nad stanjem vrednosti u akumulatoru u kojoj ćemo potvrditi da li je setovan prvi bit (9 bit drugog sprajta). Kada damo naredbu AND (logičko množenje I) gde su svi bitovi osim prvog nula vrednost akumulatora će biti dva samo ako je prvi bit već setovan
CMP #2
Proveravamo da li akumulator sadži vrednost 2 što znači da je 9-bit drugog sprajta setovan
BEQ PROVERI41
Ukoliko je vrednost akumulatora jednaka dvojci skačemo na mesto skoka za proveru da li je drugi sprajt blizu izlaska iz vidljivog okvira sa desne strane ekrana
RTS
Povratak iz podprograma
UVECAJ41
Podprogram za setovanje 9-bita drugog sprajta
LDA $D010
Učitavamo u akumulator vrednost memorijske lokacije stanja 9-bita svih sprajtova
ORA #%00000010
Radimo logičku operaciju nad stanjem vrednosti u akumulatoru u kojoj ćemo setovati prvi bit (9 bit drugog sprajta). Kada damo naredbu ORA (logičko sabitanje ILI) gde je samo prvi bit jedinica a ostali nula neće biti promene kod ostalih sprajtova (0+0=0, 0+1=1) dok će bit drugog sprajta biti setovan (1+0=1)
STA $D010
Smeštamo vrednost akumulatora u memorijsku lokaciju $d010 (9-bit svih sprajtova/bit po sprajtu 0-7) i time setujemo 9-bit drugog sprajta
RTS
Povratak iz podprograma
PROVERI41
Podprogram provere da li je X kordinata drugog sprajta zajedno sa 9-bitom dostigla desnu ivicu ekrana
LDA $D002
Učitavamo u akumulator vrednost memorijske lokacije X kordinate drugog sprajta
CMP #70
Proveravamo da li je u akumulator vrednost 70 što znači da zajedno sa 9-bitom dostižemo vidljivu ivicu drugog sprajta na desnoj strani ekrana
BEQ VRATI41
Ukoliko je vrednost u akumulatoru jednaka 70 skačemo na mesto skoka gde će se drugi sprajt vratiti na početak ekrana poništavanjem 9-bita i stavljanjem nule u njegovu X kordinatu
RTS
Povratak iz podprograma
VRATI41
Podprogram gde će se resetovati 9-bit drugog sprajta i resetovati njegova X kordinata
LDA $D010
Učitavamo u akumulator vrednost memorijske lokacije stanja 9-bita svih sprajtova
AND #%11111101
Radimo logičku operaciju nad stanjem vrednosti u akumulatoru u kojoj ćemo resetovati prvi bit (9-bit drugog sprajta) ne dirajući stanja drugih sprajtova
STA $D010
Smeštamo vrednost akumulatora u memorijsku lokaciju $d010 (9-bit svih sprajtova/bit po sprajtu 0-7) i samim tim resetujemo 9-bit drugog sprajta
LDA #0
Brišemo vrednost akumulatora
STA $D002
Smeštamo stanje akumulatora u memorijsku lokaciju X kordinate drugog sprajta i samim tim isti vraćamo na početak ekrana
RTS
Povratak iz podprograma
POZSKROL2
Podprogram za povećanje horizontalne X kordinate trećeg sprajta kvadrata/smetala
INC $D004
Uvećavamo memorijsku lokaciju X kordinate trećeg sprajta/kvadrata za jedan
BEQ UVECAJ51
Ukoliko je vrednost ove memorijske lokacije 0 (ciklično uvećanje 0-255-0) skačemo na setovanje 9 bita trećeg sprajta
LDA $D010
Učitavamo u akumulator vrednost memorijske lokacije stanja 9-bita svih sprajtova
AND #%00000100
Radimo logičku operaciju nad stanjem vrednosti u akumulatoru u kojoj ćemo potvrditi da li je setovan drugi bit (9 bit trećeg sprajta). Kada damo naredbu AND (logičko množenje I) gde su svi bitovi osim drugog nula vrednost akumulatora će biti 4 samo ako je drugi bit već setovan
CMP #4
Proveravamo da li akumulator sadži vrednost 4 što znači da je 9-bit trećeg sprajta setovan
BEQ PROVERI51
Ukoliko je vrednost akumulatora jednaka 4 skačemo na mesto skoka za proveru da li je treći sprajt blizu izlaska iz vidljivog okvira sa desne strane ekrana
RTS
Povratak iz podprograma
UVECAJ51
Podprogram za setovanje 9-bita trećeg sprajta
LDA $D010
Učitavamo u akumulator vrednost memorijske lokacije stanja 9-bita svih sprajtova
ORA #%00000100
Radimo logičku operaciju nad stanjem vrednosti u akumulatoru u kojoj ćemo setovati drugi bit (9 bit trećeg sprajta). Kada damo naredbu ORA (logičko sabitanje ILI) gde je samo drugi bit jedinica a ostali nula neće biti promene kod ostalih sprajtova (0+0=0, 0+1=1) dok će bit trećeg sprajta biti setovan (1+0=1)
STA $D010
Smeštamo vrednost akumulatora u memorijsku lokaciju $d010 (9-bit svih sprajtova/bit po sprajtu 0-7) i time setujemo 9-bit trećeg sprajta
RTS
Povratak iz podprograma
PROVERI51
Podprogram provere da li je X kordinata trećeg sprajta zajedno sa 9-bitom dostigla desnu ivicu ekrana
LDA $D004
Učitavamo u akumulator vrednost memorijske lokacije X kordinate trećeg sprajta
CMP #70
Proveravamo da li je u akumulator vrednost 70 što znači da zajedno sa 9-bitom dostižemo vidljivu ivicu trećeg sprajta na desnoj strani ekrana
BEQ VRATI51
Ukoliko je vrednost u akumulatoru jednaka 70 skačemo na podprogram gde će se treći sprajt vratiti na početak ekrana poništavanjem 9-bita i stavljanjem nule u njegovu X kordinatu
RTS
Povratak iz podprograma
VRATI51
Podprogram gde će se resetovati 9-bit trećeg sprajta i resetovati njegova X kordinata
LDA $D010
Učitavamo u akumulator vrednost memorijske lokacije stanja 9-bita svih sprajtova
AND #%11111011
Radimo logičku operaciju nad stanjem vrednosti u akumulatoru u kojoj ćemo resetovati drugi bit (9-bit trećeg sprajta) ne dirajući stanja drugih sprajtova
STA $D010
Smeštamo vrednost akumulatora u memorijsku lokaciju $d010 (9-bit svih sprajtova/bit po sprajtu 0-7) i samim tim resetujemo 9-bit trećeg sprajta
LDA #0
Brišemo vrednost akumulatora
STA $D004
Smeštamo stanje akumulatora u memorijsku lokaciju X kordinate trećeg sprajta i samim tim isti vraćamo na početak ekrana
RTS
Povratak iz podprograma
ISPIS
Podprogram gde će se ispisati tekst i stanje bodova i takođe proveriti da li je formula prošla 9 puta donju ivicu ekrana u kom slučaju će se proglasiti pobeda
LDA #“B“-64
Dajemo slovo „b“ pod navodnicima koje turbo asembler preračunava u vrednost petascii koda (66) koju umanjujemo za 64 da bi se dobila ekranska vrednost ovog slova (2) koju unosimo u akumulator. Isto tako smo mogli odmah dati broj dva ali da ne bismo pamtili ili pretraživali za svaki ekranski kod slova koje želimo da koristimo ovo je najbolji način
STA $0410
Smeštamo vrednost akumulatora direktno u ekransku memoriju. Iz ovog razloga smo morali u akumulatoru pretvoriti vrednost petascii koda u ekransku kodnu vrednost karaktera
LDA #“O“-64
Dajemo slovo „o“ pod navodnicima koje turbo asembler preračunava u vrednost petascii koda koji umanjujemo za 64 da bi se dobila ekranska vrednost slova koju unosimo u akumulator
STA $0411
Smeštamo vrednost akumulatora direktno u ekransku memoriju uvećanu za jedan u odnosu na prethodni ispis
LDA #“D“-64
Dajemo slovo „d“ pod navodnicima koje turbo asembler preračunava u vrednost petascii koda koji umanjujemo za 64 da bi se dobila ekranska vrednost slova koju unosimo u akumulator
STA $0412
Smeštamo vrednost akumulatora direktno u ekransku memoriju uvećanu za jedan u odnosu na prethodni ispis
LDA BOD
Učitavamo vrednost iz memorijske adrese BOD koja se nalazi na kraju programa i sadrži jedan bajt dat turbo asemblerskom naredbom .byte (početna vrednost je 48 što odgovara karakteru 0 bilo u petascii ili u ekranskom kodu pa ne treba umanjiti njegovu vrednosti)
STA $0414
Smeštamo vrednost akumulatora direktno u ekransku memoriju uvećanu za dva u odnosu na prethodni ispis i time pravimo razmak između teksta i ispisa vrednosti boda
CMP #57
Proveravamo da li BOD sadrži vrednost 57 što znači da smo imali 9 prelaza
BEQ KRAJPOBEDA
Ukoliko je vrednost BOD-a došla do ekranskog/petascii koda 57 (broja 9) znači da smo uspeli i idemo na deo programa gde se ispisuje da smo pobedili
RTS
Povratak iz podprograma
KRAJPOBEDA
Podprogram koji proglašava pobedu
LDA #147
Unosimo u akumulator vrednost 147 (petascii kod za brisanje ekrana)
JSR ISPISI
Pozivamo podprogram za izvršavanje petascii koda datog u akumulatoru
LDA #“P“-64
Dajemo slovo „p“ pod navodnicima koje turbo asembler preračunava u vrednost petascii koda koji umanjujemo za 64 da bi se dobila ekranska vrednost slova koju unosimo u akumulator
STA $0400
Smeštamo ekranski kod karaktera iz akumulatora u ekransku memoriju (prvi red,prva kolona)
LDA #“O“-64
Dajemo slovo „o“ pod navodnicima koje turbo asembler preračunava u vrednost petascii koda koji umanjujemo za 64 da bi se dobila ekranska vrednost slova koju unosimo u akumulator
STA $0401
Smeštamo ekranski kod karaktera iz akumulatora u ekransku memoriju (prvi red,druga kolona)
LDA #“B“-64
Dajemo slovo „b“ pod navodnicima koje turbo asembler preračunava u vrednost petascii koda koji umanjujemo za 64 da bi se dobila ekranska vrednost slova koju unosimo u akumulator
STA $0402
Smeštamo ekranski kod karaktera iz akumulatora u ekransku memoriju (prvi red,treća kolona)
LDA #“E“-64
Dajemo slovo „e“ pod navodnicima koje turbo asembler takođe preračunava u vrednost petascii koda koji umanjujemo za 64 da bi se dobila ekranska vrednost slova koju unosimo u akumulator
STA $0403
Smeštamo ekranski kod karaktera iz akumulatora u ekransku memoriju (prvi red,četvrta kolona)
LDA #“D“-64
Dajemo slovo „d“ pod navodnicima koje turbo asembler preračunava u vrednost petascii koda koji umanjujemo za 64 da bi se dobila ekranska vrednost slova koju unosimo u akumulator
STA $0404
Smeštamo ekranski kod karaktera iz akumulatora u ekransku memoriju (prvi red,peta kolona)
LDA #“A“-64
Dajemo slovo „a“ pod navodnicima koje turbo asembler preračunava u vrednost petascii koda koji umanjujemo za 64 da bi se dobila ekranska vrednost slova koju unosimo u akumulator
STA $0405
Smeštamo ekranski kod karaktera iz akumulatora u ekransku memoriju (prvi red,šesta kolona)
LDA #0
Brišemo vrednost akumulatora
STA $D015
Unosimo vrednost akumulatora u memorijsku adresu čime isključujemo sve viskorezolucijske sprajtove (takođe i multikolor sprajtove)
STA $D01C
Unosimo vrednost akumulatora u memorijsku adresu multikolor sprajtova (kada smo isključili visokorezolucijske sprajtove isključili smo sve ali da ipak ispraznimo i ovu memorijsku lokaciju)
JMP PONOVNAIGRA
Skaćemo na mesto skoka gde imamo pitanje da li želimo novu igru
POZADINA
Mesto skoka gde pravimo pozadinu (u stvari to su samo nekoliko „et“ karaktera ali isto tako možemo iscrtati celu pozadinu koju želimo koristeći karaktere i simbole)
LDX #0
Brišemo vrednost registra X
OPETPOZ
Podprogram za pravljenje petlje kod iscrtavanja karaktera pozadine
LDA #0
Praznimo akumulator A (0 kodna vrednost „et“ karaktera)
STA $0400,X
Smeštamo vrednost akumulatora od početka ekranske memorije uvećanu za registar X
INX
Uvećavamo vrednost registar X za jedan
CPX #10
Upoređujemo da li je registar X dostigao vrednost 10
BNE OPETPOZ
Ukoliko nije skačemo na mesto skoka koji pravi petlju dok se ne ispišu svih 10 „et“ karaktera
LDX #0
Praznimo registar X
OPETPOZ2
Mesto skoka za pravljenje druge petlje kod iscrtavanja karaktera pozadine
STA $041E,X
Smeštamo vrednost akumulatora od 30 kolone prvog reda ekranske memorije uvećanu za registar X
INX
Uvećavamo vrednost registar X za jedan
CPX #10
Upoređujemo da li je registar X dostigao vrednost 10
BNE OPETPOZ2
Ukoliko nije skačemo na mesto skoka koji pravi drugu petlju dok se ne ispišu svih 10 „et“ karaktera
RTS
Povratak iz podprograma
SUDAR
Podprogram za detekciju sudara sprajtova
LDA $D01E
Učitavamo vrednost u akumulator iz memorijske adrese registra detekcije sudara sprajtova. Ukoliko dođe do sudara setovaće se bitovi koji prpadaju sprajtovima koji su se sudarili (1 i 2 sprajt/bit 0 i 1/vrednost bitova 1 i 2 u akumulator će se upisati vrednost 3, 1 i 3 sprajtt/bit 0 i 2/vrednost bitova 1 i 4 u akumulator će se upisati vrednost 5).
BNE KRAJSVE
Ukoliko vrednost u akumulatoru nije nula to znači da je došlo do sudara između sprajta (nije nam bitno koji sudar je u pitanju jer mogu biti samo sudari prvog sprajta formule sa drugim ili trećim sprajtovima/smetalima a i u jednom i drugom slučaju igri je kraj) tako da odlazimo na mesto skoka gde se proglašava poraz.
RTS
Povratak iz podprograma
KRAJSVE
Mesto skoka gde proglašavamo poraz
LDA #147
Unosimo u akumulator vrednost 147 (petascii kod za brisanje ekrana)
JSR ISPISI
Pozivamo podprogram za izvršavanje petascii koda datog u akumulatoru
LDA #“P“-64
Dajemo slovo „p“ pod navodnicima koje turbo asembler takođe preračunava u vrednost petascii koda koji umanjujemo za 64 da bi se dobila ekranska vrednost slova koju unosimo u akumulator
STA $0400
Smeštamo ekranski kod karaktera iz akumulatora u ekransku memoriju (prvi red,prva kolona)
LDA #“O“-64
Dajemo slovo „o“ pod navodnicima koje turbo asembler takođe preračunava u vrednost petascii koda koji umanjujemo za 64 da bi se dobila ekranska vrednost slova koju unosimo u akumulator
STA $0401
Smeštamo ekranski kod karaktera iz akumulatora u ekransku memoriju (prvi red,druga kolona)
LDA #“R“-64
Dajemo slovo „r“ pod navodnicima koje turbo asembler takođe preračunava u vrednost petascii koda koji umanjujemo za 64 da bi se dobila ekranska vrednost slova koju unosimo u akumulator
STA $0402
Smeštamo ekranski kod karaktera iz akumulatora u ekransku memoriju (prvi red,treća kolona)
LDA #“A“-64
Dajemo slovo „a“ pod navodnicima koje turbo asembler takođe preračunava u vrednost petascii koda koji umanjujemo za 64 da bi se dobila ekranska vrednost slova koju unosimo u akumulator
STA $0403
Smeštamo ekranski kod karaktera iz akumulatora u ekransku memoriju (prvi red,četvrta kolona)
LDA #“Z“-64
Dajemo slovo „z“ pod navodnicima koje turbo asembler takođe preračunava u vrednost petascii koda koji umanjujemo za 64 da bi se dobila ekranska vrednost slova koju unosimo u akumulator
STA $0404
Smeštamo ekranski kod karaktera iz akumulatora u ekransku memoriju (prvi red,peta kolona)
LDA #0
Praznimo akumulator A
STA $D015
Smeštamo vrednost akumulatora u memorijsku adresu $d015 (53269) čime ćemo isključiti sve višerezolucijske sprajtove (samim tim isključiti sve sprajtove)
STA $D01C
Smeštamo vrednost akumulatora u memorijsku adresu $d01c (53276) čime ćemo isključiti sve multikolor sprajtove (već su isključeni u prethodnoj naredbi ali da ipak ispraznimo i ovaj registar)
PONOVNAIGRA
Mesto skoka gde se postavlja pitanje da li želimo još jednu igru
LDA #“O“-64
Dajemo slovo „o“ pod navodnicima koje turbo asembler preračunava u vrednost petascii koda koji umanjujemo za 64 da bi se dobila ekranska vrednost slova koju unosimo u akumulator
STA $0500
Smeštamo ekranski kod karaktera iz akumulatora u ekransku memoriju (7 red, 17 kolona)
LDA #“P“-64
Dajemo slovo „p“ pod navodnicima koje turbo asembler preračunava u vrednost petascii koda koji umanjujemo za 64 da bi se dobila ekranska vrednost slova koju unosimo u akumulator
STA $0501
Smeštamo ekranski kod karaktera iz akumulatora u ekransku memoriju (7 red, 18 kolona)
LDA #“E“-64
Dajemo slovo „e“ pod navodnicima koje turbo asembler preračunava u vrednost petascii koda koji umanjujemo za 64 da bi se dobila ekranska vrednost slova koju unosimo u akumulator
STA $0502
Smeštamo ekranski kod karaktera iz akumulatora u ekransku memoriju (7 red, 19 kolona)
LDA #“T“-64
Dajemo slovo „t“ pod navodnicima koje turbo asembler preračunava u vrednost petascii koda koji umanjujemo za 64 da bi se dobila ekranska vrednost slova koju unosimo u akumulator
STA $0503
Smeštamo ekranski kod karaktera iz akumulatora u ekransku memoriju (7 red, 20 kolona)
LDA #“D“-64
Dajemo slovo „d“ pod navodnicima koje turbo asembler preračunava u vrednost petascii koda koji umanjujemo za 64 da bi se dobila ekranska vrednost slova koju unosimo u akumulator
STA $0505
Smeštamo ekranski kod karaktera iz akumulatora u ekransku memoriju (7 red, 22 kolona)
LDA #“/“
Dajemo karakter „/“ pod navodnicima koje turbo asembler preračunava u vrednost petascii koda koji je identičan sa ekranskom vrednošću ovog karaktera pa samim tim ne umanjujemo njenu vrednost koju unosimo u akumulator
STA $0506
Smeštamo ekranski kod karaktera iz akumulatora u ekransku memoriju (7 red, 23 kolona)
LDA #“N“-64
Dajemo slovo „n“ pod navodnicima koje turbo asembler preračunava u vrednost petascii koda koji umanjujemo za 64 da bi se dobila ekranska vrednost slova koju unosimo u akumulator
STA $0507
Smeštamo ekranski kod karaktera iz akumulatora u ekransku memoriju (7 red, 24 kolona)
OPETIGRA
Mesto skoka za utvrđivanje želimo li novu igru ili ne
LDA 197
Unosimo u akumulator vrednost sa memorijske lokacije za čitanje tastature
CMP #18
Ukoliko je u akumulatoru vrednost 18 to znači da je pretisnut taster „D“
BEQ OPETSVE
U slučaju da je akumulator jednak vrednosti 18 idemo na mesto skoka koji će nas poslati na početak programa i startovati novu igru
CMP #39
Ukoliko je u akumulatoru vrednost 39 znači da je pretisnut taster „N“
BEQ STANIPROGRAM
U slučaju da je akumulator jednak vrednosti 39 idemo na mesto skoka koji će završiti naš program
JMP OPETIGRA
Vraćamo se na mesto skoka za određivanje pretisnutog tastera
OPETSVE
Mesto skoka za aktiviranje nove igre
PLA
PLA
Povlačimo dva puta vrednost bajta sa steka u akumulator. Ovo smo uradili da bi smo poništili adresu skoka koja se premestila na stek davanjem naredbe JSR i samim tim deaktivirali naredbu RTS
JMP POCETAK
Idemo na mesto skoka početka programa i samim tim krećemo sa novom igrom
STANIPROGRAM
Mesto skoka za završetak programa
LDA #0
Unosimo vrednost nula u akumulator
STA 54296
Sneštano vrednost iz akumulatora u memorijsku lokaciju koja sadrži jačinu tona za sva tri kanala i na ovaj način isključujemo zvuk
PLA
PLA
Povlačimo dva puta vrednost bajta sa steka u akumulator (niži i viši bajt sačuvane lokacije pre skoka u podprogram). Na ovaj način poništavamo adresu povratka aktivirane davanjem naredbe JSR. Iz ovog razloga sledeća naredba RTS neće vratiti programski tok na glavni program već će uzrokovati izlaz iz mašinskog programa (naše igre) i vratiti nas u bejzik
RTS
Izlazak iz programa i povratak u bejzik
POCETEKRAN
Podprogram/mesto skoka za ispis teksta početnog ekrama
Umesto da izbrišemo ekran sa unosom u akumulator vrednost 147 i odlazak na podprogram u $ffd2 za izvršenje petascii koda, daćemo brisanje ekrana putem donjeg mašinskog koda (ovo radimo samo zbog primera)
LDA #0
Unosimo vrednost 0 u akumulator
STA 2
Smeštamo vrednost akumulatora u memorijsku adresu 2 koja će nam biti niži bajt početka ekranske memorije
LDA #4
Unosimo vrednost 4 u akumulator
STA 3
Smeštamo vrednost akumulatora u memorijsku adresu 3 koja će nam biti viši bajt početka ekranske memorije (niži i viši bajt ukupno $0400)
LDY #0
Praznimo registar Y koji će nam biti brojač
LDA #“ “
Unosimo pod navodnicima razmak koji će se kao vrednost ekranskog koda uneti u akumulator A
OPETCEO
Mesto skoka za brisanje ekrana
STA (2),Y
Unosimo u niži bajt vrednost akumulatora (ekranski kod za razmaknicu). Pošto koristimo postindeksirano indeksiranje uzeće se za niži bajt vrednost memorijske adrese 2 i za viši bajt vrednost memorijskoj adrese 3 i karakter će se uneti počev od memorijske adrese ($0400) uvećane za vrednost registra Y
INY
Uvećavamo vrednost registra Y za jedan
BNE OPETCEO
Idemo na početak petlje za brisanje ekrana dok registar Y ne dostigne vrednost nula (0-255-0 ciklični tok uvećanja/umanjenja vrednost bajta) i na ovaj način ćemo isprazniti prvi blok ekranske memorije od 255 karaktera a kasnije i ostale
INC 3
Uvećavamo za jedan vrednost u memorijskoj lokaciji 3 (viši bajt ekranske memorije)
LDX 3
Unosimo vrednost sa memorijske adrese 3 u registar X
CPX #8
Upoređujemo da li je registar X dostigao vrednost 8
BNE OPETCEO
Ukoliko nije vraćamo se na početak petlje za brisanje ekrana i brišemo sledeće blokove ekranske memorije veličina 255 bajta. Ukoiko jeste došli smo do adrese $0800 čime smo ispunili celi ekran razmaknicama, tj.obrisali ga
Sa ovim smo izvršili brisanje početnog ekrana. Kao što vidite mnogo je jednostavnije iskoristiti već postojeći podprogram na adresi $ffd2
LDX #0
Brišemo registar X
POCTEKISP
Mesto skoka za petlju ispisa teksta
LDA TEXTPOCET,X
Unos vrednosti u akumulator iz memorijske lokacije u kojoj smo smestili tekst početnog ekrana uvećanog sa vrednost registra X. Na ovaj način možemo prikazati 256 karaktera nekog teksta (X je osmobitni registar 0-255)
CMP #0
Provera da li se u akumulator nalazi vrednost 0
BEQ POCETOPET
Ukoliko jeste izlazimo iz ispisa teksta i idemo na mesto skoka koje proverava da li je pretisnut neki taster
JSR ISPISI
Ispisujemo vrednost akumulatora kao petascii kod
INX
Uvećavamo vrednost X za jedan (u ovom slučaju brojač karaktera teksta)
BNE POCTEKISP
Ukoliko registar X nije dostignuo krajnju vrednost od 255 idemo na mesto skoka gde će se ispisati sledeći karakter (u našem slučaju nikad neće dostići ovu vrednost jer naš tekst ima manje karaktera koji ispis se završava zahvaljujući prethodnom ispitivanju kada dođemo do vrednosti 0 koja će se učitati u akumulator iz komande .byte na kraju teksta)
POCETOPET
Mesto skoka/podprogram za očitavanje tastature
LDA 197
Unosimo u akumulator vrednost iz memorijske lokacije koja služi za očitavanje tastature
CMP #64
Upoređujemo da li je ta vrednost 64 /nije pretisnut nijedan taster
BEQ POCETOPET
Ukoliko jeste idemo na mesto skoka ovog ispitivanja i pravimo beskonačnu petlju. Kada pretisnemo bilo koji taster vrednost više neće biti 64 i preći ćemo na sledeću naredbu
RTS
Povratak iz podprograma
TEXTPOCET
Memorijska adresa početka teksta za prikaz početnog ekrana
.TEXT „DOBRODOSLI U IGRU“
.BYTE 13,13
.TEXT „POTREBNO JE DA FORMULOM“
.TEXT “ PREDJETE STAZU 9 PUTA “
.BYTE 13
.TEXT „UPRAVLJANJE“
.BYTE 13
.TEXT „A-LEVO,D-DESNO,W-GORE,“
.TEXT „S-DOLE. BILO KOJI TAST“
.TEXT „ER ZA POCETAK“
Turbo asemblerska komanda „.text“ će konvertovati tekst pod navodnicima u petascii karaktere koji će se smestiti u memoriju i po pozivu prikazati na početnom ekranu, a komanda „.byte 13“ će uneti bajt vrednosti 13 koji predstavlja petascii kod za pritisak na return/enter i samim tim gde god je on unet ispis će se prebaciti u novi red
.BYTE 0
Formiranjem bajta vrednosti 0, koji će se ispitati prilikom unosa u akumulator, zaustavićemo dalji ispis teksta (inače bi se tekst nastavio ispisivati do 255-og karaktera i kodovi ostalih naredbi bi se prikazali kao petascii kodovi praveći papazjaniju od ispisa)
PRIPZVUK
Podprogram/mesto skoka za pripremu zvučnih efekata. Da bi smo pripremili računar za izvođenje zvučnih efekata i muzike treba izbrisati sve memorijske lokacije zadužene za isti. Zvuk smo obrađivali u lekciji 4 standardnog bejzika
LDA #0
Unosimo vrednost nula u akumulator
STA $D400,X
Smeštamo vrednost akumulatora u memorijsku adresu od koje počinje kontrola zvuka uvećane za vrednost registra X
INX
Uvećavamo registar X za jedan
CPX #28
Proveravamo da li je registar X dostigao vrednost 28 koliko ima bajta u kontroli zvuka svih tri kanala C64 koje trebamo izbrisati da bi smo ih pripremili za zvučne efekte i/ili muziku
BNE PRIPZVUK
Ukoliko nije idemo na mesto skoka sve dok se dati uslov ne zadovolji
LDA #8
Unosimo vrednost 8 u akumulator
STA 54296
Smeštamo vrednost akumulatora u memorijsku lokaciju jačine zvuka (0-15) koja važi za sva tri kanala
LDA #240
Unosimo vrednost 240 u akumulator
STA 54278
Smeštamo vrednost akumulatora u memorijsku lokaciju zaduženu za stalnost zvuka i glasnosti prvog kanala (najčešće korišćena vrednost 240 konstantna jačina i postojanje zvuka)
LDA #33
Unosimo vrednost 33 u akumulator
STA 54276
Smeštamo vrednost akumulatora u memorijsku lokaciju zaduženu za oblik zvuka (33-testerasti oblik zvuka)
LDA #20
Unosimo u akumulator vrednost 20
STA 54272
Stavljamo vrednost iz akumulatora u memorijsku lokaciju nižeg bajta zaduženu za visinu tona prvog kanala (raspon osam oktava). Pošto je ovo niži bajt isti ne utiče mnogo na promenu visine tona
STA 54273
Stavljamo vrednost iz akumulatora u memorijsku lokaciju višeg bajta zaduženu za visinu tona prvog kanala (raspon osam oktava). Pošto je ovo viši bajt isti je veoma bitan za promenu visine tona
RTS
Povratak iz podprograma
ZVUK
Podprogram za promene visine tona zvuka emulirajući rad motora formule
LDA #20
STA 54273
LDA #70
STA 54273
LDA #75
STA 54273
LDA #89
STA 54273
LDA #20
STA 54273
U ovih nekoliko instrukcija naizmenično smo menjali visinu tona (viši bajt) prvog kanala zvuka imitirajući (ne baš uspešno) zvuk motora formule
RTS
Povratak iz podprograma
BOD
Mesto memorijske promenljive koja čuva vrednost boda
.BYTE 48
Početna vrednost boda data je u petascii kodu koji odgovara broju 0
Uradimo kompajliranje sa ←3 i ako nema greške u unosu koda (koje će se ukoliko ih ima odmah prikazati i turbo asembler će nas vratiti u izvorni kod da bi se iste ispravile) pretisnimo taster „s“ za startovanje. U napomenama/savetima smo dali kako treba napraviti startnu bejzik programsku liniju i snimiti ovaj program na disketu kao radnu/izvršnu verziju (bez izvornog koda).
Startovanjem programa dobićemo našu igricu. Ovde treba obratiti pažnju na brzinu kretanja sprajtova. Takođe primetili ste da prilikom pomeranja prvog sprajta (formule) ostala dva sprajta kvadrata/smetala smanjuju brzinu kretanja. To je zbog proračuna koji se izvodi prilikom kretanja prvog sprajta (formule). Ovaj sporedni efekat nam se dopao ali ako želite ovo da promenite trebate u podprogramu za usporavanje dati naredbu za upoređivanje vrednosti u registru kojom možete ograničiti cilkuse (u programu je na maksimumu 255) na manji broj kada se vrši pomeranje prvog sprajta (treba naći balans) i samim tim imati uvek istu brzinu kretanja svih sprajtova. Takođe možete dati još jednu petlju ili petlju u okviru petlje ako želite da još više usporite kretanje sprajtova. Izvođenje datog programa uvek možete nasilno prekinuti sa softverskim resetom / kombinacije tastera run/stop+restore (u emulatoru esc+page up) gde neće doći do nikakvog oštećenja ili gubitka startne bejzik programske linije i/ili mašinskog dela programa.
Kao što vidite izuzetno je zanimljivo raditi u asembleru gde se, za razliku od standardnog i Sajmons bejzika, sve mora objasniti računaru, gde treba dobro paziti da ne dođe do preklapanja memorije i gde je moguće uništiti ili oštetiti ceo uneti program pogrešnim zadavanjem promene vrednosti samo jedne ključne memorijske adrese, ali i gde se sve ovo višestruko isplati zahvaljujući mogućnostima ovih programa.
Snažno vam preporučujemo iz ličnog iskustva da uvek snimite na disketu ili virtualnu disketu uneti izvorni asemblerski program, pre prevođenja i aktiviranja istog, pomoću komande turbo asemblera ←s i davanjem naziva fajla (rad u emulatoru pored ovoga podržava i korišćenje state / snapshot opcije za snimanje cele memorije što znatno olakšava posao). Ova predostrožnost će vam spasiti živce i kosu.
Takođe vam preporučujemo da proučite dati program, pokušate da ga proširite, izmenite nešto što mislite da bi dalo bolje rezultate i slično.
Evo jednog primera za vežbu šta možete promeniti u programu: Umesto komandovanja formulom putem tastature da to bude putem palice za igru.
Memorijska adresa koja očitava palicu priključenu u port 1 je $DC00/56320, a onu priključenu u port 2 je $DC01/56321 (naravno kod emulatora port 1 i 2 zavise od virtualnog podešavanja istih)
Moguća stanja položaja palice za igru i njenog dugmeta za pucanje očitane kao brojne vrednosti su sledeće:
Palica u portu 1 ($DC00/56320) Palica u portu 2 ($DC01/56321)
127 – neutralni položaj 255 – neutralni položaj
126 – gore 254 – gore
122 – gore levo 250 – gore levo
123 – levo 251 – levo
121 – dole levo 249 – dole levo
125 – dole 253 – dole
117 – dole desno 245 – dole desno
119 – desno 247 – desno
118 – gore desno 246 – gore desno
111 – pucanje u neutralnom položaju palice 239 – pucanje u neutralnom položaju palice
Kod očitavanja dugmeta za pucanje postoje više kombinacija zavisno od smera palice. Sve detekcije možete uraditi i pomoću logičkih operacija ispitivanja bitova. Važno je da budete kreativni.
Takođe dajemo vam bejzik program za očitavanje stanja palica za oba porta:
10 PRINT PEEK (56320), PEEK (56321)
20 GOTO 10
Sada još da damo uporedne dužine programa i brzine izvršavanja:
Uzećemo za primer veličinu i brzinu izvršavanja slične igre „Trke“ napisane u bejziku koje smo dali u lekciji 5 standardnog bejzika (iako ista ima samo jedan sprajt za kontrolu, a kada bi ih bilo tri, kao kod ove asemblerske igre, bila bi memorijski veća i sporije bi se izvršavala) i veličinu i brzinu izvršavanja mašinskog programa datog u današnjoj lekciji.
Veličine programa:
1) Trke – bejzik program $078E/1934 bajta
2) Formula – mašinski program $03EE/1006 bajta
Razlika u korist mašinskog programa $03A0/ 928 bajta
Brzina izvršavanja programa:
1) Trke – bejzik program – brzina prelaza sprajta
od leve do desne ivice ekrana tačka po tačku
putem programskog upravljanja preko tastera
sa detekcijom sudara, ispitivanjem granica ekrana
i isključenim skrolovanjem ekrana 14,5 sek
2) Formula – mašinac – brzina prelaza sprajta (bez
usporenja) od leve do desne ivice ekrana tačka
po tačku putem programskog upravljanja preko
tastera sa detekcijom sudara i ispitivanjem granica
ekrana 0,0085 sek
Razlika u korist mašinskog programa 1705 puta brže
Ova poređanja jasno stavljaju do znanja zašto su programeri gotovo isključivo programirali u asembleru na C64 (svi bitni komercijalni programi su pisani u njemu) što je važilo i za druge osmobitne računare koji su korišćeni u to vreme.
Sa današnjom lekcijom završili smo malu školu asemblera za C64. Nadam ste da ste uživali u proučavanju mogućnosti asemblerskih/mašinskih programa. Na vama je da ukoliko želite nastavite dalje. Bez obzira što smo upoznali sve asemblerske naredbe i kako ih koristiti u programima postoje još mnogo stvari koje možete naučiti o programiranju u njemu (korišćenje memorijskih lokacija i sistemskih podprograma, razne cake koje mogu smanjiti iskorišćenost memorije i još dodatno ubrzati izvršavanje koda (optimizacija), izvođenje veoma zanimljivih efekata prilikom prikaza grafike i reprodukcije zvuka i mnogo drugih mogućnosti).
Puno pozdrava i želimo vam sve najbolje u daljem životu, učenju i radu.

