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 lokaciju $d015 (53269) i time isključujemo sve sprajtove
STA $D400
Unosimo nulu u memorijsku lokaciju $d400 (54272) i time gasimo zvuk
STA $D401
Unosimo nulu u memorijsku lokaciju $d401 (54273) i time gasimo zvuk
STA $D404
Unosimo nulu u memorijsku lokaciju $d404 (54276) i time gasimo zvuk
RTS
Povratak iz podprograma koji se pošto nam je ovo kraj programa vraća u glavni program i beskonačno ponavlja ispis pobede i isključenje sprajtova i zvuka. Mogli smo ovde dati naredbu za bezuslovni skok JMP na neko mesto u samom programu (time bi program stalno vrteli tu petlju) ili naredbu BRK gde bi izašli iz programa (obaška što bismo trebali dodatno da restartujemo neka stanja)
SUDAR
Podprogram za detekciju sudara između sprajtova
LDA $D01E
Učitavamo vrednost iz registra sudara sprajtova u akumulator. Ukoliko se neki sprajt sudari sa drugim setovaće se za svaki od njih njegov bit vrednosti (po sprajtu 0-7). Pošto imamo tri sprajta, ukoliko nema sudara vrednost će biti nula, a ako ima biće minimum 3 (naravno zavisno od toga koji su se sprajtovi sudarili i koliko njih biće i veće vrednosti)
CMP #0
Proveravamo da li je vrednost akumulatora nula što znači da nije bilo sudara između sprajtova
BNE IZGUBIO
Ako vrednost nije nula znači da je bilo sudara i skačemo na kraj programa gde se objavljuje poraz (pošto nije moguće proveriti da li se desio sudar sprajt-sprajt između smetala šta ne utiče na ishod igre, dajemo ih na različitu visinu gde ne može doći do njihovog sudara)
RTS
Povratak iz podprograma
IZGUBIO
Podprogram/mesto skoka za objavu poraza
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 #“I“-64
Dajemo slovo „i“ 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 #“Z“-64
Dajemo slovo „z“ 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 #“G“-64
Dajemo slovo „g“ 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 #“U“-64
Dajemo slovo „u“ 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 #“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 $0404
Smeštamo ekranski kod karaktera iz akumulatora u ekransku memoriju (prvi red,peta kolona)
LDA #“I“-64
Dajemo slovo „i“ 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 #“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 $0406
Smeštamo ekranski kod karaktera iz akumulatora u ekransku memoriju (prvi red,sedma kolona)
LDA #0
Brišemo vrednost akumulatora
STA $D015
Unosimo vrednost akumulatora u memorijsku lokaciju $d015 (53269) i time isključujemo sve sprajtove
STA $D400
Unosimo nulu u memorijsku lokaciju $d400 (54272) i time gasimo zvuk
STA $D401
Unosimo nulu u memorijsku lokaciju $d401 (54273) i time gasimo zvuk
STA $D404
Unosimo nulu u memorijsku lokaciju $d404 (54276) i time gasimo zvuk
RTS
Povratak iz podprograma koji se pošto nam je ovo kraj programa vraća u glavni program i beskonačno ponavlja ispis poraza i isključenje sprajtova i zvuka
POCETEKRAN
Podprogram za ispis teksta uputstva na početnom ekranu i čekanje pritiska bilo kog tastera
LDA #147
Unosimo vrednost 147 (petascii kod za brisanje ekrana) u akumulator
JSR ISPISI
Pozivamo sistemski podprogram za izvršavanje petascii koda koji je dat u akumulatoru
LDX #0
Praznimo registar X. Služiće nam kao brojač ispisa teksta početnog ekrana
POCET1
Mesto skoka početne petlje ispisa teksta na početnom ekranu
LDA TEKST,X
Učitavamo u akumulator podatak iz memorijske lokacije TEKST uvećan za vrednost registra X. Memorijska lokacija TEKST se dobija prilikom prevođenja programa, a služi za čuvanje teksta koji će se ispisati na početnom ekranu
JSR ISPISI
Pozivamo sistemski podprogram za ispis petascii koda datog u akumulatoru. Ovaj put je u pitanju karakter teksta koji se učitava iz memorije
INX
Uvećavamo registar X za jedan i na taj način pomeramo se za jedan bajt kroz tekst koji ispisujemo
CPX #200
Proveravamo da li je X registar dostigao vrednost 200 što znači da smo ispisali 200 karaktera teksta
BNE POCET1
Ako vrednost nije jednaka 200 skačemo na početak petlje za ispis teksta
CEKAJ
Mesto skoka čekanja pritiska tastera
LDA 197
Učitavamo u akumulator vrednost memorijske lokacije 197 koja služi za očitavanje tastature
CMP #64
Proveravamo da li je vrednost 64 koja se dobija kada nije pretisnut nijedan taster
BEQ CEKAJ
Ukoliko nije pretisnut nijedan taster skačemo natrag i ne pokrećemo igru
RTS
Ukoliko je pretisnut bilo koji taster vraćamo se u glavni program gde počinje igra
TEKST
Mesto čuvanja teksta za ispis na početnom ekranu
.TEXT „{CLR}{3 DOWN} UPRAVLJAJ SVOJOM“
Prvi red teksta. Dajemo turbo asemblersku naredbu za čuvanje teksta .text. Tekst se stavlja između navodnika i može sadržati običan tekst kao i petascii kodove karaktera sa specijalnom namenom. U našem slučaju dajemo tekst za brisanje ekrana (višak od ranije ali nam neće smetati), skakanje tri reda dole i ispis poruke. Ukoliko želimo možemo direktno dati petascii/ekranski kod nekog karaktera čime u istom redu stavljamo {} i odmah upisujemo vrednost istog. U pitanju su vitičaste zagrade (na engleskom keyboardu preko emulatora: shift + i shift -). Isto tako u njih možemo upisati vrednosti za izvršavanje nekih posebnih petascii kodova (kao što je npr. {clr}, a što je lakše od pamćenja brojnih vrednosti koje se razlikuju za petascii i ekranski kod / mala i velika slova)
.TEXT „{DOWN} FORMULOM I IZBEGNI“
Drugi red teksta koji pokazuje da koristeći specijalne petascii kodove kroz tekst možemo pomerati mesto ispisa i učiniti ga da bude pregledan
.TEXT „{DOWN} PROTIVNIKE“
Treći red teksta
.TEXT „{DOWN} A-LEVO D-DESNO“
Četvrti red teksta
.TEXT „{DOWN} W-GORE S-DOLE“
Peti red teksta
.TEXT „{DOWN} PRETISNI TASTER“
Šesti red teksta
.TEXT „{DOWN} I KRENI“
Sedmi red teksta
POZADINA
Podprogram za iscrtavanje pozadine puta kojim će se kretati formula
LDX #0
Praznimo registar X koji će nam služiti kao brojač za bojenje pozadine
POZADINA1
Mesto skoka za ciklus bojenja pozadine
LDA #3
Unosimo vrednost 3 u akumulator
STA 55351,X
Smeštamo vrednost akumulatora u boju pozadine računajući od zadate memorijske adrese uvećano za vrednost X registra
STA 55391,X
Smeštamo vrednost akumulatora u boju pozadine računajući od zadate memorijske adrese uvećano za vrednost X registra
INX
Uvećavamo vrednost registra X za jedan
CPX #22
Proveravamo da li je X dostigao vrednost 22
BNE POZADINA1
Ako nije idemo na početak petlje za bojenje pozadine
RTS
Povratak iz podprograma
PRIPZVUK
Podprogram za pripremu zvuka
LDA #15
Unosimo vrednost 15 u akumulator
STA $D418
Smeštamo vrednost akumulatora u memorijsku lokaciju $d418 (54296) koja služi za regulaciju jačine zvuka
LDA #0
Brišemo akumulator
STA $D405
Smeštamo vrednost akumulatora u memorijsku lokaciju $d405 (54277)
STA $D406
Smeštamo vrednost akumulatora u memorijsku lokaciju $d406 (54278)
STA $D404
Smeštamo vrednost akumulatora u memorijsku lokaciju $d404 (54276)
STA $D401
Smeštamo vrednost akumulatora u memorijsku lokaciju $d401 (54273)
STA $D400
Smeštamo vrednost akumulatora u memorijsku lokaciju $d400 (54272)
RTS
Povratak iz podprograma
ZVUK
Podprogram za proizvodnju zvuka
LDA #12
Unosimo vrednost 12 u akumulator
STA $D400
Smeštamo vrednost akumulatora u memorijsku lokaciju $d400 (54272) koja služi za niži bajt frekvencije prvog glasa
LDA #16
Unosimo vrednost 16 u akumulator
STA $D401
Smeštamo vrednost akumulatora u memorijsku lokaciju $d401 (54273) koja služi za viši bajt frekvencije prvog glasa
LDA #33
Unosimo vrednost 33 u akumulator
STA $D404
Smeštamo vrednost akumulatora u memorijsku lokaciju $d404 (54276) koja služi za kontrolu oblika zvuka prvog glasa
RTS
Povratak iz podprograma
BOD
Mesto čuvanja broja bodova
.BYTE 48
Opis bajta za smeštanje vrednosti bodova čija je početna vrednost 48 (petascii/ekranski kod za vrednost nula)
Prateći objašnjenja za svaku programsku liniju mogli smo videti jedan malo veći asemblerski program sa svim zanimljivim radnjama koje koristi, a sada ostaje da ga prevedemo, pokrenemo i testiramo.
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 programa. Ovo iz razloga što prilikom unošenja koda može doći do greške, a i turbo asembler zna nekad da pobrljavi i da program zabode. Ukoliko je sve u redu sa kompajliranjem i startovanjem programa idite ←5, a zatim „S“ za snimanje izvornog koda na disketu. Kasnije za ponovno učitavanje istog dovoljno je ići ←5 pa „L“. Program u turbo asembleru se snima sa ekstenzijom .s (koju ne morate ukucavati prilikom učitavanja)
Do sada smo za testiranje koristili tastaturu. Za programiranje igrica bi bilo zgodno da možemo koristiti džojstik ili danas joypad (što turbo asembler i mašinski programi i te kako mogu). U našem programu nismo želeli to da uradimo zbog dužine i dodatnog objašnjavanja ali nije veliki problem. Na C64 postoje dve memorijske lokacije očitanja položaja džojstika i dugmeta za pucanje i to $dc00/56320 za port 1 i $dc01/56321 za port 2.
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)
GORE 254 127
DOLE 253 126
LEVO 251 125
DESNO 247 123
PUCANJE 239 119
Obratite pažnju da ukoliko držimo palicu ukoso ili u više pravaca biće dobijena kombinacija ovih vrednosti i takvo očitanje se kao takvo može koristiti za manipulaciju programom (npr: u levo i dole = 249 za port 1)
Sada još da damo uporedne dužine programa i brzine izvršavanja:
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:
Provera na 50 for/next petlji sa po 10000 ciklusa i po 10
obrada u svakom ciklusu što daje oko 5 miliona obrada
1) Trke – bejzik program 14,5 sek
2) Formula – mašinski program (znači obuhvaćeno usporenje, iščitavanje
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.