RETRO KUTAK – tehnologija prošlih decenija

C64 ASEMBLER (C64 ASSEMBLY) – LEKCIJA 7

Ovaj tekst pripada serijalu „C64 ASEMBLER (C64 Assembly)“ i predstavlja Lekciju 7.
Sadrži detaljno objašnjenje kako napraviti jednostavnu igru u asembleru na Commodore 64 koristeći Turbo Assembler.
Objašnjeni su ključni pojmovi: memorijske adrese, rad sa spriteovima, detekcija sudara, kontrola tastaturom i zvučni efekti preko SID čipa.
Takođe je dato poređenje BASIC i asemblerskog programa po dužini i brzini izvršavanja – uz dokaz da je asembler višestruko brži i efikasniji.
Tekst pruža praktične primere koda, savete za snimanje izvršnog fajla na disketu, kao i preporuke za eksperimentisanje i proširenje igre.
Ključne teme: Commodore 64, C64 assembler, Turbo Assembler, mašinski kod, sprite programiranje, BASIC vs asembler, retro programiranje.

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.

Оставите одговор

Ваша адреса е-поште неће бити објављена. Неопходна поља су означена *