home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 10
/
aminetcdnumber101996.iso
/
Aminet
/
dev
/
asm
/
fant_asm.lha
/
listings2
/
Listing6n.s
/
Listing6n.s
Wrap
Text File
|
1995-11-14
|
10KB
|
296 lines
; Listing6n.s HORIZONTALTER SCROLL ÜBER MEHR ALS 16 PIXEL, UNTER
; VERWENDUNG DES BPLCON1 UND DER BITPLANEPOINTERS -
; RECHTE TASTE UM NACH LINKS ZU SCROLLEN
SECTION CIPundCOP,CODE
Anfang:
move.l 4.w,a6 ; Execbase
jsr -$78(a6) ; Disable
lea GfxName(PC),a1 ; Namen der Lib
jsr -$198(a6) ; OpenLibrary
move.l d0,GfxBase ;
move.l d0,a6
move.l $26(a6),OldCop ; speichern die alte COP
; POINTEN AUF UNSERE BITPLANES
MOVE.L #PIC,d0 ; wohin pointen
LEA BPLPOINTERS,A1 ; COP - Pointers
MOVEQ #2,D1 ; Anzahl der Bitplanes -1 (hier sind es 3)
; für den DBRA - Zyklus
POINTBP:
move.w d0,6(a1)
swap d0
move.w d0,2(a1)
swap d0 ;
ADD.L #40*256,d0 ; + Länge Bitplane
addq.w #8,a1
dbra d1,POINTBP
move.l #COPPERLIST,$dff080 ; COP1LC - unsere COP
move.w d0,$dff088 ; COPJMP1 - Starten unsere COP
move.w #0,$dff1fc ; FMODE - Deaktiviert das AGA
move.w #$c00,$dff106 ; BPLCON3 - Deaktiviert das AGA
mouse:
cmpi.b #$ff,$dff006 ; Sind wir auf Zeile 255?
bne.s mouse
btst #2,$dff016 ; Rechte Taste gedrückt?
beq.s GehLinks ; wenn ja, geh nach links!
bsr.w Rechts ; Läßt das Bild rechts scrollen, indem es
; das BPLCON1 und die Pointer verändert
bra.s Warte
GehLinks:
bsr.w Links ; Bewegt Bild nach links
Warte:
cmpi.b #$ff,$dff006 ; Sind wir auf Zeile 255?
beq.s Warte
btst #6,$bfe001 ; linke Maustaste gedrückt?
bne.s mouse
move.l OldCop(PC),$dff080 ; COP1LC - "Zeiger" auf die Orginal-COP
move.w d0,$dff088 ; COPJMP1 - und starten sie
move.l 4.w,a6
jsr -$7e(a6) ; Enable
move.l GfxBase(PC),a1
jsr -$19e(a6) ; Closelibrary
rts
; DATEN
GfxName:
dc.b "graphics.library",0,0
GfxBase:
dc.l 0
OldCop:
dc.l 0
; Diese Routine läßt das Bild nach Rechts scrollen, sie verwendet dazu das
; BPLCON1 und die Bitplanepointers in der Copperlist. MEINBPCON1 ist
; das Byte des BPLCON1.
Rechts:
CMP.B #$ff,MEINBPCON1 ; sind wir bei maximalen Scroll angelangt (15)?
BNE.s CON1ADDA ; wenn nicht, weiter um ein weiteres
LEA BPLPOINTERS,A1 ; Mit diesen 4 Anweisungen holen wir aus der
move.w 2(a1),d0 ; Copperlist die Adresse, wohin das $dff0e0
swap d0 ; gerade pointet und geben diesen Wert
move.w 6(a1),d0 ; in d0
subq.l #2,d0 ; pointet 16 Bit weiter nach hinten, das Bild
; scrollt um 16 Pixel nach Rechts
clr.b MEINBPCON1 ; löscht den Hardwarescroll des BPLCON1 ($dff102)
; denn wir haben 16 Pixel schon mit den Bitplane-
; Pointers "übersprungen", wir müssen wieder bei
; NULL beginnen, um mit dem $dff102 um jeweils
; 1 Pixel nach rechts zu gehen.
LEA BPLPOINTERS,A1 ; Pointer in der COPPERLIST
MOVEQ #2,D1 ; Anzahl der Bitplanes -1 (hier sind es 3)
POINTBP2:
move.w d0,6(a1) ; kopiert das niederw. Word der Adress des Plane
swap d0 ; vertauscht die 2 Word von d0 (z.B.: 1234 > 3412)
move.w d0,2(a1) ; kopiert das höherw. Word der Adresse des Plane
swap d0 ; vertauscht die 2 Word von d0 (3412 > 1234)
ADD.L #40*256,d0 ; + Länge Bitplane -> nächstes Bitplane
addq.w #8,a1 ; zu den nächsten bplpointers in der Cop
dbra d1,POINTBP2 ; Wiederhole D1 Mal POINTBP (D1=num of bitplanes)
rts
CON1ADDA:
add.b #$11,MEINBPCON1 ; scrolle ein Pixel nach vorne
rts
; Routine, die nach Links scrollt, identisch mit der vorherigen:
LINKS:
TST.B MEINBPCON1 ; sind wir bei minimalen Scroll angelangt (00)?
BNE.s CON1SUBBA ; wenn nicht, zurück um ein weiteres
LEA BPLPOINTERS,A1 ; Mit diesen 4 Anweisungen holen wir aus der
move.w 2(a1),d0 ; Copperlist die Adresse, wohin das $dff0e0
swap d0 ; gerade pointet und geben diesen Wert
move.w 6(a1),d0 ; in d0
addq.l #2,d0 ; pointet 16 Bit weiter nach vorne, das Bild
; scrollt um 16 Pixel nach Links
move.b #$FF,MEINBPCON1 ; Hardwarescroll auf 00 (BPLCON1, $dff102)
LEA BPLPOINTERS,A1 ; Pointer in der COPPERLIST
MOVEQ #2,D1 ; Anzahl der Bitplanes -1 (hier sind es 3)
POINTBP3:
move.w d0,6(a1) ; kopiert das niederw. Word der Adress des Plane
swap d0 ; vertauscht die 2 Word von d0 (z.B.: 1234 > 3412)
move.w d0,2(a1) ; kopiert das höherw. Word der Adresse des Plane
swap d0 ; vertauscht die 2 Word von d0 (3412 > 1234)
ADD.L #40*256,d0 ; + Länge Bitplane -> nächstes Bitplane
addq.w #8,a1 ; zu den nächsten bplpointers in der Cop
dbra d1,POINTBP3 ; Wiederhole D1 Mal POINTBP (D1=num of bitplanes)
rts
CON1SUBBA:
sub.b #$11,MEINBPCON1 ; scrolle ein Pixel nach hinten
rts
SECTION GRAPHIC,DATA_C
COPPERLIST:
dc.w $120,$0000,$122,$0000,$124,$0000,$126,$0000,$128,$0000 ; SPRITE
dc.w $12a,$0000,$12c,$0000,$12e,$0000,$130,$0000,$132,$0000
dc.w $134,$0000,$136,$0000,$138,$0000,$13a,$0000,$13c,$0000
dc.w $13e,$0000
dc.w $8E,$2c81 ; DiwStrt (Register mit Normalwerten)
dc.w $90,$2cc1 ; DiwStop
dc.w $92,$0038 ; DdfStart
dc.w $94,$00d0 ; DdfStop
dc.w $102 ; BplCon1
dc.b 0 ; hochwertiges Byte des $dff102, nicht verwendet
MEINBPCON1:
dc.b 0 ; niederwertiges Byte des $dff102, verwendet
dc.w $104,0 ; BplCon2
dc.w $108,0 ; Bpl1Mod
dc.w $10a,0 ; Bpl2Mod
; 5432109876543210
dc.w $100,%0011001000000000 ; Bits 12 +13 an! (3 = %011)
BPLPOINTERS:
dc.w $e0,$0000,$e2,$0000 ;erstes Bitplane
dc.w $e4,$0000,$e6,$0000 ;zweites Bitplane
dc.w $e8,$0000,$ea,$0000 ;drittes Bitplane
dc.w $0180,$000 ; Color0
dc.w $0182,$475 ; Color1
dc.w $0184,$fff ; Color2
dc.w $0186,$ccc ; Color3
dc.w $0188,$999 ; Color4
dc.w $018a,$232 ; Color5
dc.w $018c,$777 ; Color6
dc.w $018e,$444 ; Color7
dc.w $FFFF,$FFFE ; Ende der Copperlist
dcb.b 80*40,0 ; auf NULL gesetzter Speicher vor dem Bitplane
PIC:
incbin "amiga.320*256*3" ; hier laden wir das Bild in RAW
dcb.b 40,0 ; siehe oben
end
Furchtbar, der "Wackelkontakt" beim linken Rand des Monitors, gell?? Ihn
zu eliminieren ist nicht schwierig, einfach zwei Kleinigkeiten
austauschen, schauen wir was und warum: das Warum ist darin zu suchen, daß
die DMA-Kanäle nicht über die Bewegung des Bildes informiert sind und sie
somit unvorbereitet sind, und so nicht die Zeit haben, die ersten 16 Pixel
ganz Links zu lesen. Was können wir dagegen tun? Nichts.
Aber wir können dieses Mißgeschick außerhalb des sichtbaren Feldes
ablaufen lassen, erinnert ihr euch an die Kollegen DIWSTART und DIWSTOP?
Sie bestimmen die Größe des Bildschirmes, auf dem die Daten angezeigt
werden. Es leuchtet ein, daß wenn wir das Videofenster um 16 Pixel weiter
rechts starten lassen, das Problem "zugestopft" wird:
dc.w $8E,$2c91 ; DiwStrt ($81+16=$91)
Tauscht den Wert aus und startet erneut das Listing. Auch wenn wir dieses
Problem beseitigt haben, jetzt tritt ein weiteres auf: wir haben nur mehr
304 Pixel zur Verfügung, und nicht mehr 320. Und dann ist alles auch noch
verschoben!! Aber die Register DDFSTART und DDFSTOP eilen uns zu Hilfe!
Diese Register kümmern sich um die Größe des Videofensters, aber auf
andere Art und Weise. Während das DIWSTART/STOP wie ein schwarzes Stück
Papier ist, dessen rechteckigen Ausschnitt wir in Dimension und Größe
ändern können, wie das Bild unten zeigt,
#####################
#####################
##### #####
##### Bild #####
##### #####
##### #####
##### #####
##### #####
##### #####
#####################
#####################
ist das DDFSTART/STOP anders: damit verändern wir wirklich die Länge einer
Videozeile; wenn wir z.B. den Bildschirm um 16 Pixel verbreitern, und ihn
somit 336 Pixel pro Zeile groß werden lassen, also 42 Bytes pro Zeile
statt 40, dann müssen wir wirklich 42 Bytes pro Zeile verarbeiten. Der
OVERSCAN-MODUS, der über die üblichen 320x256 bzw. 640x256 Pixel
hinausreicht, wird genau mit den DDFSTART und DDFSTOP erreicht, ohne zu
vergessen, das Videofenster mit den DIWSTART und DIWSTOP zu "vergrößern".
Zurück zu unserem Problem: wir müssen zusehen, daß dieser Fehler, der 16
Pixel breit ist, außerhalb unseres Sichtfeldes stattfindet. Wir müssen mit
dem DDFSTART das Bild um 16 Pixel weiter rechts beginnen lassen, und ihn
bei der selben Position enden lassen, und die Werte in DIWSTART/DIWSTOP
gleich lassen. Damit werden wir immer 320x256 Pixel sehen, aber das
Videofenster ist in Wirklichkeit 336 Pixel breit, und der Fehler tritt
außerhalb des Bildschirmes auf. Das Bild wird somit aber 42 Byte breit,
und das müssen wir diese 2 Bytes ( 16 Pixel) für jede Zeile im Programm
ausgleichen.
Wie schaffen wir es, bei Ende der Zeile (jetzt bei Byte 42) um 2 Bytes
zurückzugehen, um die Zeile korrekt anzuzeigen? Kurzum, daß die Rechnung
aufgeht? Indem wie dem Modulo 2 abziehen. In unserem Fall, mit dem Modulo
auf NULL, einfach auf -2 setzen.
Um den Bildschirm 16 Pixel früher starten zu lassen, müssen folgende
Änderungen im DATA FETCH START (DDFSTART) vorgenommen werden:
dc.w $92,$30 ; DDFSTART = $30 (Bildschirm startet
; 16 Pixel früher, er verbreitert sich
; also auf 42 Bytes pro Zeile, 336 Pixel
; Breite, aber das DIWSTART "versteckt"
; diese ersten 16 Pixel mit dem Fehler.
dc.w $108,-2 ; MODULA = -2, wir müssen die ersten
dc.w $10a,-2 ; 16 Pixel "überspringen", indem wir
; sie zwei Mal lesen lassen
Bringt diese Änderungen an und stellt das DIWSTART wieder her:
dc.w $8E,$2c81 ; DiwStrt
Jetzt ist der Scroll PERFEKT. Einzig und allein ist jetzt der Nachteil,
daß mit vergrößern des Videofensters der Sprite7, also der letzte,
verschwindet.
P.S.: Wenn ihr ein bißchen spionieren wollt, was der Fehler außerhalb des
Bildes tut, und ob er noch existiert, lasst das DIWSTART 16 Pixel früher
starten:
dc.w $8E,$2c71 ; DiwStrt
Der ist immer noch da!!!!! Aber jetzt sieht ihn niemand.
Habt ihr gesehen, es war doch ein Kinderspiel, diesen Fehler aus der Welt
zu schaffen. Einfach das DDFSTART um 16 Pixel (bei $30) beginnen lassen
und 2 von den MODULA abziehen.