Interrupt - Programmierung

Moderator: Rockford

Antworten
Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Interrupt - Programmierung

Beitrag von Dr. Irata »

Ich mache mal ein neues Thema auf, weil ich es so spannend finde.
Und habe gleich eine Frage:

Als junger Kerl habe ich viel im Basic programmiert. Für meinen Mathekurs habe ich dann in Basic eine Kurvendiskussion geschrieben, mit grafischer Darstellung der Kurve. Man konnte via INPUT eine beliebige Funktion eingeben, der Rechner hat sie dann in einem Koordinatensystem gezeichnet.
Mein Problem damals war: Wie bekomme ich die Funktion in das Programm?
Die Lösung: Ich positioniere den String mit der durch INPUT eingegebenen Funktion auf den Bildschirm, positioniere den Curser oberhalb des Strings, unterhalb des Strings kommt ein Befehl auf dem Bildschirm CONT, dann ein paar Returns in den Tastaturbuffer und das Programm stoppen.
Der Curser läuft über den String (mit Zeilennummer), speichert ihn ins Programm und durch den Befehl CONT startet das unterbrochene Programm wieder. Dann kann die Funktion gezeichnet werden.
Jetzt die Frage:
Kann ich in meinem Assemblerprogramm etwas in den Tastaturbuffer speichern und löse damit den Tastaturinterrupt aus??
Also es geht um die Auslösung des Tastaturinterrupts ohne eine Taste zu drücken...
Gruß
Peter

Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von Dr. Irata »

Folgende Möglichkeit eines weiteren Interrupt, den man sehr schön in seinem Programm nutzen kann habe ich gerade entdeckt und ausprobiert:
Der Break-Interrupt!!!

Folgende Idee: Der VBI ist ja so schön, da er kontinuierlich 5 x pro Sekunde ausgelöst wird. Viele Steuerungen können so im VBI super programmiert werden, leider ist halt irgendwann Schluss! Den VBI aufzuteilen geht, aber dann wird die Steuerung träge und die Schüsse laufen langsamer, was man dann wieder aufwendig abfangen muss. Insgesamt sind da klare Limitationen. Die möglichen ca. 1600 Befehle gehen auch nur bei 50 Hz und ab ca. 600 Befehle wirds dann langsam instabil - da das ja noch den Bildschirmaufbau betrifft, bekommt man mit zunehmender Länge des Programmes im VBI Probleme mit der Bildstabilität.
Also dachte ich mir folgendes: Warum nicht den schönen VBI als Timer für einen anderen Interrupt nutzen. Der Tastaturinterrupt wäre möglich, man muss aber dann per Programm einen Tastendruck simulieren - habe ich jetzt noch nicht hinbekommen, geht bestimmt.
Wir haben aber noch den Break-Interrupt .... und der geht!
Immer wenn ein Maschinenprogramm auf einen Break-Befehl trifft, wird der Interrupt ausgelöst - und die Vektoren kann man abfangen und entsprechend umbiegen:

Der BRK - Befehl steht einfach im VBI und löst somit 5x pro Sekunde den Interrupt aus!

Code: Alles auswählen

.proc vbinter2			
			
			pha
			txa
			pha
			tya
			pha
									
			brk
			
			...
			weiterer Code
			
			
Vor dem Hauptprogramm wird der alte Vektor gerettet und der neue ins Register reingeschrieben:

Code: Alles auswählen

			mwa vbreak breakin
			mwa #tastaturi vbreak	


Dann einfach die Subroutine einfügen (unterhalb des Hauptprogrammes - dieses selber wird gar nicht verändert)

Code: Alles auswählen

.proc tastaturi
			
			pha
			txa
			pha
			tya
			pha
			
			...
			
			hier steht der Code (z.B. die Missiles)
			...
			
			pla
			tay
			pla
			tax
			pla
			jmp (breakin)
			
	
	.endp
			
			


getestet und funktioniert... ;-)

Benutzeravatar
Kveldulfur
Beiträge: 624
Registriert: 17.08.2021 02:32
Has thanked: 237 times
Been thanked: 163 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von Kveldulfur »

Hallo Peter!

Der VBI ist genauso oft wie die Hz-Zahl des Bildschirmaufbaus. Also 50Hz oder 60Hz, dass sind 50x in der Sekunde oder 60x in der Sekunde.
Du kannst sicherlich einen weiteren Interrupt innerhalb eines Interrupts aufrufen, nur wird das nichts daran ändern, dass Du nur eine bestimmte Anzahl an Maschinenzyklen in der gleichen Zeit hast.
Zumal wenn Du ein Objekt innerhalb eines VBIs mehrfach bewegst, diese Bewegung nicht angezeigt wird, weil der Bildschirm nicht erneut aufgebaut wurde, dann kannst Du das Objekt gleich zwei oder drei Schritte auf einmal machen lassen.

Ich denke mit dem Ansatz kommst Du nicht besonders weit und statt BRKs könntest Du auch JSRs nutzen.

Grüße
Janko

Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von Dr. Irata »

Hallo Janko,
prinzipiell hast du Recht, ich komme nicht viel weiter, aber ich komme damit ein wenig weiter....
Ich habe jetzt den langen VBI in 2 VBI´s geteilt und die Schüsse und die Steuerung so modifiziert, daß sie immer 2 y / x-Werte weiter gehen.
Zusätzlich habe ich jetzt nochmal ca. 200-300 Programmcodes frei im BRK-Interrupt, der dann auch jeweils vom 2. VBI gesteuert wird - also 2.5x pro Sekunde (nicht 5x) - hier habe ich experimentiert und es funktioniert... mache ich mehr Code in den BRK Interrupt, friert der Atari komplett ein.
Ich hoffe, daß ich so aber noch ganz bequem die Soundsteuerung unterbringen kann... mehr brauche ich nicht, der Rest läuft im Hauptprogramm.
Ich programmiere das mal durch und stelle dann den Code hier online...
Gruß
Peter

Benutzeravatar
atarixle
Beiträge: 271
Registriert: 18.06.2021 21:19
Has thanked: 29 times
Been thanked: 51 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von atarixle »

Das waren damals keine Returns im Tastaturbuffer, sondern eher dieser eine simple POKE, der die Taste Return dauerhaft ausgelöst hat, solange der Editor E: aktiv war.

Schau mal bitte in das Atari Profibuch Seite 162.

Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von Dr. Irata »

... hm ja, verstehe. Mit dem Editor bin ich allerdings auch noch nicht so firm. Wenn ich das richtig gelesen habe, dann kann ich per Software keine Tastaturaktion simulieren und so den Interrupt auslösen??

Benutzeravatar
Kveldulfur
Beiträge: 624
Registriert: 17.08.2021 02:32
Has thanked: 237 times
Been thanked: 163 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von Kveldulfur »

Hallo Peter!

Ich bin ja ein kleiner Fan von Peter Finzel und kann Dir nur empfehlen "die Hexenküche" zu lesen. Da wird sehr viel über Interrupts erklärt.
Auch sehr schön ab Seite 47 der Abschnitt "Wie schnell ist Ihr ATARI?".

Grüße
Janko

Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von Dr. Irata »

Tatsächlich habe ich den Artikel bereits mehrfach gelesen und finde ihn gut - ich habe die Hexenküche original hier und übrigens auch eine alte Originalausgabe von DeRe - auch ein interessantes Buch.
Über die Interruptprogrammierung - also so richtig in die Tiefe - findet man leider nicht so viel..
Lieben Dank und Gruß
Peter

... aus dem wie schnell der Atari ist, habe ich ja auch entnommen, wie viele Befehle in in den VBI stecken kann - leider auch alles ein wenig Theorie, denn ab ca. 500-600 Befehlen wirds dann zunehmend instabil

FlorianD
Beiträge: 182
Registriert: 19.08.2021 00:18
Has thanked: 21 times
Been thanked: 55 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von FlorianD »

hast Du dieses Buch schon mal durchgearbeitet?
https://www.atariarchives.org/agagd/

Ich finde, die Autoren erklären am besten von allen, wie man Spiele auf dem ATARI programmiert und VBI, DLI usw ausnutzt.

Ein sehr gutes Kapitel ist
https://www.atariarchives.org/agagd/chapter9.php

Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von Dr. Irata »

... oh ... das ist interessant!!
Vielen Dank!!!!

FlorianD
Beiträge: 182
Registriert: 19.08.2021 00:18
Has thanked: 21 times
Been thanked: 55 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von FlorianD »

ich habe das Buch folgendermaßen verstanden, grob beschrieben sollte man so vorgehen: Positionen von Playern, Missiles, Landschaft in der Hauptroutine berechnen, und dann im Interrupt nur "setzen", bzw abwechselnd Bilder aufbauen und jeden 2. Interrupt wechseln.

In der Hauptroutine hast Du ewig Zeit für komplizierte Berechnungen, solltest aber keine P/M/DL "zeichnen" oder "Löschen", dann flackert das Bild.

Benutzeravatar
DjayBee
Beiträge: 625
Registriert: 17.08.2021 04:02
Has thanked: 384 times
Been thanked: 175 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von DjayBee »

Exakt.
Das war der Hintergedanke meines Kommentars im RtP Thread.

Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von Dr. Irata »

... dies ist ja mein erstes Projekt dieser Art und natürlich sammelt man da so seine Erfahrungen.
Primär wollte ich anhand dieses Spieles Assembler lernen und den Atari noch besser verstehen lernen... daß das so kompliziert wird und daß ich im Prinzip bei diesem komplexen Programm alles ziehen muss, ahnte ich zu Beginn nicht. Mein nächstes Projekt werde ich ganz anders aufbauen und diesen Artikel werde ich gut studieren.
Ich habe jetzt in den letzten Wochen viel experimentiert und muss feststellen: Um alles so machen zu können, wie ich es vor hatte, müsste ich alles komplett umbauen ... das macht jetzt keinen Sinn. Ich mache ein paar Abstriche - es wird nur 2 Missiles geben, die Landschaft wird nicht 15 Minuten scrollen, sondern weniger, dafür baue ich andere Dinge noch ein. Ich möchte das Projekt wirklich abschließen und ein schönes spielbares Programm rausbringen. Caverns of Mars I war auch viel einfacher, als Phobos...
Ich finde es aber echt toll, wie Ihr hier auch mitlest oder mit immer wieder Tips gebt.
Am Ende möchte ich einen guten Code haben, der zwangsläufig viele Aspekte berücksichtigt: Feinscrolling, P/M Grafik, Animationen, Aufbau Landschaft / Speicher, Interrupts, Displaylist, Sound - incl. kleine Engine, die man ins Programm einbinden kann... vielleicht nehme ich die SFX und modifiziere sie... einen guten Sprite/ Landschaftsteile Editor habe ich heute Dank Mathy gefunden.
Alles möchte ich dann hier in einem Extrablock incl. Assemblercode zusammenstellen und veröffentlichen... vielleicht macht man sogar ein kleines Lernscript daraus, was frei verfügbar ist. Für alle und natürlich kostenlos.....
Liebe Grüße
Peter

Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von Dr. Irata »

Grundsätzlich ist es also das Problem des Timings....
In dem Artikel wird ja beschrieben, wie der VBI Teile der Hauptroutine steuert...
Ein Problem dabei ist wohl, daß der VBI viel schneller läuft als das Hauptprogramm... wenn eine Schleife im Hauptprogramm auf den VBI wartet, dann ist der vielleicht schon ein paar mal durchgelaufen. Allerdings habe ich zur Zeit immer ein Problem mit der Kollision, denn wenn der Missile kollidiert und das dann an das Hauptprogramm weitergegeben wird, dann läuft er ja schon etwas weiter (weil der VBI schneller ist) und überschreibt die Kollision mit etwas anderem...

Benutzeravatar
DjayBee
Beiträge: 625
Registriert: 17.08.2021 04:02
Has thanked: 384 times
Been thanked: 175 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von DjayBee »

Bist du dir sicher, dass deine Hauptprogrammschleife länger braucht, als 1/50 Sekunde, der Zeit zwischen zwei VBIs?

Teste es doch einfach mal:
Lies RTCLOK+2 am Beginn und Ende deiner Schleife aus und vergleich die Werte. Dann siehst du, wieviele VBIs dazwischen vergangen sind weil RTCLOK+2 innerhalb jedes VBIs inkrementiert wird.

Das Zeitproblem im VBI ist ja nicht, dass du die 1/50 Sekunde überschreitest, sondern dass du innerhalb des VBIs nur den kurzen Zeitraum hast, den der (vermutlich inzwischen virtuelle) Kathodenstrahl benötigt, um von rechts unten nach links oben geschwenkt zu werden.

Du hast zwei Möglichkeiten, dich zu synchronisieren.

Entweder für die komplette Hauptschleife, was sinnvoll ist, wenn sie deutlich weniger Zeit benötigt, als die 1/50 Sekunde und du nicht willst, dass sie schneller abläuft.

Oder, wie in meinem Beispiel im anderen Thread, du baust die Dinge, die gezielt innerhalb jeder 1/50 Sekunde einmal (aber nicht exakt synchron, wie im VBI) passieren müssen, in ein Unterprogramm ein, das du (ggf. auch mehrfach) aus deinem Hauptprogramm aufrufst.
Da passen z.B. die Kollisionsabfragen rein oder auch Änderungen auf dem gerade nicht sichtbaren Bildschirm, falls du mittels Page-Flipping bzw. Double-Buffering arbeitest.
Der mehrfache Einbau der Unterprogramme hat dann Sinn, wenn dein Hauptprogramm tatsächlich mehr Zeit verschlingt, als 1/50 Sekunde.

Mini-Codebeispiel für die Variante Hauptschleife:

Code: Alles auswählen

; Programmbeginn

; Hauptschleife
main
	lda RTCLOK+2
	sta startzeit		; Ein Byte, das du irgendwo allokiert hast.
	
; Hier kommt deine Hauptschleife mit all den zeitaufwändigen Aufgaben rein.

; Warte darauf, dass der VBI ausgeführt wird.
; Falls der Schleifendurchlauf langsamer war, geht's direkt weiter weil RTCLOK+2 bereits inkrementiert wurde.
	lda startzeit
warte
	cmp RTCLOK+2
	beq warte

; Und es geht von vorne los.
	jmp main
Mini-Codebeispiel für die Variante Unterprogramm (analog zum RtP Thread) minimal erweitert:
Die Unterprogramme steuer dabei selbst, dass sie zwischen zwei VBIs nur einmal ausgeführt werden. Jeder weitere Aufruf innerhalb dieser Zeit führt zu einem direkten RTS.

Code: Alles auswählen

; Programmbeginn

; Stell einen definierten Anfangszustand her.
; Ansonsten kann es sein, dass der erste Durchlauf stottert.
	lda RTCLOK+2
	sta letzter_durchlauf1		; Ein Byte, das du irgendwo allokiert hast.
	sta letzter_durchlauf2
	; und ggf. für weitere Unterprogramme

; Hauptschleife

main
; Wieder deine Hauptschleife mit all den zeitaufwändigen Aufgaben.
	jsr tue_dieses
	jsr kollisionen	; VBI-synchronisiert
	jsr bildschirmaufbau_double_buffer	; VBI synchronisiert
	jsr tue_jenes
	jsr mach_was_tolles	; das ganz lang dauert
	jsr kollisionen	; VBI-synchronisiert; ein zweites Mal, falls "mach_was_tolles" zu lange gebraucht hat
	jsr bildschirmaufbau_double_buffer	; VBI synchronisiert

; Und es geht von vorne los.
	jmp main
	
kollisionen
	lda RTCLOK+2	; wird im Stage 1 VBI automatisch inkrementiert
	cmp letzter_durchlauf1
	bne mach_weiter1
	rts
mach_weiter1
	sta letzter_durchlauf1
; Berechne die Kollisionen und merk die Ergebnisse für die Umsetzung im VBI
	rts

bildschirmaufbau_double_buffer
	lda RTCLOK+2	; wird im Stage 1 VBI automatisch inkrementiert
	cmp letzter_durchlauf2
	bne mach_weiter2
	rts
mach_weiter2
	sta letzter_durchlauf2
; Bau denzweiten Bildschirm auf, dass du im VBI umschalten kannst.
	rts
	

Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von Dr. Irata »

Ich glaube auch, daß ich prinzipiell mehr Zeit in der Hauptschleife hätte, wobei da schon ne Menge Code drin ist... wahrscheinlich liegt es in der primären Konzeption! Ich habe ja den gesamten Grob-/Feinscroll in der Hauptroutine. Der Grobscroll ist bei mir so aufgebaut, dass er den gesamten Bildschirm um eine Reihe verschiebt - und das braucht Zeit. Der Feinscroll ist da natürlich viel schneller und damit das flüssig läuft, habe ich da m ittels RTCLOK schon jeweils bei jeder Feinscrollausführung eine Warteschleife drin. Das bremst die Hauptschleife natürlich enorm aus.
Ich müsste also den Grobscroll schneller machen und so konzipieren, daß er nicht den ganzen Bildschirm hochscrollt, sondern nur die Bildschirmvektoren umbiegt. Das wäre sicherlich sinnvoll ... aber ich habe ja die letzte Reihe so aufgebaut, daß sie quasi komprimierte Daten aus dem Speicher holt und die letzte Landschaftreihe quasi daraus immer aufbaut. In der anderen schnellen Version würden ich ja nur quasi den Computerspeicher "abfahren" und bei 980 Byte proBildschirm wäre dann nach 20-25 Bildschirmzyklen (a ca 5 Sekunden) nach ca. 2 Minuten Scrollzeit der Speicher voll... so schaffe ich ca. 10-15 Minuten.
Tales Of Beta Lyrae zB hat wahrscheinlich genau aus diesem Grund einen komplexen Zufallsgenerator für die Landschaft generiert... da hat man dann nicht so ein Speicherproblem. Und bei Phobos hört der automatische Scroll dann irgendwann auf und man fährt langsam durch die Lande... wahrscheinlich genau aus diesem Grund.
Ich müsste alles komplett umkonzipieren.....
Lieben Gruß
Peter

Benutzeravatar
DjayBee
Beiträge: 625
Registriert: 17.08.2021 04:02
Has thanked: 384 times
Been thanked: 175 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von DjayBee »

Prodehl hat geschrieben:
06.02.2022 11:37
Ich müsste also den Grobscroll schneller machen und so konzipieren, daß er nicht den ganzen Bildschirm hochscrollt, sondern nur die Bildschirmvektoren umbiegt. Das wäre sicherlich sinnvoll ... aber ich habe ja die letzte Reihe so aufgebaut, daß sie quasi komprimierte Daten aus dem Speicher holt und die letzte Landschaftreihe quasi daraus immer aufbaut.
Wenn du jede Bildschirmzeile in der Displaylist mit einer Adresse versiehst, anstatt nur der ersten (und ggf. der nach 4 KB), kannst du beides haben.

Du schiebst dann die Adressen der jeweiligen Bildschirmzeilen durch die Displaylist durch und baust die letzte Zeile nicht speichertechnisch "ganz hinten" auf, sondern an der Adresse auf die die letzte Zeile in der Displaylist gerade zeigt.

Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von Dr. Irata »

Code: Alles auswählen

.proc wartes
			clc
 		   	ldx delay ; Warteschleife
st  			lda RTCLOK+2    
wa   			cmp RTCLOK+2    
        		beq wa    
        		dex            
        		bpl st 
        		rts
        .endp
        
        	; -------------------------------------------------------------------------------------
        	
	.proc feinscroll
			ldy #1
			mva #0 delay
@			jsr wartes
			
			sty vscrol
			iny
			cpy #8
			bne @-		
			rts
        .endp	

so sieht mein Feinscroll und die zugehörige Warteschleife aus...

und so der Programmablauf ohne Warteschleife...
rt2.1 2.MOV
(745.94 KiB) 54-mal heruntergeladen

Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von Dr. Irata »

Hey DjayBee ....
ganz 100% habe ich nicht verstanden, wie ich das umsetzen kann, aber prinzipiell habe ich es verstanden... ja, das wird wohl die Lösung sein!
Und dann läuft der Fein-/ und Grobscroll fast identisch schnell ab...

Benutzeravatar
DjayBee
Beiträge: 625
Registriert: 17.08.2021 04:02
Has thanked: 384 times
Been thanked: 175 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von DjayBee »

Das würde ich definitiv im VBI tun. Da musst du nicht explizit warten und Zyklen verbrennen, sondern bekommst schön alle 1/50 Sekunde einen Aufruf und kannst dann, bei einem delay von 0 wie in deinem obigen Beispiel, jedes Mal einen Finescroll durchführen.

Falls du den Grobscroll mittels Manipulation der Displaylist machen möchtest, weiß ich nicht, ob das kurz genug für einen VBI ist. Ggf. musst du dann mit zwei Displaylists arbeiten, diese im Hauptprogramm verändern (wenn VSCROL=7) ist und die jeweils neue Adresse in SDLSTL hinterlegen. Dann wird sie automatisch vom nächsten VBI aktiviert, in dem du dann VSCROL gleichzeitig auf 0 setzt.

Ich hab den Eindruck, dass du bei Rob von playermissile.com etwas abgeschaut hast.
Lies dazu mal Interlude: Vertical Blank Interrupts
und den Code bei Code Walkthrough: 2D Scrolling with DLI (vom Wort DLI hier nicht irritieren lassen).

Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von Dr. Irata »

...ja klar, da habe ich viel nachgelesen...

FlorianD
Beiträge: 182
Registriert: 19.08.2021 00:18
Has thanked: 21 times
Been thanked: 55 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von FlorianD »

Prodehl hat geschrieben:
06.02.2022 00:45
... dies ist ja mein erstes Projekt dieser Art und natürlich sammelt man da so seine Erfahrungen.
Primär wollte ich anhand dieses Spieles Assembler lernen und den Atari noch besser verstehen lernen... daß das so kompliziert wird und daß ich im Prinzip bei diesem komplexen Programm alles ziehen muss, ahnte ich zu Beginn nicht. Mein nächstes Projekt werde ich ganz anders aufbauen und diesen Artikel werde ich gut studieren.
...
Ich habe jetzt in den letzten Wochen viel experimentiert und muss feststellen: Um alles so machen zu können, wie ich es vor hatte, müsste ich alles komplett umbauen ... das macht jetzt keinen Sinn.
...
Ich finde es aber echt toll, wie Ihr hier auch mitlest oder mit immer wieder Tips gebt.
Am Ende möchte ich einen guten Code haben, der zwangsläufig viele Aspekte berücksichtigt: Feinscrolling, P/M Grafik, Animationen, Aufbau Landschaft / Speicher, Interrupts, Displaylist, Sound - incl. kleine Engine, die man ins Programm einbinden kann... vielleicht nehme ich die SFX und modifiziere sie... einen guten Sprite/ Landschaftsteile Editor habe ich heute Dank Mathy gefunden.
...
Du hast schon SO VIEL gelernt und umgesetzt, das ist bewundernswert! Mach nur weiter und lass Dich nicht entmutigen. Es gibt viele gute Bücher, Beispiele, und oft mehr als einen Weg nach ROM, äh RAM, äh nee Rom.
Das wird schon. Manchmal muss man auch noch mal von vorn anfangen, ging mir auch oft genug so. Aber bis dahin hat man viel gelernt und das hat man in Petto/in Reserve. Viel Kommentieren macht alten Code besser verständlich, auch so eine Erfahrung.

Benutzeravatar
LarsImNetz
Beiträge: 152
Registriert: 24.08.2021 18:27
Has thanked: 109 times
Been thanked: 80 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von LarsImNetz »

Hallo alle zusammen.

Wenn man das hier so verfolgt, glaube ich, Peter Du machst etwas verkehrt.

Nur mal mein "Sempf" dazu:
- Du solltest Dein Programm nicht vollständig im VBI laufen lassen, da es hier zu viele Einschränkungen bzgl. der Zeit gibt. Im VBI sollten nur Dinge gemacht werden wie Feinscrolling oder das Zurücksetzen des Displaylist-Interrupts.

- Erstelle beliebig viele kleine Displaylist-Interrupts, die nur die Farbe anpassen oder CHBASE verbiegen. Brauchst Du mehrere, verbiege am Ende VDSLST auf den nächsten DLI-Interrupt. Hast Du einen DLI zu viel oder zu wenig, der VBI richtet das, Dein Programm verabschiedet sich nicht gleich in die Jagdgründe.

- Teile sämtliche Arbeiten in kleine unabhängige Routinen auf und lass diese von einer Main-Loop in der von Dir gewünschten Reihenfolge aufrufen. Wenn Du am Ende der Main-Loop bist, warte einfach bis VCOUNT==94 ist und beginne die Main-Loop wieder von vorne. So kannst Du Dein Programm syncron zu 1/50s oder 1/60s halten.

- Willst Du nur jeden 10ten Interrupt eine der Routinen ausführen, dann decrementiere einen Counter innerhalb deiner Routine und wenn der Counter 0 ist, führe die Routine aus. Die Routine wird alle 1/50s gerufen, aber nur jeden 10ten Interrupt ausgeführt. Die paar extra-Zyklen für das Decrement und JSR/RTS sind nicht der Rede wert. Willst Du die Routine häufiger rufen, weil z.B. Schüsse in schnellerer Abfolge passieren sollen, dann setze einfach den Initialwert für den Counter runter. So klappt es dann auch mit unterschiedlichen Levels.

So bist Du auch in der Lage mehr zu machen, als wenn alles im VBI verwurstet ist. Du kannst länger laufende Routinen z.B. jeden 2. Main-Loop-Durchlauf laufen lassen und in der anderen Phase andere Dinge machen. Das Programm wirkt flott und bleibt aufgeräumt. Was Du vermeiden solltest, das die kleinen Routinen zu viele Dinge machen und länger als 1/50s laufen, dann solltest Du sie optimieren oder aufspalten.
Und sollte Dein Programm doch anfangen zu ruckeln, ist evtl. Main-Loop-Durchlauf noch nicht optimal. Man muss nicht jede 1/50s den Score neu zeichnen. Das kann man prima machen, wenn Zeit da ist.

Du willst wissen, wie viel Zeit eine Deiner kleinen Routinen verbraucht. Zähle die Zeilen.(?) Dazu: warte bis VCOUNT >= 4 ist, setze die Hintergrundfarbe auf einen anderen Wert als Schwarz, führe Deine Routine aus, am Ende setzt du die Hintergrundfarbe wieder auf Schwarz. So bekommt man recht schnell einen Überblick über Routinen die recht lange brauchen. Wenn man beim VCOUNT min. bis 18 wartet, kann man sehr schön sehen, das es hier mehr Zeilen bedarf bis einfachste Routinen durchgelaufen sind. Willkommen im DMA-Dilemma.

Desweiteren sollten Dinge für die Player-Missiles immer außerhalb der gerade sichtbaren Zeile passieren, sonst kommt es vor, das Du der sichtbaren Zeile hinterher läufst und überhaupt nichts siehst. Oder das die Player-Missiles genau dazwischen liegen, dann kann es zum Versatz der horizontalen Position kommen.
Musik kannst Du einfach mitten drin abspielen. Einfach die Routine aufrufen, die normalerweile im VBI gerufen werden sollte, wenn schon alles andere fertig gezeichnet ist. Läuft Deine Main-Loop syncron, wird es auch die Musik sein.

Refaktorisiere die Routinen und spalte sie auf in Typen wie "die Zeichnen" und "die Rechnen". Rechnen kannst Du auch wenn der Schirm dargestellt wird, Zeichnen aber sollte besser außerhalb gerufen werden.

Noch ein Tipp, falls Dein Programm noch ein Quentchen mehr Zeit braucht. Verzichte auf WSYNC in den Displaylist-Interrupts. Hier sollte man sehen, das die DLIs zur richtigen Zeit ausgelöst werden ggf. die Reihenfolge der LDA/STA anpassen. WSYNC sollte das letzte Mittel bleiben. Und wenn sich auf dem Schirm viel bewegt, stört ein Farbwechsel am Rand wenig, hier hilft dann ein gezieltes NOP.
Den DMA für die PM-Grafik kann man auch im DLI einschalten, wenn man die PM-Grafik braucht und am Ende, wenn die letzte Zeile der PM-Grafik gezeichnet wurde wieder abschalten. Das spart ca. 5 Zyklen pro nicht darzustellender Zeile. Was nicht geht ist den DMA komplett abzuschalten und im DLI dann wieder versuchen einzuschalten, das funktioniert nicht. Da spreche ich aus Erfahrung ;-)
Du kannst auch CRITIC auf 1 setzen und die Dinge die alle im 2. VBI passieren abstrippen und nur was Du wirklich brauchst nachprogrammieren. Aber ich mache das meist nicht. Ist mir zu aufwendig.

Einen Vorteil bringt das obige noch: Dein Programm sollte auch bei 1/60s im NTSC-Mode noch laufen, wenn Du alles richtig gemacht hast. Wenn es jetzt ruckelt, kannst Du das Programm noch weiter optimieren. Die 1/60s NTSC-Jungs werden es Dir danken.

Schönen Abend
Lars

Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von Dr. Irata »

Guten Morgen Lars!
Vielen Dank für die vielen interessanten Anregungen!
Als ich vor ein paar Monaten gestartet bin, war mein Ziel eigentlich Assembler zu lernen, dabei das System mehr kennenzulernen und dabei einen einfachen Shooter nach dem Vorbild Phobos zu schreiben. Eigentlich könnte ich jetzt aufhören und mit meinen gesammelten Erfahrungen was ganz anderes machen, irgendwie möchte ich aber das Projekt zu Ende bringen....
Am Anfang habe ich relativ unbedarft angefangen und drauf los programmiert... ganz ohne VBI und DLI.
Allerdings braucht man den VBI zwingend und die Vorteile des VBI haben mich wohl verleitet zu viel da reinzupacken... in der Hoffnung, daß ich es kann. Es geht auch, aber das. System wird dann instabiler ab ca. 600 Befahle.
Allerdings ist mein Programm mittlerweile ja recht strukturiert!
Ich habe tatsächlich eine relativ einfache Hauptschleife und diese Hauptschleife ruft viele kleine Unterprogramme wiederkehrend auf. Der Code ist auch entsprechend geschachtelt. und aufgebaut, so daß ich den Überblick behalte.
Der VBI ist gar nicht so lang - im VBI mache ich die Joystickabfrage und die ganze PM-Steuerung und Berechnung incl. Kollision. Das wars.
Das Feinscroll mit Grobscroll läuft. im Hauptprogramm. Das geht auch nicht anders, weil ich den Grobscroll so aufgebaut habe, daß er den gesamten Bildschirm um eins nach oben schiebt - für den VBI wäre das zu lang. Die Crux ist leider dabei, daß ich dann Warteschleifen für den Feinscroll brauche und dadurch läuft das Hauptprogramm langsamer als der VBI. Die notwendige Syncronisierung läuft also nicht. Den Grobscroll habe ich so. gemacht, weil ich den Landschaftsaufbau (meine "Letzte Reihe") komprimiert habe und aus Landschaftsdaten quasi berechne - daher kann ich den Grobscroll nicht einfach so über den Atarispeicher bewegen. Ich müsste dafür die DL ständig verändern und anpassen - diese Möglichkeit habe ich erst vor ein paar Tagen kennengelernt. Das mache ich im nächsten Projekt, denn da müsste ich das aktuelle Programm quasi fast völlig neu konstruieren - habe ich probiert mit dem Ergebnis, daß nichst mehr stabil läuft... je mehr ich jetzt grundsätzlich ändere, desto schlechter wird es. Da hilft nur. eine fast komplette Neukonzeption...
Aber alle deine Einwände sind natürlich berechtig und die werde ich beim nächsten Projekt unbedingt berücksichtigen. Hauptprogramm und VBI zu syncronisieren macht absolut Sinn -auch du wirst deine Erfahrungen gesammelt haben ;-)
Und ich muss mich dann auch intensiv mit dem DLI beschöäftigen... !
Liebe Grüße
Peter

Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Interrupt - Programmierung

Beitrag von Dr. Irata »

... so sieht beispielsweise meine Hauptschleife im Moment aus:

Code: Alles auswählen

hauptprogramm
			
			jsr schuesse
			jsr blinken
			jsr letztereihe 		;letzte Reihe (lands) Bildschirm1 printen (sichtbar)	
			jsr feinscroll 			;Feinscroll Bildschirm1 ausführen (sichtbar)		
			mwa #$7530 var1			;var1 auf 30000 ($7530) setzen
			mwa #$7AE4 var2			;var2 auf 31460 ($7AE4) setzen
			jsr grobscroll			;Bildschirm1 kopieren + grobscroll
			mwa #$7b0C var1			;var1 + var2 auf 31500 ($7B0C) setzen
			mwa #$7b0C var2
			jsr umschalten
			jsr incfuelzaehler
			jsr letztereihe			
			jsr feinscroll			;Feinscroll Bildschirm2 ausführen (sichtbar)						
			mwa #$7508 var2			;var1 auf 29960 ($7508) setzen
			mwa #$7b0C var1			;var2 auf 31500 ($7B0C) setzen
			jsr grobscroll			;;Bildschirm2 kopieren + grobscroll
			mwa #$7530 var1			;var1 + var2 auf 30000 ($7530) setzen
			mwa #$7530 var2
			jsr umschalten			;umschalten auf Bildschirm1 - Bildschirm1 wird sichtbar
			jsr kollmissile
			jsr incfuelzaehler
			
			;Ende der Bildschirmausführung / Kontrolle Durchläufe
			sec
			lda #45 	; - 36 = Anzahl der Durchläufe - auf 4 beschränkt, da die Landschaft noch rudimentär ist und sich dann wiederholen soll
			sbc var6+1
			bpl @+
			jmp start1			;Stop hier
@	 	
			jmp hauptprogramm	 			;weiter

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast