Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- .286
- w equ word ptr
- b equ byte ptr
- surfclen equ 200 ;maximale L„nge der Oberfl„chendef.
- Punktelen equ 4*100 ;L„nge des Point-Arrays
- anz_fl equ 30 ;maximale Anzahl Fl„chen
- anz_eck equ 10 ;maximale Anzahl Ecken
- data segment ;externe Variablen aus Pascal-Teil
- extrn vz:word ;Gesamt-Tiefe
- extrn rotx:Word ;Rotations-Winkel
- extrn roty:Word
- extrn rotz:word
- extrn worldconst:dataptr ;Array mit Punkten
- extrn surfcconst:dataptr ;Array mit Oberfl„chendefinitionen
- extrn lightsrc:word ;Flag fr Lichtquellenschattierung
- extrn fl_sort:word ;Flag fr Fl„chensortierung
- extrn fl_ruecken:word ;Flag fr Fl„chenrckenunterdrckung
- extrn Texture:Byte ;Flag fr Texturen
- extrn Fuellen:Byte ;Flag fr Fllen / Drahtmodell
- crotx dw 0 ;x-, y- und z-Winkel als Offset auf
- croty dw 0 ;den jeweiligen Sinus-Wert
- crotz dw 0
- rotx_x dw 0 ;x,y,z nach x-rot
- rotx_y dw 0
- rotx_z dw 0
- roty_x dw 0 ;nach y-rot
- roty_y dw 0
- roty_z dw 0
- rotz_x dw 0 ;nach z-rot, endgltig
- rotz_y dw 0
- rotz_z dw 0
- startpoly dw 0 ;Beginn d. Def. der aktuellen Fl„che
- Punkte dw Punktelen dup (0);nimmt fertig berechnete Koordinaten auf
- Punkteptr dw 0 ;Zeiger im Punkte-Array
- Punkte3d dw Punktelen dup (0);nimmt fertige 3d-Koordinaten auf (Textur)
- mittel dw anz_fl*2 dup (0) ;Verzeichnis der mittleren z-Werte
- mittelptr dw 0 ;Zeiger im Mittel-Array
- n dw 0,0,0,0,0,0 ;Normalenvektor 32 Bit
- n_betr dw 0 ;Betrag des Normalenvektors
- extrn sinus:dataptr
- data ends
- extrn drawpol:near ;zeichnet Fl„che als Drahtmodell
- extrn fillpol:near ;fllt Fl„che
- extrn wurzel:near ;berechnet Wurzel von ax
- getdelta macro ;berechnet die beiden Fl„chenvektoren
- mov ax,poly3d[0] ;x: Ursprungsecke
- mov delta2[0],ax ;in delta2 zwischenspeichern
- sub ax,poly3d[8] ;Differenz zum ersten Punkt bilden
- mov delta1[0],ax ;und delta1 fertig
- mov ax,poly3d[2] ;y: Ursprungsecke
- mov delta2[2],ax ;in delta2 zwischenspeichern
- sub ax,poly3d[10d] ;Differenz zum ersten Punkt bilden
- mov delta1[2],ax ;und delta1 fertig
- mov ax,poly3d[4] ;z: Ursprungsecke
- mov delta2[4],ax ;in delta2 zwischenspeichern
- sub ax,poly3d[12d] ;Differenz zum ersten Punkt bilden
- mov delta1[4],ax ;und delta1 fertig
- mov bp,polyn ;letzten Punkt anw„hlen
- dec bp
- shl bp,3 ;jeweils 8 Byte
- mov ax,poly3d[bp] ;x holen
- sub delta2[0],ax ;Differerenz bilden
- mov ax,poly3d[bp+2] ;y holen
- sub delta2[2],ax ;Differerenz bilden
- mov ax,poly3d[bp+4] ;z holen
- sub delta2[4],ax ;Differerenz bilden
- endm
- setkoord macro quelle,offst ;setzt fertig berechnete Screenkoord
- .386
- mov ax,quelle ;Koordinate projizieren
- cwd
- shld dx,ax,7
- shl ax,7
- idiv cx
- add ax,offst ;Bildschirmmitte ist 0/0/0
- mov bx,Punkteptr ;im Punkte-Array vermerken
- mov Punkte[bx],ax
- add Punkteptr,2 ;Array-Zeiger weiter
- endm
- z2cx macro tabofs ;holt z-koordinate nach cx
- mov cx,tabofs + 4
- add cx,vz ;z-translation drauf
- mov bx,mittelptr ;im Mittel-Array vermerken
- add mittel[bx],cx
- endm
- xrot macro zkoord,qkoord ;rotiert qkoord um x, speichert in zkoord
- .386
- mov bp,crotx ;winkel holen
- mov bx,[qkoord]
- shl bx,3 ;x8, um auf Punkte-Eintr„ge zu allignen
- mov Punkteptr,bx
- sub bx,[qkoord] ;insg. x6, um auf Welt-Eintr„ge zu allignen
- sub bx,[qkoord]
- add bx,offset worldconst ;auf Welt setzen
- mov ax,[bx] ;x holen
- mov zkoord,ax ;und unver„ndert setzen
- mov ax,[bx+2] ;y holen
- imul w ds:[bp+60d] ;*cos rotx
- shrd ax,dx,14d
- mov cx,ax ;in cx sichern
- mov ax,[bx+4] ;z holen
- imul w ds:[bp] ;*-sin rotx
- shrd ax,dx,14d
- sub cx,ax
- mov zkoord+2,cx ;y wert fertig und setzen
- mov ax,[bx+2] ;y holen
- imul w ds:[bp] ;*sin rotx
- shrd ax,dx,14d
- mov cx,ax ;sichern in cx
- mov ax,[bx+4] ;z holen
- imul w ds:[bp+60d] ;*cos rotx
- shrd ax,dx,14d
- add cx,ax
- mov zkoord+4,cx
- endm
- yrot macro zkoord,qkoord ;rotiert qkoord um y, speichert in zkoord
- mov bp,croty ;winkel holen
- mov ax,qkoord+2 ;y holen
- mov zkoord+2,ax ;und unver„ndert setzen
- mov ax,qkoord ;x holen
- imul w ds:[bp+60d] ;*cos roty
- shrd ax,dx,14d
- mov cx,ax ;in cx sichern
- mov ax,qkoord+4 ;z holen
- imul w ds:[bp] ;*sin roty
- shrd ax,dx,14d
- add cx,ax
- mov zkoord,cx ;x wert fertig und setzen
- mov ax,qkoord ;x holen
- imul w ds:[bp] ;*-sin roty
- shrd ax,dx,14d
- mov cx,ax ;sichern in cx
- mov ax,qkoord+4 ;z holen
- imul w ds:[bp+60d] ;*cos roty
- shrd ax,dx,14d
- sub ax,cx
- mov zkoord+4,ax
- endm
- zrot macro zkoord,qkoord ;rotiert qkoord um z, speichert in zkoord
- mov bx,Punkteptr ;Eintragung in 3d-Punkte-Array vorbereiten
- mov bp,crotz ;winkel holen
- mov ax,qkoord+4 ;z holen
- mov zkoord+4,ax ;und unver„ndert setzen
- mov Punkte3d[bx+4],ax ;auáerdem im 3D-Array merken
- mov ax,qkoord ;x holen
- imul w ds:[bp+60d] ;*cos rotz
- shrd ax,dx,14d
- mov cx,ax ;in cx sichern
- mov ax,qkoord+2 ;y holen
- imul w ds:[bp] ;*-sin rotz
- shrd ax,dx,14d
- sub cx,ax
- mov zkoord,cx ;x wert fertig und setzen
- mov Punkte3d[bx],cx
- mov ax,qkoord ;x holen
- imul w ds:[bp] ;*sin rotz
- shrd ax,dx,14d
- mov cx,ax ;sichern in cx
- mov ax,qkoord+2 ;y holen
- imul w ds:[bp+60d] ;*cos rotz
- shrd ax,dx,14d
- add cx,ax
- mov zkoord+2,cx
- mov Punkte3d[bx+2],cx
- endm
- get_normal macro ;berechnet Normalenvektor einer Fl„che
- mov ax,delta1[2] ;a2*b3
- imul delta2[4]
- shrd ax,dx,4
- mov n[0],ax
- mov ax,delta1[4] ;a3*b2
- imul delta2[2]
- shrd ax,dx,4
- sub n[0],ax
- mov ax,delta1[4] ;a3*b1
- imul delta2[0]
- shrd ax,dx,4
- mov n[2],ax
- mov ax,delta1[0] ;a1*b3
- imul delta2[4]
- shrd ax,dx,4
- sub n[2],ax
- mov ax,delta1[0] ;a1*b2
- imul delta2[2]
- shrd ax,dx,4
- mov n[4],ax
- mov ax,delta1[2]
- imul delta2[0]
- shrd ax,dx,4
- sub n[4],ax ;Kreuzprodukt (=Normalenvektor) fertig
- mov ax,n[0] ;x1 ^ 2
- imul ax
- mov bx,ax
- mov cx,dx
- mov ax,n[2] ;+x2 ^ 2
- imul ax
- add bx,ax
- adc cx,dx
- mov ax,n[4] ;+x3 ^ 2
- imul ax
- add ax,bx
- adc dx,cx ;Summe in dx:ax
- push si
- call wurzel ;wurzel in ax
- pop si
- mov n_betr,ax ;Betrag des Normalenvektors fertig
- endm
- light macro ;bestimmt Helligkeit einer Fl„che
- mov ax,n[0]
- imul l[0] ;Lichtvektor * Normalenvektor
- mov bx,ax ;in cx:bx Summe bilden
- mov cx,dx
- mov ax,n[2]
- imul l[2]
- add bx,ax
- adc cx,dx
- mov ax,n[4]
- imul l[4]
- add ax,bx ;Skalarprodukt fertig in dx:ax
- adc dx,cx
- idiv l_betr ;durch l_betr divid.
- mov bx,n_betr ;und durch n_betr
- cwd
- shld dx,ax,5 ;Werte von -32 bis +32
- shl ax,5d
- mov bp,startpoly ;Adressierung der Fl„chenfarbe vorbereiten
- idiv bx ;Division durch Nenner
- inc ax
- or ax,ax
- js zugewandt ;wenn cos à positiv -> vom Licht abgewandt
- xor ax,ax ;also keine Beleuchtung
- zugewandt:
- sub b polycol,al ;cos<0 -> auf Grundfarbe addieren
- endm
- code segment
- assume cs:code,ds:data
- public drawworld
- public linecount
- public polycol
- public polyn
- public poly2d
- public poly3d
- linecount dw 0
- polycol dw 3 ;aktuelle Fl„chenfarbe
- polyn dw 0 ;Anzahl tats„chlich vorhandener Ecken
- poly2d dw anz_eck*4 dup (0) ;Ecken des zu zeichnenden Polygons
- poly3d dw anz_eck*4 dup (0) ;3D-Ecken
- public Txt_Nr
- Txt_Nr dw 0 ;Nummer der aktuellen Textur
- public delta1,delta2
- delta1 dw 0,0,0 ;Ebenenvektoren
- delta2 dw 0,0,0
- l dw 11d,11d,11d ;Lichtvektor
- l_betr dw 19d ;Betrag des Lichtvektors
- drawworld proc pascal ;zeichnet dreidimensionale Welt
- push ds
- push es
- push bp
- lea si,surfcconst ;Oberfl„chen werden durch si adressiert
- mov mittelptr,0 ;im Mittel-Array mit 0 anfangen
- mov ax,ds:[rotx] ;Winkel holen,
- shl ax,1 ;als Speicheroffset umrechnen
- add ax,offset sinus
- mov crotx,ax ;und in Hilfsvariablen ablegen
- mov ax,ds:[roty] ;genauso fr y
- shl ax,1
- add ax,offset sinus
- mov croty,ax
- mov ax,ds:[rotz] ;und z
- shl ax,1
- add ax,offset sinus
- mov crotz,ax
- npoly: ;Polygon-Schleife
- mov startpoly,si ;fr sp„tere Verwendung sichern
- add si,2 ;Farbe berspringen
- mov cx,[si] ;Anzahl Ecken holen
- mov linecount,cx ;Z„hler laden
- inc cx ;wegen geschlossener Fl„che
- mov w polyn,cx ;in Punkte-Array eintragen
- add si,2 ;weiter auf eigentliche Koordinaten
- nline:
- xrot rotx_x,si ;koordinaten rotieren um x
- yrot roty_x,rotx_x ;um y
- zrot rotz_x,roty_x ;und um z
- z2cx rotz_x ;z start holen
- setkoord rotz_x,160 ;Koordinaten schreiben
- setkoord rotz_y,100
- add si,2 ;n„chste Eckpunkt
- dec linecount ;Linienz„hler weiter
- je polyok ;alle gezeichnet -> Schluss
- jmp nline ;sonst n„chste Linie
- polyok:
- mov bx,mittelptr ;Mittelwert errechnen:
- mov ax,mittel[bx] ;Summe holen
- mov cx,polyn
- dec cx
- cwd
- div cx ;und durch Anzahl Ecken teilen
- mov mittel[bx],ax ;zurckschreiben
- mov ax,startpoly ;auch "Nummer" der Fl„che schreiben
- mov mittel[bx+2],ax
- add mittelptr,4 ;und weiter
- cmp w [si+2],0 ;alle Polygone fertig ?
- je fertig
- jmp npoly
- fertig:
- cmp b fl_sort,0 ;Fl„chen sortieren ?
- je kein_quicksort
- call quicksort pascal,0,bx ;Feld von 0 bis aktuelle Position sortieren
- kein_quicksort:
- mov mittel[bx+4],0 ;Abschluss setzen
- mov ax,cs ;Zielsegment setzen
- mov es,ax
- xor bx,bx ;mit erster Fl„che beginnen
- npoly_draw:
- lea di,poly2d ;Ziel:Poly-Array
- mov bp,mittel[bx+2] ;Zeiger auf Farbe und Punkte der Fl„che holen
- mov ax,ds:[bp] ;Farbe holen und setzen
- mov polycol,ax
- mov texture,0 ;Annahme: keine Textur
- cmp ah,0ffh ;Textur ?
- jne keine_textur
- mov texture,1 ;ja, dann setzen
- mov b txt_nr,al ;Nummer merken
- keine_textur:
- mov b lightsrc,0 ;Annahme: keine Schattierung
- cmp ah,0feh ;Schattierung ?
- jne keine_Lichtquelle
- mov b lightsrc,1 ;ja, dann setzen
- keine_Lichtquelle:
- add bp,2 ;auf Anzahl positionieren
- mov cx,ds:[bp] ;Anzahl Ecken holen
- mov polyn,cx ;in Poly-Array schreiben
- npoint:
- add bp,2
- mov si,ds:[bp] ;Zeiger auf tats„chl. Punkt holen
- shl si,3 ;3 Word Eintr„ge !
- add si,offset Punkte ;und x/y von Punkte-Array in Poly-Koord.
- mov ax,[si+Punkte3d-Punkte] ;3d-x holen
- mov es:[di+poly3d-poly2d],ax ;3d-x setzen
- mov ax,[si+Punkte3d-Punkte+2] ;3d-y holen
- mov es:[di+poly3d-poly2d+2],ax;3d-y setzen
- mov ax,[si+Punkte3d-Punkte+4] ;3d-z holen
- mov es:[di+poly3d-poly2d+4],ax;3d-z setzen
- movsw ;2D-Koordinaten setzen
- movsw
- add di,4 ;n„chsten Poly2d-Eintrag
- dec cx ;alle Ecken ?
- jne npoint
- mov bp,polyn ;erste Ecke auf letzte kopieren
- shl bp,3 ;auf ersten Punkt positionieren
- neg bp
- mov ax,es:[di+bp] ;und kopieren
- mov es:[di],ax
- mov ax,es:[di+bp+2]
- mov es:[di+2],ax
- add di,poly3d-poly2d ;das gleiche fr 3d-Koordinaten
- mov ax,es:[di+bp] ;und kopieren
- mov es:[di],ax
- mov ax,es:[di+bp+2]
- mov es:[di+2],ax
- mov ax,es:[di+bp+4]
- mov es:[di+4],ax
- cmp fuellen,1 ;Fl„che fllen ?
- jne lines
- getdelta ;ja, dann Delta1 und 2 berechnen
- cmp b lightsrc,0 ;Lichtquelle ?
- jne schattiere
- jmp kein_licht
- schattiere: ;ja,
- push bx
- get_normal ;dann Normalenvektor
- light ;und Helligkeit berechnen
- pop bx
- kein_licht:
- inc polyn ;Anzahl Ecken erh”hen
- call fillpol ;Fl„che zeichnen
- next:
- add bx,4 ;n„chste Fl„che anpeilen
- cmp mittel[bx],0 ;letzte ?
- je _npoly_draw ;nein, dann weiter
- jmp npoly_draw
- lines:
- push bx
- call drawpol ;Polygon zeichnen
- pop bx
- jmp next
- _npoly_draw:
- pop bp ;und fertig
- pop es
- pop ds
- ret
- drawworld endp
- public quicksort
- quicksort proc pascal unten,oben:word
- ;sortiert Mitten-Array nach Quicksort-Algorithmus
- local schluessel:word
- local links:word
- push bx
- mov bx,unten ;Mitte finden
- add bx,oben
- shr bx,1
- and bx,not 3 ;auf 4er Bl”cke posit
- mov dx,mittel[bx] ;Schluessel holen
- mov schluessel,dx
- mov ax,unten ;rechts und links mit Grundwerten init.
- mov si,ax
- mov links,ax
- mov ax,oben
- mov di,ax
- mov dx,schluessel
- links_naeher:
- cmp mittel[si],dx ;grӇer als Schluessel -> weitersuchen
- jbe links_dran
- add si,4 ;auf n„chsten posit
- jmp links_naeher ;und den berprfen
- links_dran:
- cmp mittel[di],dx ;kleiner als Schluessel -> weitersuchen
- jae rechts_dran
- sub di,4 ;auf n„chsten posit
- jmp links_dran ;und den berprfen
- rechts_dran:
- cmp si,di ;links <= rechts ?
- jg end_schl ;nein -> Teilbereich fertig sortiert
- mov eax,dword ptr mittel[si] ;Mittelwerte und Positionen tauschen
- xchg eax,dword ptr mittel[di]
- mov dword ptr mittel[si],eax
- add si,4 ;Zeiger weiterbewegen
- sub di,4
- end_schl:
- cmp si,di ;links > rechts, dann weitermachen
- jle links_naeher
- mov links,si ;links sichern, wg. Rekursion
- cmp unten,di ;unten < rechts -> linken Teilbereich sort.
- jge rechts_fertig
- call quicksort pascal,unten,di;rekursiv h„lften weiter sortieren
- rechts_fertig:
- mov si,links ;oben > links -> rechten Teilbereich sort.
- cmp oben,si
- jle links_fertig
- call quicksort pascal,si,oben ;rekursiv h„lften weiter sortieren
- links_fertig:
- pop bx
- ret
- quicksort endp
- code ends
- end.286
- b equ byte ptr
- w equ word ptr
- data segment
- extrn vpage:word ;aktuelle Bildschirmseite
- data ends
- putpixel macro ;setzt Pixel an ax/bx
- pusha
- xchg ax,bx ;x und y vertauschen
- push ax ;y fr sp„ter sichern
- mov cx,bx ;x holen
- and cx,3 ;Plane maskieren
- mov ax,1 ;und entspr. Bit setzen
- shl ax,cl
- mov ah,2 ;TS Register 2
- xchg ah,al
- mov dx,3c4h
- out dx,ax
- pop cx ;y holen
- mov ax,80d ;Zeilen-Offset berechnen
- mul cx
- shr bx,2 ;Spalten-Offset addieren
- add bx,ax
- add bx,vpage ;auf aktuelle Seite schreiben
- mov b es:[bx],3 ;und Farbe setzen
- popa
- endm
- code segment public
- assume cs:code,ds:data
- public bline
- bline proc near
- ;zieht Linie von ax/bx nach cx/dx
- push bp
- push ax ;x0 und
- push bx ;y0 sichern
- mov bx,4340h ;Selbstmodifikation vorbereiten
- sub cx,ax ;deltax berechnen
- jns deltax_ok ;negativ ?
- neg cx ;ja, dann deltax Vorzeichen umkehren
- mov bl,48h ;und dec ax statt inc ax
- deltax_ok:
- mov bp,sp ;Addressierung von y1 auf dem Stack
- sub dx,ss:[bp] ;deltay berechnen
- jns deltay_ok ;negativ ?
- neg dx ;ja, dann deltay Vorzeichen umkehren
- mov bh,4bh ;und dec bx statt inc bx
- deltay_ok:
- mov si,dx ;deltay und
- or si,cx ;deltax = 0 ?
- jne ok
- add sp,6 ;dann ax, bx und bp vom Stack und Ende
- ret
- ok:
- mov w cs:dist_pos,bx ;dec/inc ax/bx an Ziel schreiben
- cmp cx,dx ;deltax >= deltay ?
- jge deltax_gross
- xchg cx,dx ;nein, dann deltax und deltay tauschen
- mov bl,90h ;und inc ax noppen
- jmp konstanten
- deltax_gross:
- mov bh,90h ;sonst inc bx noppen
- konstanten:
- mov w cs:dist_neg,bx ;dec/inc ax/bx an Ziel schreiben
- shl dx,1 ;Add_2 bestimmen
- mov di,dx ;in di sichern
- sub dx,cx ;Start-Dist bestimmen
- mov bp,dx ;und in bp sichern
- mov si,bp ;Add_1 bestimmen
- sub si,cx ;und in si sichern
- mov ax,0a000h ;VGA-Segment laden
- mov es,ax
- pop bx ;gesicherte Werte fr x0 und y0 zurckholen
- pop ax
- loop_p:
- putpixel ;Punkt setzen
- or bp,bp ;Dist positiv ?
- jns dist_pos
- dist_neg:
- inc ax ;x weiter (evtl Selbstmodifikation)
- inc bx ;y weiter (evtl Selbstmodifikation)
- add bp,di ;Dist aktualisieren
- loop loop_p ;n„chsten Punkt
- jmp fertig ;danach fertig
- dist_pos:
- inc ax ;x weiter (evtl Selbstmodifikation)
- inc bx ;y weiter (evtl Selbstmodifikation)
- add bp,si ;Dist aktualisieren
- loop loop_p ;n„chsten Punkt
- fertig:
- pop bp
- ret
- bline endp
- code ends
- endextrn waitretrace:far
- data segment public
- maxrow dw (?)
- data ends
- code segment public
- public makecopper
- assume cs:code,ds:data
- MakeCopper proc pascal y_pos1,y_pos2,overlay_maske:word
- ; Zeichnet 2 Copperbalken an Positionen y_pos1 (rot) und y_pos2 (gruen)
- ; overlay_maske: 0ff00h : Copper 2 im Vordergrund
- ; 000ffh : Copper 1 im Vordergrund
- ; 00000h : Durchdringung beider Copper
- hoehe equ 88 ;Gesamth”he je Copper
- mov ax,y_pos1 ;maximale y-Koordinate bestimmen
- cmp ax,y_pos2
- ja ax_high
- mov ax,y_pos2
- ax_high:
- add ax,hoehe ;H”he drauf
- mov maxrow,ax ;maximale Zeile, die beachtet werden muá
- xor cx,cx ;Zeilenz„hler mit 0 starten
- call waitretrace ;auf Retrace warten zur Synchronisation
- next_line:
- inc cx ;Zeilenz„hler hochz„hlen
- mov bx,cx ;Farbe 1 berechnen
- sub bx,y_pos1 ;dazu Position relativ zum Copperstart holen
- cmp bx,hoehe/2 -1 ;schon 2. H„lfte ?
- jle copper1_up
- sub bx,hoehe -1 ;dann bx:=127-bx
- neg bx
- copper1_up:
- or bx,bx
- jns copper1_ok ;positiv, dann Farbe
- xor bl,bl
- copper1_ok:
- mov ax,cx ;Farbe 2 berechnen
- sub ax,y_pos2 ;Position relativ berechnen
- cmp ax,hoehe/2 -1 ;2. H„lfte
- jle copper2_up
- sub ax,hoehe -1 ;dann ax:=127-ax
- neg ax
- copper2_up:
- or ax,ax ;positiv, dann Farbe
- jns copper2_ok
- xor al,al
- copper2_ok:
- mov bh,al ;bl hat jetzt Farbe Copper 1 / bh Copper 2
- mov ax,bx ;Overlay berechnen
- and ax,overlay_maske ;Copper 1 oder 2 ausmaskieren
- or al,al ;Copper 1 Vorrang
- je Copper1_hinten
- xor bh,bh ;dann Copper 2 l”schen
- copper1_hinten:
- or ah,ah ;Copper 2 Vorrang
- je Copper2_hinten
- xor bl,bl ;dann Copper 1 l”schen
- copper2_hinten:
- xor al,al ;Farbe 0 im DAC selektieren
- mov dx,3c8h
- out dx,al
- or bl,bl ;wenn Copper 1 schwarz -> lassen
- je bl_0
- add bl,(128-hoehe) / 2 ;sonst aufhellen, um Maximalhelligkeit
- bl_0: ;zu erreichen
- or bh,bh ;fr Copper 2 das Gleiche
- je bh_0
- add bh,(128-hoehe) / 2
- bh_0:
- ;jetzt auf horizontalen Retrace warten und Copper aktivieren
- cli ;Interrupts l”schen, da SEHR zeitkritisch
- mov dx,3dah ;Input Status Register 1 selektieren
- in_retrace:
- in al,dx ;auf Display warten
- test al,1
- jne in_retrace
- in_display:
- in al,dx ;Warten auf (Horizontal-) Retrace
- test al,1
- je in_display
- mov al,bl ;Farbe 1 laden
- mov dx,3c9h ;und setzen
- out dx,al ;Rot-Anteile fr Copper 1 setzen
- mov al,bh
- out dx,al ;Gruen-Anteile fr Copper 2 setzen
- xor al,al
- out dx,al
- cmp cx,maxrow ;letzte Zeile erzeugt ?
- jne next_line
- mov dx,3dah ;ja -> beenden
- wait_hret: ;vor dem Abschalten, unbedingt auf Retrace
- in al,dx ;warten, sonst Flimmern in letzter Zeile
- test al,1
- je wait_hret
- xor al,al ;Farbe 0 im DAC selektieren
- mov dx,3c8h
- out dx,al
- inc dx ;alle auf 0 setzen: schwarz
- out dx,al
- out dx,al
- out dx,al
- sti
- ret
- makecopper endp
- code ends
- end
- data segment public
- extrn colors:word
- data ends
- code segment public
- assume cs:code,ds:data
- public fade_set,fade_ResetPic
- col db 0 ;Codesegment-Pendant zu Colors
- fade_set proc pascal near quelle:dword, start:word, y:word, hoehe:word
- mov ax,colors ;Colors in Code-Segment Variable col eintragen
- mov col,al
- push ds
- mov ax,word ptr Quelle + 2 ;Quellzeiger nach ds:si
- mov ds,ax
- mov si,word ptr Quelle
- mov ax,320 ;Startadresse innerhalb des Quellbilds dazu
- mul start
- add si,ax
- mov ax,0a000h ;Zielzeiger 0a000:0 nach es:di
- mov es,ax
- mov ax,320 ;Startadresse innerhalb des Zielbilds dazu
- mul y
- mov di,ax
- mov ax,320 ;Hoehe in Anzahl Bytes umrechnen
- imul hoehe
- mov cx,ax
- lp: ;Hauptschleife
- lodsb ;Zielwert in al
- mul col ;neuen Farbwert berechnen
- add al,es:[di] ;aktueller Wert in draufaddieren
- add al,col
- stosb ;und zurckschreiben
- dec cx ;alle Punkte kopiert ?
- jne lp
- pop ds
- ret
- fade_set endp
- fade_ResetPic proc pascal far y:word, hoehe:word
- mov ax,0a000h ;VGA-Adresse 0a000:0 nach es:di
- mov es,ax
- mov ax,320 ;Zeile y bercksichtigen
- mul y
- mov di,ax
- mov ax,320 ;Anzahl zu bearbeitender Bytes berechnen
- mul hoehe
- mov cx,ax
- res_lp:
- mov al,es:[di] ;Wert holen
- xor ah,ah ;ah bei Division l”schen !
- div byte ptr colors ;Blocknummer berechnen
- dec al ;Reset-Block rausnehmen
- stosb ;zurckschreiben
- dec cx ;alle Punkte fertig ?
- jne res_lp ;nein, dann weiter
- ret
- fade_ResetPic endp
- code ends
- end
- .286
- clr=256 ;Code fr "Alphabet l”schen"
- eof=257 ;Code fr "Datei-Ende"
- w equ word ptr
- b equ byte ptr
- data segment public
- extrn gifname:dataptr ;Name der Gif-Datei, incl. ".gif" + db 0
- extrn vscreen:dword ;Zeiger auf Zielspeicherbereich
- extrn palette:dataptr ;Zielpalette
- extrn vram_pos:word ;Position innerhalb des Bildschirmspeichers
- extrn rest:word ;Rest, der noch kopiert werden muá
- extrn errornr:word; ;Flag fr Fehler
- handle dw 0 ;DOS-Handle fr Gif-Datei
- Puf db 768 dup (0) ;Puffer der eingelesenen Daten
- PufInd dw 0 ;Zeiger innerhalb dieses Puffers
- abStack db 1281 dup (0) ;Stack, zum Entschlsseln eines Bytes
- ab_prfx dw 4096 dup (0) ;Alphabet, Pr„fix-Teil
- ab_tail dw 4096 dup (0) ;Alphabet, Postfix-Teil
- free dw 0 ;n„chste freie Position im Alphabet
- breite dw 0 ;Anzahl Bit eines Bytes
- max dw 0 ;Maximale Alphabet-L„nge bei akt. Breite
- stackp dw 0 ;Zeiger innerhalb des Alphabet-Stacks
- restbits dw 0 ;Anzahl noch zu lesender Bit
- restbyte dw 0 ;Anzahl noch vorhandener Byte im Puffer
- sonderfall dw 0 ;Zwischenspeicher fr den Sonderfall
- akt_code dw 0 ;gerade bearbeiteter Code
- old_code dw 0 ;vorhergehender Code
- readbyt dw 0 ;gerade gelesenes Byte
- lbyte dw 0 ;zuletzt gelesenes physikalisches Byte
- data ends
- extrn p13_2_modex:far ;wird beim šberlauf ben”tigt
- code segment public
- assume cs:code,ds:data
- public readgif
- GifRead proc pascal n:word
- ;liest n physikalische Bytes aus Datei
- mov ax,03f00h ;Funktion 3fh von Interrupt 21h: Lesen
- mov bx,handle ;Handle laden
- mov cx,n ;Anzahl zu lesender Bytes laden
- lea dx,puf ;Zeiger auf Zielpuffer
- int 21h ;Interrupt ausfhren
- ret
- gifread endp
- GifOpen proc pascal
- ;”ffnet die Gif-Datei zum Lese-Zugriff
- mov ax,03d00h ;Funktion 3dh: ™ffnen
- lea dx,gifname + 1 ;Zeiger auf Namen (L„ngenbyte berspringen)
- int 21h ;ausfhren
- mov handle,ax ;Handle sichern
- ret
- gifopen endp
- GifClose proc pascal
- ;schlieát Gif-Datei
- mov ax,03e00h ;Funktion 3eh: Schlieáen
- mov bx,handle ;Handle laden
- int 21h ;ausfhren
- ret
- gifclose endp
- GifSeek proc pascal Ofs:dword
- ;Positionierung innerhalb der Datei
- mov ax,04200h ;Funktion 42h,
- mov bx,w handle ;Unterfunktion 0: Seek rel. zu Dateianfang
- mov cx,word ptr Ofs + 2 ;Offset laden
- mov dx,word ptr Ofs
- int 21h ;ausfhren
- ret
- Endp
- ShiftPal proc pascal
- ;gleicht das 24-Bit Palettenformat an das 18-Bit VGA-Format an
- mov ax,ds ;Quell- und Zielarrays im Datensegment
- mov es,ax
- mov si,offset Puf ;Lesen aus Datenpuffer
- lea di,palette ;Schreiben in Palette
- mov cx,768d ;786 Byte kopieren
- @l1:
- lodsb ;Byte holen
- shr al,2 ;konvertieren
- stosb ;und schreiben
- loop @l1
- ret
- Endp
- FillPuf proc pascal
- ;liest einen Block aus der Datei in Puf
- call gifread pascal,1 ;ein Byte lesen
- mov al,b puf[0] ;L„nge nach al laden
- xor ah,ah
- mov w restbyte,ax ;und in RestByte sichern
- call gifread pascal, ax ;Bytes lesen
- ret
- Endp
- GetPhysByte proc pascal
- ;holt ein physikalisches Byte aus dem Puffer
- push bx ;bx wird vom Aufrufer ben”tigt
- cmp w restbyte,0 ;keine Daten mehr im Puffer ?
- ja @restda
- pusha ;dann Puffer neu fllen
- call fillpuf
- popa
- mov w pufind,0 ;und Zeiger zurck
- @restda: ;Daten im Puffer
- mov bx,w PufInd ;Puffer-Zeiger laden
- mov al,b Puf[bx] ;Byte holen
- inc w pufind ;Zeiger weiter
- pop bx ;und fertig
- ret
- Endp
- GetLogByte proc pascal
- ;holt ein logisches Byte aus dem Puffer, benutzt GetPhysByte
- push si ;si wird vom Aufrufer ben”tigt
- mov ax,w breite ;Byte-Breite holen
- mov si,ax ;und sichern
- mov dx,w restbits ;lbyte um 8-Restbits nach rechts schieben
- mov cx,8
- sub cx,dx ;dazu Differenz bilden
- mov ax,w lByte
- shr ax,cl ;und shiften
- mov w akt_code,ax ;Code sichern
- sub si,dx ;Restbits bereits geholt -> abziehen
- @nextbyte:
- call getphysbyte ;neues Byte holen
- xor ah,ah
- mov w lByte,ax ;in lByte fr n„chstes logische Byte sichern
- dec w restbyte ;Byte als geholt markieren
- mov bx,1 ;restliche Bits in geholtem Byte maskieren
- mov cx,si ;dazu Anzahl Bits setzen
- shl bx,cl ;1 um Anzahl shiften
- dec bx ;und dekrementieren
- and ax,bx ;Byte maskieren
- mov cx,dx ;auf die richtige Position shiften
- shl ax,cl ;also um Restbits nach links
- add w akt_code,ax ;und zum Ergebnis addieren
- sbb dx,w breite ;Restbits vermindern
- add dx,8 ;um das, was ber 8 Bit hinausgeht
- jns @positiv
- add dx,8
- @positiv:
- sub si,8 ;bis zu 8 Bit geholt -> abziehen
- jle @fertig ;<= 0 -> alles fertig, Ende
- add dx,w breite ;ansonsten Restbits um fehlende Bits erh”hen
- sub dx,8
- jmp @nextbyte ;und weitermachen
- @fertig:
- mov w restbits,dx ;Restbits fr n„chsten Aufruf sichern
- mov ax,w akt_code ;und ax laden
- pop si
- ret
- Endp
- ReadGif proc pascal
- ;L„dt ein Gif-Bild namens gifname in vscreen, šberlauf wird auf Bildschirm
- ;ausgelagert
- push ds ;ds sichern
- call GifOpen ;Datei ”ffnen
- jnc ok ;Fehler ?
- mov errornr,1 ;dann melden und beenden
- pop ds
- ret
- ok:
- call gifseek pascal, 0,13d ;ersten 13 Byte berspringen
- push 768d ;768 Byte der Palette laden
- call gifread
- call shiftpal ;und nach "Palette" konvertieren
- call gifread pascal,1 ;ein Byte berspringen
- @extloop: ;Extension-Blocks berlesen
- cmp w puf[0],21h ;noch ein Extension-Block vorhanden ?
- jne @noext ;nein, dann weiter
- call gifread pascal,2 ;ersten beiden Bytes lesen
- mov al,b puf[1] ;L„nge des Datenblocks
- inc al ;um eins erh”hen
- xor ah,ah
- call gifread pascal, ax ;und berlesen
- jmp @extloop
- @noext:
- call gifread pascal, 10d ;Rest des IDBs lesen
- test b puf[8],128 ;lokale Palette ?
- je @nolok ;nein, dann weiter
- push 768 ;ansonsten lesen
- call gifread
- call shiftpal ;und setzen
- @nolok:
- les di,dword ptr vscreen ;Zieladresse laden
- mov w lbyte,0 ;Letztes gelesenes Byte 0
- mov w free,258 ;erster freier Eintrag 258
- mov w breite,9 ;Byte-Breite 9 Bit
- mov w max,511 ;damit maximaler Eintrag bei 511
- mov w stackp,0 ;Stack-Zeiger auf Beginn
- mov w restbits,0 ;keine Restbits
- mov w restbyte,0 ;oder Restbytes zu holen
- @mainloop: ;fr jedes logische Byte durchlaufen
- call getlogByte ;logisches Byte holen
- cmp ax,eof ;End of File - Kennung
- jne @no_abbruch
- jmp @abbruch ;ja, dann Ende
- @no_abbruch:
- cmp ax,clr ;Clr-Code ?
- jne @no_clear
- jmp @clear ;ja, dann Alphabet l”schen
- @no_clear:
- mov w readbyt,ax ;aktuelles Byte sichern
- cmp ax,w free ;ist Code bereits im Alphabet (<free)
- jb @code_in_ab ;ja, dann ausgeben
- mov ax,w old_code ;nein, dann Sonderfall, also letzen String
- mov w akt_code,ax ;zur Bearbeitung geben
- mov bx,w stackp
- mov cx,w sonderfall ;und erstes Zeichen anh„ngen (immer konkret)
- mov w abstack[bx],cx ;dieses auf Stack eintragen
- inc w stackp ;Stack-Pointer weiter
- @code_in_ab: ;Code im Alphabet vorhanden:
- cmp ax,clr ;< Clr-Code ?
- jb @konkret ;dann konkretes Zeichen
- @fillstack_loop: ;ansonsten entschlsseln
- mov bx,w akt_code ;dazu aktuellen Code als Zeiger im Alphabet
- shl bx,1 ;Word-Array (!)
- push bx
- mov ax,w ab_tail[bx] ;Tail holen, der ist konkret
- mov bx,w stackp ;also auf Stack schieben
- shl bx,1 ;ebenfalls Word-Array
- mov w abstack[bx],ax ;eintragen
- inc w stackp
- pop bx
- mov ax,w ab_prfx[bx] ;Prefix holen
- mov w akt_code,ax ;als aktuellen Code zum Entschlsseln geben
- cmp ax,clr ;> Clr-Code
- ja @fillstack_loop ;dann weiter entschlsseln
- @konkret: ;jetzt nur noch konkrete Werte auf dem Stack
- mov bx,w stackp ;letzten Code auf den Stack schieben
- shl bx,1 ;Word-Array
- mov w abstack[bx],ax
- mov w sonderfall,ax ;auch fr den Sonderfall vermerken
- inc w stackp ;Zeiger weiter
- mov bx,w stackp ;Lesen des Stack vorbereiten
- dec bx ;Zeiger vermindern und
- shl bx,1 ;auf Word-Array ausrichten
- @readstack_loop: ;Stack abarbeiten
- mov ax,w abstack[bx] ;Zeichen vom Stack holen
- stosb ;und in Ziel-Speicher schreiben
- cmp di,0 ;Segment-šberlauf ?
- jne @noovl1
- call p13_2_modex pascal,vram_pos,16384d
- add vram_pos,16384d ;dann Teil in Bildschirmspeicher auslagern
- les di,dword ptr vscreen ;Position im VGA-Ram weiter und Zielzeiger neu
- @noovl1:
- dec bx ;Stack-Pointer auf n„chstes Element
- dec bx
- jns @readstack_loop ;abgearbeitet ? nein, dann weiter
- mov w stackp,0 ;Stackpointer-Variable auf 0
- mov bx,w free ;jetzt in Alphabet eintragen
- shl bx,1 ;dazu auf Position "free" positionieren
- mov ax,w old_code ;letzten Code in Pr„fix schreiben
- mov w ab_prfx[bx],ax
- mov ax,w akt_code ;aktuellen Code in Tail
- mov w ab_tail[bx],ax
- mov ax,w readbyt ;gelesenes Byte als letzten Code sichern
- mov w old_code,ax
- inc w free ;auf n„chste Position innerhalb d. Alphabets
- mov ax,w free
- cmp ax,w max ;bereits Maximum erreicht ?
- ja @no_mainloop
- jmp @mainloop ;nein, dann einfach weitermachen
- @no_mainloop:
- cmp b breite,12 ;Breite bereits 12 Bit ?
- jb @no_mainloop2
- jmp @mainloop ;ja, dann einfach weitermachen
- @no_mainloop2:
- inc w breite ;sonst erh”hen
- mov cl,b breite ;neuen Maximalwert berechnen
- mov ax,1 ;1 um neue Breite nach links schieben
- shl ax,cl
- dec ax ;und dekrementieren
- mov w max,ax ;eintragen
- jmp @mainloop ;und zurck zur Hauptschleife
- @clear: ;Alphabet zurcksetzen:
- mov w breite,9 ;Breite wieder auf Ursprungswert
- mov w max,511 ;Maximum wieder bei 511
- mov w free,258 ;erste freie Position bei 258
- call getlogbyte ;n„chstes Byte holen
- mov w sonderfall,ax ;als Sonderfall vermerken
- mov w old_code,ax ;und auch als zuletzt gelesenen
- stosb ;diesen Wert direkt in Speicher, weil konkret
- cmp di,0 ;Segment-šberlauf ?
- jne @noovl2
- call p13_2_modex pascal,vram_pos,16384d
- add vram_pos,16384d ;dann in Bildschirmspeicher auslagern
- les di,dword ptr vscreen ;VGA-Ram Zeiger weiter und Startadresse neu
- @noovl2:
- jmp @mainloop ;zurck zur Hauptschleife
- @abbruch: ;Abbruch durch Eof-Code
- call gifclose ;Datei schlieáen
- mov rest,di ;Anzahl noch zu kopierender Bytes sichern
- pop ds ;und beenden
- ret
- Endp
- code ends
- end
- .286
- w equ word ptr
- b equ byte ptr
- data segment public
- extrn vscreen:dword
- extrn vpage:word
- extrn palette:dataptr
- data ends
- code segment public
- assume cs:code,ds:data
- public init_modex, p13_2_modex, squeeze, copyscreen, double
- public clrx, split, setpal, getpal, switch, setstart, enter400
- public waitretrace, fade_out, fade_to, copy_block, pal_rot
- switch proc far ;schaltet zw. beiden Bildschirmseiten um
- mov bx,vpage ;Startadresse laden
- mov dx,3d4h
- mov al,0ch ;auf CRTC-Register 0dh/0ch aufteilen
- mov ah,bh
- out dx,ax ;Highbyte setzen (Register 0dh)
- inc al
- mov ah,bl
- out dx,ax ;Lowbyte setzen (Register 0ch)
- cmp bx,16000d ;Startadresse umschalten (0/16000)
- je setze0
- mov vpage,16000
- ret
- setze0:
- mov vpage,0
- ret
- switch endp
- Init_ModeX proc pascal far ;schaltet Mode X ein
- mov ax,0013h ;Mode 13h setzen
- int 10h
- mov dx,3c4h ;Timing Sequenzer
- mov al,4 ;Register 4 (Memory Mode):
- out dx,al ;Bit 3 l”schen -> Chain4 aus
- inc dx
- in al,dx
- and al,0f7h
- or al,4h ;Bit 2 setzen -> Odd/Even Mode aus
- out dx,al
- dec dx
- mov ax,0f02h ;Register 2 (Write Plane Mask):
- out dx,ax ;0fh: alle Planes beim Schreiben ein
- mov ax,0a000h ;Bildschirmspeicher l”schen
- mov es,ax
- xor di,di
- xor ax,ax
- mov cx,0ffffh
- cld
- rep stosw
- mov dx,3d4h ;CRTC
- mov al,14h ;Register 14h (Underline Row Adress):
- out dx,al
- inc dx
- in al,dx ;Bit 6 l”schen -> Doubleword adress. aus
- and al,0bfh
- out dx,al
- dec dx
- mov al,17h ;Register 17h (CRTC Mode):
- out dx,al ;Bit 6 setzen -> Byte Mode ein
- inc dx
- in al,dx
- or al,40h
- out dx,al
- ret
- Endp
- Enter400 proc pascal far ;schaltet von Mode X (200 Zeilen)
- mov dx,3d4h ;in erweieterten 400-Zeilen-Modus
- mov al,9 ;CRTC Register 9 (Maximum Row Adress)
- out dx,al ;selektieren
- inc dx ;Wert auslesen
- in al,dx
- and al,01110000b ;Bit 7 und 3:0 l”schen
- out dx,al ;und zurckschreiben
- ret
- Enter400 endp
- plane_l: db 0
- plane_pos: dw 0
- p13_2_modex proc pascal far start,pic_size:word
- mov dx,03ceh ;Write Mode 0 setzen
- mov ax,4005h ;ber GDC Register 5 (GDC Mode)
- out dx,ax
- mov b plane_l,1 ;Plane-Maske speichern
- push ds
- lds si,dword ptr ds:vscreen ;Quelladresse laden
- mov w plane_pos,si ;und sichern
- mov ax,0a000h ;Zieladresse setzen
- mov es,ax
- mov di,start
- mov cx,pic_size ;Anzahl holen
- @lpplane:
- mov al,02h ;TS Register 2 (Write Plane Mask)
- mov ah,b plane_l ;entsprechende Plane maskieren
- mov dx,3c4h
- out dx,ax
- @lp1:
- movsb ;Byte kopieren
- add si,3 ;auf n„chstes Quellbyte positionieren
- loop @lp1
- mov di,start ;Zieladresse neu holen
- inc w plane_pos ;Quelladresse auf neuen Start
- mov si,w plane_pos
- mov cx,pic_size ;GrӇe holen
- shl b plane_l,1 ;n„chste Plane maskieren
- cmp b plane_l,10h ;alle 4 Planes kopiert ?
- jne @lpplane
- pop ds
- ret
- Endp
- Split proc pascal far row:byte ;Screen-Splitting in Zeile row
- mov bl,row
- xor bh,bh
- shl bx,1 ;*2 wg. Zeilenverdopplung
- mov cx,bx
- mov dx,3d4h ;CRTC
- mov al,07h ;Register 7 (Overflow low)
- out dx,al
- inc dx
- in al,dx
- and al,11101111b ;Bit 4 mit Bit 8 der Zeile laden
- shr cx,4
- and cl,16
- or al,cl
- out dx,al ;und setzen
- dec dx
- mov al,09h ;Register 9 (Maximum Row Adress)
- out dx,al
- inc dx
- in al,dx
- and al,10111111b ;Bit 6 mit Bit 9 der Zeile laden
- shr bl,3
- and bl,64
- or al,bl
- out dx,al ;und setzen
- dec dx
- mov al,18h ;Register 18h (Line Compare/Split Screen)
- mov ah,row ;restlichen 8 Bit setzen
- shl ah,1
- out dx,ax
- ret
- Endp
- SetStart proc pascal far t:word ;setzt Bildschirmstart auf angegebene Adr.
- mov dx,3d4h ;CRTC
- mov al,0ch ;Register 0ch(Linear Starting Adress Middle)
- mov ah,byte ptr t + 1 ;Bits 15:8 setzen
- out dx,ax ;Register 0dh(LSA Low)
- mov al,0dh ;Bits 7:0 setzen
- mov ah,byte ptr t
- out dx,ax
- ret
- Endp
- WaitRetrace proc pascal far
- mov dx,3dah ;Input Status Register 1
- @wait1:
- in al,dx ;Bit 3 wird 0 wenn Strahl beim Bildaufbau
- test al,08h
- jnz @wait1
- @wait2:
- in al,dx ;Bit 3 wird 1 wenn Retrace
- test al,08h
- jz @wait2
- ret ;jetzt ist Strahl ganz unten am Bildschirm
- Endp
- public squeeze
- squeeze proc pascal far ;f„hrt Bildschirm zusammen
- mov si,200*80 ;Start-Wert fr Startadresse
- mov di,199 ;Start-Wert fr Split-Zeile
- sqlp: ;Hauptschleife
- call waitretrace ;auf Retrace warten
- call split pascal, di ;Setzen der unteren H„lfte durch Splitting
- call setstart pascal, si ;Setzen der oberen H„lfte durch Scrolling
- sub si,80 ;eine Zeile weiter, also nach unten fahren
- dec di ;Split eine Zeile runter, also untere
- cmp di,99d ;H„lfte rauffahren
- jae sqlp ;fertig ?
- ret
- squeeze endp
- clrx proc pascal far pmask:byte ;L”scht Mode X - Seiten
- mov al,02h
- mov ah,pmask
- mov dx,3c4h
- out dx,ax
- mov ax,0a000h ;Startadresse und L„nge holen
- mov es,ax
- mov di,vpage
- xor ax,ax
- mov cx,8000
- rep stosw ;und l”schen
- ret
- clrx endp
- copyscreen proc pascal far ziel,quelle:word
- mov dx,3c4h ;alle Planes selektieren
- mov ax,0f02h
- out dx,ax
- mov dx,3ceh ;Write-Mode 1 (kopieren)
- mov ax,4105h
- out dx,ax
- push ds
- mov ax,0a000h ;Quell- und Zielsegment im VGA
- mov es,ax
- mov ds,ax
- mov si,quelle ;Quell- und Zieloffset laden
- mov di,ziel
- mov cx,16000d ;16000 Byte (=64000 Pixel) kopieren
- rep movsb
- pop ds
- mov dx,3ceh ;Write-Mode 0
- mov ax,4005h
- out dx,ax
- ret
- copyscreen endp
- SetPal proc pascal far
- push si
- mov si,offset palette ;Adresse holen
- mov cx,256*3 ;Anzahl Farben holen
- xor al,al
- mov dx,03c8h ;External Palette RAM, Pixel Write Adress
- out dx,al ;ab Farbe 0 setzen
- inc dx ;Pixel Color Value
- rep outsb ;alle Farben an VGA schicken
- pop si
- ret
- Endp
- getpal proc pascal far
- push di
- mov di,offset palette ;Adresse holen
- mov cx,256*3 ;Anzahl Farben holen
- xor al,al
- mov dx,03c7h ;External Palette RAM, Pixel Read Adress
- out dx,al ;ab Farbe 0 lesen
- mov dx,3c9h ;Pixel Color Value
- rep insb ;alle Farben an VGA schicken
- pop di
- ret
- Endp
- double proc pascal far
- mov dx,3d4h ;CRTC Register 13h (Row Offset)
- mov ax,5013h ;auf 80 setzen (doppelte Breite)
- out dx,ax ;und schreiben
- ret
- double endp
- fade_out proc pascal far ;Fadet Bild raus, Video-Modus unabh„ngig
- local groesste:word ;beinhaltet maximal m”glichen Farb-Wert
- mov groesste,63
- mov ax,ds ;Ziel-Segment laden
- mov es,ax
- main_loop: ;Hauptschleife, wird einmal pro Bild durchl.
- lea si,palette ;Quell- und Zieloffset auf Palette
- mov di,si
- mov cx,768 ;768 Byte modifizieren
- lp:
- lodsb ;Wert holen
- dec al ;herunterz„hlen
- jns setzen ;wenn noch nicht negativ -> setzen
- xor al,al ;sonst 0
- setzen:
- stosb ;Zielwert in "Palette" schreiben
- dec cx ;Schleifenz„hler
- jne lp
- call waitretrace ;auf Retrace synchronisieren
- call setpal ;berechnete Palette setzen
- dec groesste ;„uáere Schleife herunter z„hlen
- jne main_loop ;noch nicht fertig ? dann weiter
- ret
- fade_out endp
- fade_to proc pascal far zielpal:dword, laenge:word, schritt:byte
- ;fadet "Palette" auf "Zielpal", šbergabe von Pascal als Array of Byte !
- local groesste:word
- mov ax,63 ;Anzahl Durchl„ufe berechnen, die
- div schritt ;n”tig sind, um 63 zu erreichen
- xor ah,ah
- mov groesste,ax ;Anzahl Schleifendurchl„ufe setzen
- next_frame:
- les di,zielpal ;Offset holen, Pascal bergibt Arrays far !
- lea si,palette ;Offset der "Palette" holen
- mov cx,768 ;768 Bytes bearbeiten
- weiter:
- mov al,[si] ;Wert aus aktueller Palette holen
- mov ah,[di] ;Wert aus Zielpal holen
- mov bl,ah
- sub bl,al ;Differenz zum Zielwert
- cmp bl,schritt ;mehr als ein Schritt drber ?
- jg rauf ;-> runterz„hlen
- neg bl ;Differenz
- cmp bl,schritt ;grӇer als negativer Schritt
- jg runter
- mov al,ah ;Ziel erreicht, endgltig setzen
- schreiben:
- dec cx ;Farb-Schleife runter
- je fertig ;0 ? -> fertig
- mov [si],al ;Wert in Palette schreiben
- inc si ;n„chsten Wert selektieren
- inc di
- jmp weiter ;und weitermachen
- runter:
- sub al,schritt ;herunterz„hlen
- jmp schreiben
- rauf:
- add al,schritt ;heraufz„hlen
- jmp schreiben
- fertig: ;Palette fertig berechnet
- call waitretrace ;Synchronisation
- call setpal ;Palette setzen
- dec groesste ;alle 63 Durchl„ufe fertig ?
- jne next_frame ;nein -> weiter
- ret
- fade_to endp
- copy_block proc pascal far ziel,quelle,breite,hoehe:word
- local sprung:word
- mov dx,3ceh ;GDC
- mov ax,4105h ;ReadMode 0, WriteMode 1
- out dx,ax ;auf Register 5 : GDC Mode
- mov dx,3c4h ;TS
- mov ax,0f02h ;alle Planes einschalten
- out dx,ax ;auf Register 2 : Write Plane Mask
- push ds
- mov ax,0a000h ;Kopieren innerhalb VGA
- mov es,ax ;-> beide Segmente auf 0a000h
- mov ds,ax
- mov si,quelle ;Quelldaten von Quelle
- mov di,ziel ;nach Ziel kopieren
- mov dx,hoehe ;hoehe Zeilen kopieren
- mov ax,80 ;Sprung zwischen zwei Zeilen berechnen
- sub ax,breite ;(= 80-Breite)
- mov sprung,ax
- line_lp:
- mov cx,breite ;Breite laden
- rep movsb ;eine Zeile kopieren
- add si,sprung
- add di,sprung
- dec dx ;Zeilenz„hler weiter
- jne line_lp
- pop ds
- ret
- copy_block endp
- Pal_Rot proc pascal far Start,Ende:Word
- ;rotiert Palettenteil Start bis Ende um 1
- ;wenn Start < Ende : Rotation nach unten
- ;wenn Start > Ende : Rotation nach oben
- mov ax,ds ;es auf Datensegment
- mov es,ax
- lea si,palette ;Palettenoffset laden
- mov di,si ;auch nach di
- mov ax,3 ;"Start" in Palettenoffset umrechnen
- mul start
- add si,ax ;und auf si addieren
- mov ax,3 ;das Gleiche fr Ziel
- mul ende
- add di,ax ;auf di addieren
- mov bx,[si] ;Bytes der Start-Farbe sichern
- mov dl,[si+2]
- mov cx,di ;Differenz zw. Start und Ende ist Anzahl
- sub cx,si ;zu kopierender Bytes
- mov di,si ;Start-Farbe als Ziel-Offset
- add si,3 ;eine Farbe darber als Quell-Offset
- ;fr vorw„rts kopieren bereits fertig
- cld ;Vorgabe: vorw„rts kopieren
- or cx,cx ;wenn cx negativ (Start > Ende)
- jns vorwaerts
- std ;dann rckw„rts kopieren
- neg cx ;cx korrigieren
- sub si,4 ;si auf das 2. Byte der vorletzten Farbe
- add di,2 ;di auf das 2. Byte der letzten Farbe
- add cx,2 ;2 Byte mehr kopieren,
- vorwaerts: ;damit Position nach Kopierschleife stimmt
- rep movsb ;Farben kopieren
- mov [di],bx ;Bytes der alten Start-Farbe
- mov [di+2],dl ;als letzte Farbe schreiben
- cld ;Direction-Flag wieder l”schen
- ret
- Pal_Rot Endp
- code ends
- end
- .286
- w equ word ptr
- b equ byte ptr
- include texture.inc ;Textur-Makros implementieren
- setnewlinel macro ;Hier nur ax und bx verwenden !
- local dylpos,dxlpos,dxlgross,macro_fertig
- mov bx,4043h ;Code fr inc ax (in bh) und inc bx (in bl)
- mov bp,links
- mov ax,poly2d[bp+8] ;Zielkoordinaten sichern
- mov xl1,ax
- mov ax,poly2d[bp+10d]
- mov yl1,ax
- mov ax,poly2d[bp] ;links x/y Start in glob. var
- mov xl0,ax
- sub ax,xl1 ;delta x bilden
- inc xl1 ;fr die Abbruchbedingung
- neg ax ;xl1-xl0
- jns dxlpos ;dxl negativ ?
- neg ax ;dann Betrag bilden
- mov bh,48h ;Code fr dec ax (dec xl0)
- sub xl1,2 ;Erweiterung der Zielkoordinate nach negativ
- dxlpos:
- mov dxl,ax ;und glob. sichern
- mov incflagl,ax ;im Inkrement-Flag sichern
- mov ax,poly2d[bp+2]
- mov yl0,ax
- sub ax,yl1 ;|delta y| bilden
- inc yl1 ;fr die Abbruchbedingung
- neg ax
- jns dylpos ;negativ ?
- neg ax ;dann Betrag bilden
- mov bl,4bh ;Code fr dec bx (dec yl1)
- sub yl1,2 ;Erweiterung der Zielkoordinate nach negativ
- dylpos:
- mov dyl,ax ;und glob. sichern
- cmp dxl,ax ;dx < dy
- jae dxlgross
- neg incflagl ;dann Vorzeichenwechsel fr Inkrement-Flag
- dxlgross:
- mov cs:byte ptr incxl,bh ;Selbstmodifikation durchfhren
- mov cs:byte ptr incyl,bl
- cmp texture,1 ;Texturen ben”tigt ?
- jne macro_fertig ;nein, dann berspringen
- txt_makevarl ;sonst Textur-Variablen berechnen
- macro_fertig:
- mov ax,xl0 ;Register als Laufvariablen verwenden
- mov bx,yl0
- mov si,incflagl
- endm
- setnewliner macro ;Hier nur cx und dx verwenden !
- local dyrpos,dxrpos,dxrgross,macro_fertig
- mov cx,4142h ;Code fr inc cx (in ch) und inc dx (in cl)
- mov bp,rechts
- mov dx,poly2d[bp] ;Zielkoordinaten holen
- mov xr1,dx
- mov dx,poly2d[bp+2]
- mov yr1,dx
- mov dx,poly2d[bp+8] ;rechts x/y in glob. var
- mov xr0,dx
- sub dx,xr1 ;|delta x| bilden
- inc xr1 ;fr die Abbruchbedingung
- neg dx
- jns dxrpos ;negativ ?
- neg dx ;dann Betrag bilden
- mov ch,49h ;Code fr dec cx
- sub xr1,2 ;Erweiterung der Zielkoordinate nach negativ
- dxrpos:
- mov dxr,dx ;in glob. Var sichern
- mov incflagr,dx
- mov dx,poly2d[bp+10d] ;|delta y| bilden
- mov yr0,dx
- sub dx,yr1
- inc yr1 ;fr die Abbruchbedingung
- neg dx
- jns dyrpos ;negativ ?
- neg dx ;dann Betrag bilden
- mov cl,4ah ;Code fr dec dx
- sub yr1,2 ;Erweiterung der Zielkoordinate nach negativ
- dyrpos:
- mov dyr,dx ;und in glob. var sichern
- cmp dxr,dx ;dx < dy ?
- jae dxrgross
- neg incflagr ;dann Vorzeichenwechsel fr Inkrement-Flag
- dxrgross:
- mov cs:byte ptr incxr,ch ;Selbstmodifikation
- mov cs:byte ptr incyr,cl
- cmp texture,1 ;Texturen ben”tigt ?
- jne macro_fertig ;nein, dann berspringen
- txt_makevarr ;sonst Textur-Variablen berechnen
- macro_fertig:
- mov cx,xr0 ;Register laden
- mov dx,yr0
- mov di,incflagr
- endm
- data segment public
- extrn vpage:word ;aktuelle Bildschirmseite
- extrn fl_ruecken ;Flag fr Fl„chenrckenunterdrckung
- extrn glas:Byte; ;Flag fr Glas-Fl„chen
- ;Textur-Variablen:
- extrn Texture:Byte ;Textur ben”tigt ?
- extrn Txt_Daten:DataPtr ;Array mit Zeigern auf Grafikdaten
- extrn Txt_Offs:DataPtr ;Array mit Offsets innerhalb des Textur-Bilds
- extrn Txt_Groesse:DataPtr ;Array mit GrӇenangaben
- d_x dd 0 ;relative x-Koordinate
- d_y dd 0 ;relative y-Koordinate
- D dd 0 ;Hauptdeterminante
- Spalte1 dd 0 ;Komponenten der Hauptdeterminante
- dd 0
- Spalte2 dd 0
- dd 0
- obere_Reihe dw 0 ;welche Koordinaten wurden benutzt ?
- untere_Reihe dw 0
- xl_3d dd 0 ;Laufwerte fr 3d-Koordinaten beim Fllen
- yl_3d dd 0
- zl_3d dd 0
- xr_3d dd 0
- yr_3d dd 0
- zr_3d dd 0
- inc_xl dd 0 ;Werte fr Addition auf Laufwerte
- inc_yl dd 0
- inc_zl dd 0
- inc_xr dd 0
- inc_yr dd 0
- inc_zr dd 0
- ;Variablen fr Fllalghorithmus
- hoch_punkt dw 0 ;w„hrend Suche in dx gehalten
- hoch_y dw 0 ;w„hrend Suche in bx gehalten
- links dw 0 ;Punkt der linken Seite
- rechts dw 0 ;Punkt der rechten Seite
- xl0 dw 0 ;Laufwerte fr linke Start- und Endpunkte
- yl0 dw 0
- xl1 dw 0
- yl1 dw 0
- xr0 dw 0 ;Laufwerte fr rechts
- yr0 dw 0
- xr1 dw 0
- yr1 dw 0
- dxl dw 0 ;Delta X / Y fr beide Seiten
- dyl dw 0
- dxr dw 0
- dyr dw 0
- incflagl dw 0 ;Flags, wann y inkrementiert werden muá
- incflagr dw 0 ;also eine Art "Steigung"
- data ends
- code segment public
- assume cs:code,ds:data
- extrn polycol:word ;Fl„chenfarbe
- extrn polyn:word ;Anzahl Ecken
- extrn poly2d:word ;Array mit 2D-Koordinaten
- extrn poly3d:word ;Array mit 3D-Koordinaten
- extrn delta1,delta2:word ;Ebenenvektoren
- extrn bline:near ;zeichnet Linie
- lambda1 dd 0 ;affine Koordinaten
- lambda2 dd 0
- inc_lambda1 dd 0 ;Schrittweiten
- inc_lambda2 dd 0
- plane dw 0002h ;aktuell zu setzende Plane
- x0 dw 0 ;Koordinaten fr Linie
- y0 dw 0
- x1 dw 0
- zz dw 0 ;noch zu zeichnende Punkte
- extrn Txt_Nr:Word ;Nummer der zu zeichnenden Textur
- public drawpol
- ;zeichnet Drahtmodell der Fl„che in Poly2d
- drawpol proc near
- push es
- pusha
- xor si,si ;Index auf ersten Eintrag
- mov bp,polyn ;Anzahl Ecken holen
- @nline:
- mov ax,poly2d[si] ;Koordinaten aus Tabelle holen
- mov bx,poly2d[si+2]
- mov cx,poly2d[si+8]
- mov dx,poly2d[si+10d]
- push bp
- push si
- call bline ;Linie zeichnen
- pop si
- pop bp
- add si,8 ;n„chste Linie
- dec bp ;Anzahl dekrementieren
- jne @nline
- popa
- pop es
- ret
- drawpol endp
- hline proc near ;zeichnet horiz. Linie ax/bx -> cx/bx
- pusha
- push es
- mov x0,ax ;Koordinaten fr sp„ter sichern
- mov y0,bx
- mov x1,cx
- sub cx,ax ;Anzahl zu zeichnender Punkte berechnen
- jne zzok
- inc cx
- zzok:
- mov zz,cx
- cmp glas,1 ;Glas-Fl„chen ?
- jne Solid1
- push ax ;ja, dann GDC-Modus: OR
- mov dx,3ceh
- mov ax,1003h ;Register 3: Function Select
- out dx,ax
- pop ax
- Solid1:
- mov dx,3c4h ;Timing Sequenzer-Port
- mov di,0a000h
- mov es,di ;VGA-Segment w„hlen
- mov di,ax ;Offset berechnen
- shr di,2 ;(x div 4) + y*80
- add di,vpage ;aktuelle Seite drauf
- mov bx,y0
- imul bx,80d
- add di,bx ;jetzt in di
- cmp zz,4
- jl keine_mitte ;<4 Punkte zeichnen -> keine 4er-Bl”cke
- and ax,11b ;untere beiden Bit sind wichtig
- je mitte ;wenn 0 sofort 4er-Bl”cke setzen
- keine_mitte:
- mov bx,0f02h ;wenn kein_shift, dann diese Maske benutzen
- mov cx,zz ;Anzahl Punkte in Maske setzen
- cmp cx,20h ;ab 20h shiftet der 386 wieder rein !
- jae kein_shift
- mov bx,0102h ;Maske vorbereiten
- shl bh,cl ;Anzahl Punkte=Anzahl zu setzender Bits
- dec bh
- and bh,0fh
- kein_shift:
- mov cx,ax ;je nach Startplane richtig schieben
- and cl,3
- shl bh,cl
- mov ax,bx ;und Maske fertig
- sub zz,4 ;zu zeichnende Punkte runterzaehlen
- add zz,cx
- start:
- out dx,ax ;berechnete Schreibmaske setzen
- mov al,b polycol ;Farbe holen
- mov ah,es:[di] ;Latches laden, nur fr Glas-K”rper
- stosb ;setzen
- mitte:
- cmp zz,4
- jl schluss ;wenn kein 4er Block mehr -> Abschluss
- mov ax,0f02h ;alle Planes selektieren
- out dx,ax ;(zz div 4) 4er Bl”cker setzen
- mov cx,zz
- shr cx,2
- mov al,b polycol
- cmp glas,1 ;Glas-K”rper ?
- jne Solid
- @lp:
- mov ah,es:[di] ;Latches laden, nur fr Glas-K”rper
- stosb ;und zurckschreiben
- dec cx
- jne @lp
- jmp schluss
- Solid:
- rep stosb ;Mittelteil zeichnen
- schluss:
- mov cx,x1 ;šbrige Pixel setzen
- and cx,3h
- dec zz
- js hline_fertig ;wenn nichts mehr da -> Ende
- mov ax,0102h
- shl ah,cl ;Maske erstellen
- dec ah
- out dx,ax
- mov al,b polycol ;Farbe holen
- mov ah,es:[di] ;Latches laden, nur fr Glas-K”rper
- stosb ;und Punkte zeichnen
- hline_fertig:
- mov dx,3ceh ;GDC-Mode wieder auf MOVE
- mov ax,0003h
- out dx,ax
- pop es
- popa
- ret
- hline endp
- txt_hline ;Macro enth„lt die Prozedur "hline_texture"
- public fillpol
- fillpol proc near ;fllt Polygon in Mode X
- push bp
- pusha
- cmp texture,1 ;werden Texturen benutzt ?
- jne Fllen ;nein, dann einfach fllen
- txt_Hauptdet ;sonst Hauptdeterminante berechnen
- Fllen:
- xor si,si ;Suche nach h”chstem Punkt,ersten Eintrag sel.
- mov cx,polyn ;Anzahl Ecken
- sub cx,2
- mov bx,0ffffh ;extrem hoher Wert, auf jeden Fall unterboten
- npoint:
- mov ax,poly2d[si+2] ;y holen
- cmp ax,bx ;wenn bisheriges Minimum unterboten
- ja no_min
- mov bx,ax ;neues Minimum festhalten
- mov dx,si
- no_min:
- add si,8
- dec cx ;n„chste Ecke, wenn nicht 0ffffh
- jns npoint
- mov hoch_punkt,dx ;in glob var festhalten
- mov hoch_y,bx ;Hochpunkt-Suche abgeschlossen
- or dx,dx ;links = 0 ?
- jne dec_valid
- mov bx,polyn ;ja: rechts ans andere Ende
- sub bx,2
- shl bx,3
- jmp lr_fertig ;positionieren
- dec_valid:
- mov bx,dx ;ansonsten einen davor
- sub bx,8
- lr_fertig:
- mov links,dx ;in glob var festhalten
- mov rechts,bx
- ; ax/bx : Startkoordinaten links (xl0/yl0)
- ; cx/dx : Startkoordinaten rechts (xr0/yr0)
- ; si : šberlaufflag links
- ; di : šberlaufflag rechts
- ; bp : Zeiger auf aktuellen Punkt
- setnewlinel ;Linienvariablen laden
- setnewliner
- schleifel:
- cmp ax,xl1
- je neue_liniel ;wenn Ende erreicht -> neue Linie setzen
- cmp bx,yl1
- je neue_liniel ;sonst weiterzeichnen
- or si,si ;Inkrement-Flag <= 0
- jg flaglgross
- incyl: ;Diese Stelle wird gepatcht !
- inc bx ;y weiter
- add si,dxl ;IncFlag weitersetzen
- txt_incl ;auch 3D-Koordinaten weiter
- cmp bx,yl1 ;Ziel erreicht ?
- je neue_liniel ;dann neue Linie
- jmp links_erh”ht ;Links wurde y erh”ht -> jetzt rechts
- flaglgross:
- sub si,dyl ;Inkflag runterz„hlen
- incxl: ;Diese Stelle wird gepatcht !
- inc ax ;x weiter
- jmp schleifel
- fertig__:
- jmp fertig
- neue_liniel:
- mov bx,links ;Erh”hung vorbereiten
- cmp bx,rechts
- je fertig__ ;gleich, dann fertig
- add bx,8 ;links weiter
- mov ax,polyn ;Ist Links am Ende der Liste ?
- shl ax,3
- sub ax,8 ;Ende bestimmt
- cmp bx,ax ;Vergleich
- jb links_setzen
- xor bx,bx ;wenn ja, dann auf 0 setzen
- links_setzen:
- mov links,bx
- setnewlinel ;Variablen neu laden
- jmp schleifel
- fertig_:
- jmp fertig
- links_erh”ht:
- schleifer:
- cmp cx,xr1
- je neue_linier ;wenn Ende erreicht -> neue Linie setzen
- cmp dx,yr1
- je neue_linier ;sonst weiterzeichnen
- or di,di ;Inkrement-Flag <= 0
- jg flagrgross
- incyr: ;Diese Stelle wird gepatcht !
- inc dx ;y weiter
- add di,dxr ;IncFlag weitersetzen
- txt_incr
- cmp dx,yr1 ;Ziel erreicht ?
- je neue_linier ;dann neue Linie
- jmp rechts_erh”ht ;Rechts wurde y erh”ht -> jetzt Linie ziehen
- flagrgross:
- sub di,dyr ;Inkflag runterz„hlen
- incxr:
- inc cx ;Diese Stelle wird gepatcht !
- jmp schleifer
- neue_linier:
- mov dx,rechts ;Verminderung vorbereiten
- cmp dx,links
- je fertig_ ;wenn gleich, dann fertig
- sub dx,8 ;Wenn vorher auf 0->ans andere Ende setzen
- jns rechts_setzen
- mov dx,polyn
- sub dx,2
- shl dx,3 ;auf Ende positioniert
- rechts_setzen:
- mov rechts,dx
- setnewliner ;Variablen neu laden
- jmp schleifer
- rechts_erh”ht:
- push ax
- push cx
- cmp cx,ax ;richtige Reihenfolge ?
- jae direct_ok ;dann ok, sonst:
- cmp w fl_ruecken,0 ;Fl„chenrcken unterdrcken ?
- je zeichnen ;nein, dann dennoch zeichnen
- pop cx
- pop ax
- jmp fertig ;Polygon wird nicht gezeichnet
- zeichnen:
- xchg ax,cx ;Koordinaten in richtige Reihenfolge
- direct_ok:
- cmp texture,1 ;Texturen verwenden ?
- jne norm_fuellen ;nein, dann normal fllen
- call hline_texture ;horizontale Textur-Linie zeichnen
- pop cx
- pop ax
- jmp schleifel ;und weiter
- norm_fuellen:
- call hline ;horizontale Linie zeichnen
- pop cx
- pop ax
- jmp schleifel ;und weitermachen
- fertig:
- popa
- pop bp
- ret
- fillpol endp
- code ends
- enddata segment
- extrn vscreen:dword ;Zeiger auf Landschaftsdaten
- extrn x,y: word ;Koordinaten des Trapez
- extrn vpage:word ;aktuelle Bildschirmseite
- data ends
- code segment
- assume cs:code,ds:data
- ;Variablen mit Nachkommateil (untere 8 Bit):
- offst dd 0 ;aktueller Offset
- step dd 0 ;PixelgrӇe
- row_start dd 0 ;Beginn der aktuellen Zeile
- row_step dd 0 ;Abstand zur n„chsten Zeile
- z_count dw 0 ;Z„hler fr die Tiefe
- shrink dw 0 ;Korrektur am unteren Bildschirmrand
- Zeile dd 0 ;aktuelle Bildschirm-Zeilennummer
- vpage_cs dw 0 ;Bildschirmseite im Code-Segment
- .386
- public Draw_Voxel
- Draw_Voxel proc pascal
- ;stellt Landschaft auf aktueller Bildschirmseite dar
- ;liest Daten aus vscreen ab Position (x/y)
- mov ax,vpage ;Nummer der Bildschirmseite merken
- mov vpage_cs,ax
- push ds
- mov ax,0a000h ;Zielsegment laden
- mov es,ax
- mov ax,320 ;Offset in Landschaft berechnen
- imul y
- add ax,x
- lds si,vscreen ;Daten aus vscreen entnehmen
- add si,ax ;Offset dazu
- shl esi,8 ;in Festkommazahl umwandeln
- mov offst,esi ;Startwerte fr Pixel ...
- mov row_start,esi ;... und Zeile
- mov step,100h ;zun„chst Skalierungs-Faktor 1
- mov Zeile,100*256 ;in Bildschirmzeile 100 beginnen
- mov row_step,14040h ;Abstand der Zeilen 320,25
- mov shrink,0 ;zun„chst keine Korrektur
- mov z_count,160 ;Anzahl zu berechnender Zeilen
- next_y:
- mov eax,Zeile ;aktuelle (Bildschirm-) Zeilennummer holen
- mov ebx,eax ;sichern
- shr eax,8 ;in ganze Zahl umwandeln
- add eax,50 ;50 Pixel nach unten
- imul eax,80 ;in Offset umrechnen
- mov di,ax ;als Zielzeiger sichern
- cmp di,199*80 ;Bildschirmrand berschritten ?
- jb normal
- mov di,199*80 ;ja, dann auf letzte Zeile positionieren
- mov eax,Zeile ;Differenz zum unteren Bildschirmrand
- shr eax,8
- sub eax,149
- mov shrink,ax ;und als Korrektur merken
- normal:
- add di,vpage_cs ;aktuelle Bildschirmseite dazu
- imul ebx,16500 ;Zeilennummer mit 1.007 multiplizieren
- shr ebx,14 ;dazu * 16500 / 16384 rechnen
- mov Zeile,ebx ;und sichern
- mov bp,80 ;Anzahl Pixel pro Zeile
- next_x:
- mov esi,offst ;aktuellen Pixel-Offset laden
- shr esi,8 ;in ganze Zahl wandeln
- xor eax,eax
- mov al,[si] ;Punkt aus Landschaft laden
- mov cx,ax ;sichern
- cmp cx,99 ;Farbe (=H”he) < 100
- ja fill_bar
- mov ax,99 ;dann auf 99 setzen
- fill_bar:
- shl ax,5 ;Fluchtpunkt-Projektion: H”he * 32
- xor dx,dx
- push bp
- mov bp,z_count ;dividiert durch die Entfernung
- add bp,50
- idiv bp
- pop bp
- sub ax,shrink ;Korrektur durchfhren
- jbe weiter ;wenn <= 0, gar nicht zeichnen
- push di
- next_fill:
- mov es:[di],cl ;Farbe eintragen
- sub di,80 ;n„chsth”here Zeile ansprechen
- dec al ;Z„hler verringern
- jne next_fill ;weitermachen ?
- pop di
- weiter:
- inc di ;n„chstes Byte auf dem Bildschirm ansprechen
- mov esi,step ;Schrittweite holen
- add esi,offst ;aufaddieren
- mov offst,esi ;und zurckschreiben
- dec bp ;n„chsten Punkt
- jne next_x
- mov esi,row_step ;Start der Zeile verschieben
- add esi,row_start
- mov row_start,esi
- mov offst,esi ;auch Pixel-Offset neu laden
- dec step ;Skalierungsfaktor herunterz„hlen
- dec z_count ;Zeilenz„hler weiter
- jne next_y
- pop ds
- ret
- Draw_Voxel endp
- code ends
- end
- extrn WaitRetrace:far
- data segment public
- extrn sinus:dataptr ;Sinustabelle
- data ends
- code segment public
- assume cs:code,ds:data
- public make_wob
- make_wob proc pascal wob_pos,wob_hoehe,wob_offset:word
- xor cx,cx ;Zeilenz„hler auf 0
- call waitretrace ;Synchronisation mit Kathodenstrahl
- next_line:
- inc cx ;Zeilenz„hler hoch
- mov bx,cx ;Position innerhalb des Wobblers bestimmen
- sub bx,wob_pos
- mov si,bx ;merken fr Schluá
- add bx,wob_offset ;Offset drauf fr Bewegung
- and bx,63 ;nur Werte von 0..63 erlauben (ArraygrӇe)
- shl bx,1 ;Arrayzugriff auf Words
- mov bx,sinus[bx] ;Wert holen in bx
- cli ;Interrupts l”schen, da SEHR zeitkritisch
- mov dx,3dah ;Input Status Register 1 selektieren
- in_display:
- in al,dx ;Warten auf (Horizontal-) Retrace
- test al,1
- je in_display
- in_retrace:
- in al,dx ;auf Display warten
- test al,1
- jne in_retrace
- cmp cx,wob_pos ;gewnschte Zeile erreicht ?
- jb next_line ;nein -> Standarwert setzen
- mov dx,3d4h ;CRTC-Register 4 (Horizontal Sync Start)
- mov al,4 ;selektieren
- mov ah,bl ;Sinus-Wert holen
- out dx,ax ;und eintragen
- cmp si,wob_hoehe ;Ende erreicht ?
- jb next_line
- mov dx,3dah
- warten:
- in al,dx ;Warten auf (Horizontal-) Retrace
- test al,1
- jne warten
- mov dx,3d4h ;Sync Start wieder normal setzen
- mov ax,5504h
- out dx,ax
- sti ;Interrupts wieder zulassen
- ret
- make_wob endp
- code ends
- end
- Uses Crt,ModeXLib,var_3d;
- Const
- worldlen=8*3; {Punkte-Array}
- Worldconst:Array[0..worldlen-1] of Integer =
- (-200,-200,-200,
- -200,-200,200,
- -200,200,-200,
- -200,200,200,
- 200,-200,-200,
- 200,-200,200,
- 200,200,-200,
- 200,200,200);
- surfclen=38; {Fl„chen-Array}
- surfcconst:Array[0..surfclen-1] of Word=
- (0,4, 0,2,6,4,
- 0,4, 0,1,3,2,
- 0,4, 4,6,7,5,
- 0,4, 1,5,7,3,
- 0,4, 2,3,7,6,
- 0,4, 0,4,5,1,0,0);
- Var
- i,j:Word;
- procedure drawworld;external; {zeichnet die Welt auf akt. Bildschirmseite}
- {$l 3dasm.obj}
- {$l poly.obj}
- {$l bres.obj}
- {$l wurzel.obj}
- Begin
- vz:=1000; {K”rper befindet sich bei 1000 Einh. Tiefe}
- vpage:=0; {mit Seite 0 beginnen}
- init_modex; {ModeX einschalten}
- rotx:=0; {Startwerte fr Rotation}
- roty:=0;
- rotz:=0;
- Fuellen:=false; {Fl„chenfllen aus}
- fl_sort:=false; {Fl„chensortierung aus}
- fl_ruecken:=false; {Fl„chenrckeunterdrckung aus}
- Glas:=false; {Glas-Oberfl„chen aus}
- repeat
- clrx($0f); {Bildschirm l”schen}
- DrawWorld; {Welt zeichnen}
- switch; {auf fertiges Bild schalten}
- WaitRetrace; {n„chsten Retrace abwarten}
- Inc(rotx); {weiterrotieren ... }
- If rotx=120 Then rotx:=0;
- Inc(rotz);
- If rotz=120 Then rotz:=0;
- inc(roty);
- if roty=120 Then roty:=0;
- Until KeyPressed; { ... bis Taste}
- TextMode(3);
- End.
- Uses Crt,ModeXLib,var_3d;
- Const
- worldlen=8*3; {Punkte-Array}
- Worldconst:Array[0..worldlen-1] of Integer =
- (-200,-200,-200,
- -200,-200,200,
- -200,200,-200,
- -200,200,200,
- 200,-200,-200,
- 200,-200,200,
- 200,200,-200,
- 200,200,200);
- surfclen=38; {Fl„chen-Array}
- surfcconst:Array[0..surfclen-1] of Word=
- (01,4, 0,2,6,4,
- 02,4, 0,1,3,2,
- 04,4, 4,6,7,5,
- 08,4, 1,5,7,3,
- 16,4, 2,3,7,6,
- 32,4, 0,4,5,1,0,0);
- Var
- i,j:Word;
- Procedure Glas_Pal;
- {bereitet die Palette auf Glas-K”rper vor}
- Begin
- FillChar(Palette[3],765,63); {zun„chst alle Farben weiá}
- For i:=1 to 255 do Begin {255 Mischfarben bestimmen}
- If i and 1 = 1 Then Dec(Palette[i*3],16);
- If i and 2 = 2 Then Dec(Palette[i*3+1],16);
- If i and 4 = 4 Then Dec(Palette[i*3+2],16);
- If i and 8 = 8 Then Begin
- Dec(Palette[i*3],16);
- Dec(Palette[i*3+1],16);
- End;
- If i and 16 = 16 Then Begin
- Dec(Palette[i*3],16);
- Dec(Palette[i*3+2],16);
- End;
- If i and 32 = 32 Then Begin
- Dec(Palette[i*3+1],16);
- Dec(Palette[i*3+2],16);
- End;
- End;
- SetPal;
- End;
- procedure drawworld;external; {zeichnet die Welt auf akt. Bildschirmseite}
- {$l 3dasm.obj}
- {$l poly.obj}
- {$l bres.obj}
- {$l wurzel.obj}
- Begin
- vz:=1000; {K”rper befindet sich bei 1000 Einh. Tiefe}
- vpage:=0; {mit Seite 0 beginnen}
- init_modex; {ModeX einschalten}
- Glas_Pal;
- rotx:=0; {Startwerte fr Rotation}
- roty:=0;
- rotz:=0;
- Fuellen:=true; {Fl„chenfllen ein}
- fl_sort:=false; {Fl„chensortierung aus}
- fl_ruecken:=false; {Fl„chenrckeunterdrckung aus}
- Glas:=true; {Glas-Oberfl„chen ein}
- repeat
- clrx($0f); {Bildschirm l”schen}
- DrawWorld; {Welt zeichnen}
- switch; {auf fertiges Bild schalten}
- WaitRetrace; {n„chsten Retrace abwarten}
- Inc(rotx); {weiterrotieren ... }
- If rotx=120 Then rotx:=0;
- Inc(rotz);
- If rotz=120 Then rotz:=0;
- inc(roty);
- if roty=120 Then roty:=0;
- Until KeyPressed; { ... bis Taste}
- TextMode(3);
- End.
- Uses Crt,ModeXLib,Gif,var_3d;
- Const
- worldlen=8*3; {Punkte-Array}
- Worldconst:Array[0..worldlen-1] of Integer =
- (-200,-200,-200,
- -200,-200,200,
- -200,200,-200,
- -200,200,200,
- 200,-200,-200,
- 200,-200,200,
- 200,200,-200,
- 200,200,200);
- surfclen=38; {Fl„chen-Array}
- surfcconst:Array[0..surfclen-1] of Word=
- ($fee0,4, 0,2,6,4,
- $fec0,4, 0,1,3,2,
- $fec0,4, 4,6,7,5,
- $fee0,4, 1,5,7,3,
- $fec0,4, 2,3,7,6,
- $fec0,4, 0,4,5,1,0,0);
- { $fe = Lichtquelle benutzen, Grundfarbe im Low-Byte}
- Var
- i,j:Word;
- Procedure Schatt_Pal; {Palette auf Schattierung vorbereiten}
- Begin
- For j:=192 to 223 do Begin {Farben 192 - 223 und 224 - 255 vorbereiten}
- i:=trunc((j/32)*43); {Helligkeit ermitteln}
- Fillchar(Palette[j*3],3,i+20); {Farben 192-223 auf Grauwerte}
- Palette[(j+32)*3]:=i+20; {Farben 224-255 auf Rotwerte}
- Palette[(j+32)*3+1]:=0;
- Palette[(j+32)*3+2]:=0;
- End;
- Setpal; {Diese Palette setzen}
- End;
- procedure drawworld;external; {zeichnet die Welt auf akt. Bildschirmseite}
- {$l 3dasm.obj}
- {$l poly.obj}
- {$l bres.obj}
- {$l wurzel.obj}
- Begin
- vz:=1000; {K”rper befindet sich bei 1000 Einh. Tiefe}
- vpage:=0; {mit Seite 0 beginnen}
- LoadGif('logor.gif'); {Hintergrundbild laden}
- init_modex; {ModeX einschalten}
- Schatt_Pal; {Schattier-Palette berechnen}
- rotx:=0; {Startwerte fr Rotation}
- roty:=0;
- rotz:=0;
- Fuellen:=true; {Fl„chenfllen ein}
- fl_sort:=true; {Fl„chensortierung ein}
- fl_ruecken:=true; {Fl„chenrckeunterdrckung ein}
- Glas:=false; {Glas-Oberfl„chen aus}
- p13_2_modex(16000*2,16000); {Hintergrund auf VGA-Seite 2}
- repeat
- CopyScreen(vpage,16000*2); {Hintergrundbild auf aktuelle Seite}
- DrawWorld; {Welt zeichnen}
- switch; {auf fertiges Bild schalten}
- WaitRetrace; {n„chsten Retrace abwarten}
- Inc(rotx); {weiterrotieren ... }
- If rotx=120 Then rotx:=0;
- Inc(rotz);
- If rotz=120 Then rotz:=0;
- inc(roty);
- if roty=120 Then roty:=0;
- Until KeyPressed; { ... bis Taste}
- TextMode(3);
- End.
- Uses Crt,ModeXLib,var_3d;
- Const
- worldlen=8*3; {Punkte-Array}
- Worldconst:Array[0..worldlen-1] of Integer =
- (-200,-200,-200,
- -200,-200,200,
- -200,200,-200,
- -200,200,200,
- 200,-200,-200,
- 200,-200,200,
- 200,200,-200,
- 200,200,200);
- surfclen=38; {Fl„chen-Array}
- surfcconst:Array[0..surfclen-1] of Word=
- (01,4, 0,2,6,4,
- 02,4, 0,1,3,2,
- 03,4, 4,6,7,5,
- 04,4, 1,5,7,3,
- 05,4, 2,3,7,6,
- 06,4, 0,4,5,1,0,0);
- Var
- i,j:Word;
- procedure drawworld;external; {zeichnet die Welt auf akt. Bildschirmseite}
- {$l 3dasm.obj}
- {$l poly.obj}
- {$l bres.obj}
- {$l wurzel.obj}
- Begin
- vz:=1000; {K”rper befindet sich bei 1000 Einh. Tiefe}
- vpage:=0; {mit Seite 0 beginnen}
- init_modex; {ModeX einschalten}
- rotx:=0; {Startwerte fr Rotation}
- roty:=0;
- rotz:=0;
- Fuellen:=true; {Fl„chenfllen ein}
- fl_sort:=true; {Fl„chensortierung ein}
- fl_ruecken:=true; {Fl„chenrckeunterdrckung ein}
- Glas:=false; {Glas-Oberfl„chen aus}
- repeat
- clrx($0f); {Bildschirm l”schen}
- DrawWorld; {Welt zeichnen}
- switch; {auf fertiges Bild schalten}
- WaitRetrace; {n„chsten Retrace abwarten}
- Inc(rotx); {weiterrotieren ... }
- If rotx=120 Then rotx:=0;
- Inc(rotz);
- If rotz=120 Then rotz:=0;
- inc(roty);
- if roty=120 Then roty:=0;
- Until KeyPressed; { ... bis Taste}
- TextMode(3);
- End.
- Uses Crt,ModeXLib,Gif,var_3d;
- Const
- worldlen=8*3; {Punkte-Array}
- Worldconst:Array[0..worldlen-1] of Integer =
- (-200,-200,-200,
- -200,-200,200,
- -200,200,-200,
- -200,200,200,
- 200,-200,-200,
- 200,-200,200,
- 200,200,-200,
- 200,200,200);
- surfclen=38; {Fl„chen-Array}
- surfcconst:Array[0..surfclen-1] of Word=
- ($ff00,4, 0,2,6,4,
- $ff01,4, 0,1,3,2,
- $ff02,4, 4,6,7,5,
- $ff00,4, 1,5,7,3,
- $ff03,4, 2,3,7,6,
- $ff04,4, 0,4,5,1,0,0);
- { $ff = Texturen benutzen, Nummer im Low-Byte}
- Var
- i,j:Word;
- Procedure Prep_Texturen;
- {Variablen der Texturen laden}
- Begin
- LoadGif('Textur'); {Textur-Bild laden}
- GetMem(Txt_Pic,64000); {Speicher dafr holen}
- Move(VScreen^,Txt_Pic^,64000);{und dorthin kopieren}
- For i:=0 to Txt_Anzahl-1 do Begin
- Txt_Daten[i]:=Txt_Pic; {Zeiger auf Daten laden}
- Txt_Offs[i]:=i*64; {Offset bestimmen}
- End;
- End;
- procedure drawworld;external; {zeichnet die Welt auf akt. Bildschirmseite}
- {$l 3dasm.obj}
- {$l poly.obj}
- {$l bres.obj}
- {$l wurzel.obj}
- Begin
- vz:=1000; {K”rper befindet sich bei 1000 Einh. Tiefe}
- vpage:=0; {mit Seite 0 beginnen}
- init_modex; {ModeX einschalten}
- Prep_Texturen;
- LoadGif('logo.gif'); {Hintergrundbild laden}
- rotx:=0; {Startwerte fr Rotation}
- roty:=0;
- rotz:=0;
- Fuellen:=true; {Fl„chenfllen ein}
- fl_sort:=true; {Fl„chensortierung ein}
- fl_ruecken:=true; {Fl„chenrckeunterdrckung ein}
- Glas:=false; {Glas-Oberfl„chen aus}
- p13_2_modex(16000*2,16000); {Hintergrund auf VGA-Seite 2}
- repeat
- CopyScreen(vpage,16000*2); {Hintergrundbild auf aktuelle Seite}
- DrawWorld; {Welt zeichnen}
- switch; {auf fertiges Bild schalten}
- WaitRetrace; {n„chsten Retrace abwarten}
- Inc(rotx); {weiterrotieren ... }
- If rotx=120 Then rotx:=0;
- Inc(rotz);
- If rotz=120 Then rotz:=0;
- inc(roty);
- if roty=120 Then roty:=0;
- Until KeyPressed; { ... bis Taste}
- TextMode(3);
- End.
- Uses Crt,ModeXLib;
- var y1, {y-Position Copper 1}
- y1_dir, {y-Richtung Copper 1}
- Maske:Word; {Overlay-Maske, fr šberlagerung der Copper}
- Procedure MakeCopper(y_pos1,y_pos2,overlay_maske:word);external;
- {$l copper}
- begin
- TextMode(3); {Copper funktioniert in JEDEM Videomodus ! }
- y1:=Port[$3da]; {ATC in Index-Mode schalten}
- Port[$3c0]:=$11 or 32; {Register 11h w„hlen}
- Port[$3c0]:=255; {Rahmenfarbe 255}
- y1:=0; {Start am oberen Bildschirmrand}
- y1_dir:=2; {Bewegung zun„chst nach unten}
- Maske:=$00ff; {zun„chst Copper 1 (rot) im Vordergrund}
- Repeat
- Inc(y1,y1_dir); {Copper-Bewegung}
- If (y1<=0) or (y1>=150) {am Rand : }
- then Begin
- y1_dir:=-y1_dir; {Richtung umkehren}
- Maske:=Swap(Maske); {jew. anderen Copper in Vordergrund}
- End;
- Write('D i e s i s t e i n D e m o t e x t ');
- MakeCopper(y1,150-y1,Maske);{Copper zeichnen}
- Until KeyPressed;
- End.
- Uses Crt,ModeXLib,Gif,Font;
- Var Eingabe:Char; {gerade eingegebenes Zeichen}
- Begin
- Init_ModeX; {Mode X ein}
- LoadGif('pfont4'); {Zeichensatz laden}
- p13_2_ModeX(48000,16000); {und auf Seite 3 kopieren}
- Repeat {Schleife zum Ausgeben von Tastatureingaben}
- Eingabe:=ReadKey; {Zeichen holen}
- Print_Char(Eingabe); {und auf Monitor bringen}
- Until Eingabe=#27; {bis Esc gedrckt}
- Print_String('hallo, test'); {zum Abschluá noch einen String ausgeben}
- ReadLn;
- TextMode(3);
- End.
- Unit fade;
- {verwendet zum šberblenden eines gerade angezeigten Bild(teil)s
- in ein neues}
- Interface
- Uses ModeXLib;
- Var Colors:Word; {Anzahl Farben pro Einzelbild}
- Procedure fade_ResetPic(y,Hoehe:Word);
- Procedure Ueberblenden(Pic:Pointer;Pal:Array of Byte; Start,y,Hoehe:Word);
- Implementation
- Var i,j:Word; {tempor„re Z„hler}
- Ziel_Pal:Array[0..768] of Byte; {tempor„re Zielpalette}
- Procedure fade_set(Quelle:Pointer;Start,y,Hoehe:Word);external;
- {"mischt" Quelle mit VGA-Ram}
- {dabei Quelle ab Zeile Start und VGA-Ram ab Zeile y bei H”he Hoehe verwenden}
- Procedure fade_ResetPic(y,Hoehe:Word);external;
- {bereitet bergeblendetes Bild auf erneutes Faden vor}
- {dazu Reduktion von "Colors^2" auf "Colors" Farben}
- {auch hier y=Zeile im VGA-Ram, Hoehe=H”he des zu bearbeitenden Bereichs}
- {$l fade}
- Procedure fade_CopyPal;
- {Palette auf Colors^2 vervielfachen (nichthomogenen Block 0 vervielfachen)}
- Begin
- For i:=1 to Colors do
- Move(Palette[0],Palette[i*3*Colors],Colors*3);
- End;
- Procedure fade_spreizen(Var Pal:Array of Byte);
- {Palette auf Colors^2 spreizen (jede Farbe einzeln vervielfachen)}
- {hier werden aus den Farben 0..Colors-1 die homogenen Bl”cke gebildet}
- Begin
- For i:= 0 to Colors-1 do {jede Farbe einzeln bearbeiten}
- For j:=0 to Colors -1 do {jeweils Colors mal schreiben}
- Move(Pal[i*3],Pal[(i+1)*3*Colors+j*3],3);
- End;
- Procedure Ueberblenden(Pic:Pointer;Pal:Array of Byte; Start,y,Hoehe:Word);
- {Blendet von aktuell sichtbarem Bild auf Pic (mit Palette Pal) ber
- dabei wird in Zeile "Start" von Pic begonnen, "Hoehe" Zeilen zur
- y-Koordinate y des aktuellen Bilds zu kopieren}
- Begin
- WaitRetrace; {Synchronisation}
- fade_CopyPal; {in aktueller Palette Block vervielfachen}
- SetPal; {diese Palette neu setzen}
- Move(Palette,Ziel_Pal,768); {originale Palettenteile beibehalten}
- Move(pal,Ziel_Pal,Colors*3); {Zielpalette laden}
- fade_spreizen(Ziel_pal); {Zielpaletten-Blocks spreizen}
- fade_set(pic,start,y,hoehe); {neues Bild dazumischen}
- fade_to(Ziel_pal,1); {und berblenden}
- End;
- Begin
- Colors:=15; {nur Defaultwert !}
- End.
- uses crt,ModeXLib,Tools;
- var i,j:word;
- zielpal:Array[0..767] of Byte;
- Procedure Fade_in(ZPal:Array of Byte);
- Begin
- For j:=0 to 63 do Begin {64 Durchl„ufe, um komplett zu faden}
- For i:=0 to 767 do {768 Farbwerte berechnen}
- If Palette[i] < ZPal[i] {aktueller Wert noch kleiner als Zielwert ?}
- Then Inc(Palette[i]); {dann erh”hen}
- WaitRetrace; {Synchronisation}
- SetPal; {berechnete Palette setzen}
- End;
- End;
- begin
- ClrScr; {Bildschirm l”schen}
- GetPal; {"Palette" mit aktuelle DAC-Palette laden}
- Move(Palette,Zielpal,768); {Palette sichern}
- FillChar(Palette,768,0); {alte Palette l”schen}
- SetPal; {und setzen}
- Draw_Ansi('color.ans'); {Hintergrundbild laden}
- ReadLn;
- fade_in(Zielpal); {Bild auf Zielpal (originale Palette) faden}
- ReadLn;
- TextMode(3); {Normalzustand herstellen}
- End.
- uses crt,modexlib,Tools;
- var i:word;
- Begin
- GetPal; {"Palette" mit aktuelle DAC-Palette laden}
- Draw_Ansi('color.ans'); {Bild laden}
- Setpal;
- ReadLn;
- Fade_out; {Bild ausblenden}
- ReadLn;
- TextMode(3); {wieder normales Bild}
- End.uses Crt,ModeXLib,gif,fade;
- Var pic1_pal, {Paletten der beiden Bilder}
- pic2_pal:Array[0..767] of Byte;
- pic1, {beinhaltet 1.Bild}
- pic2:Pointer; {2. Bild, ist gleich vscreen}
- Begin
- Init_Mode13; {Mode 13h ein}
- Screen_off; {Bildschirm aus w„hren Ladens}
- LoadGif('schach'); {erstes Bild laden}
- GetMem(pic1,64000); {Speicher fr 1.Bild holen}
- Move(vscreen^,pic1^,64000); {in pic1 sichern}
- Move(Palette,pic1_pal,768); {und die Palette sichern}
- Show_Pic13; {dieses Bild auf Screen}
- LoadGif('kiste'); {n„chstes in vscreen^ Laden}
- pic2:=vscreen; {pic2 als Zeiger darauf verwendet}
- Move(Palette,pic2_pal,768); {dessen Palette sichern}
- Move(pic1_pal,Palette,768); {Palette von Bild 1 aktivieren}
- SetPal; {und setzen}
- Screen_on; {jetzt Bildschirm wieder einschalten}
- ReadLn; {warten}
- Ueberblenden(pic2,pic2_pal,0,0,200);
- {und dann Bild 2 einblenden)}
- fade_ResetPic(0,200); {erneutes Faden vorbereiten}
- ReadLn;
- Ueberblenden(pic1,pic1_pal,0,0,200);
- {und Bild 1 einblenden}
- ReadLn;
- TextMode(3);
- End.
- uses crt,ModeXLib,Tools;
- var i:word;
- origpal,
- zielpal:Array[0..767] of Byte;
- begin
- ClrScr;
- GetPal; {"Palette" mit aktuelle DAC-Palette laden}
- Move(Palette,OrigPal,768); {Palette sichern}
- Move(Palette,Zielpal,768); {Ziel-Palette bestimmen}
- Draw_Ansi('color.ans'); {Ansi-Bild laden}
- Make_bw(ZielPal); {ZielPal auf schwarz/weiá ziehen}
- readkey;
- fade_to(ZielPal,1); {schwarz/weiáe Palette einblenden}
- ReadKey;
- fade_to(OrigPal,1); {Original-Palette einblenden}
- ReadLn;
- TextMode(3); {Normalzustand herstellen}
- End.
- Uses Crt,Gif,ModeXLib,Fade;
- Var
- Text_Pal:Array[0..767] of Byte;
- i:word;
- Begin
- Init_Mode13; {Mode 13h benutzen}
- Screen_Off; {Bildschirm beim Laden aus}
- LoadGif('vflog210'); {statischen Teil laden}
- Move(Palette[210*3], {dessen Palettenteil (Farben 210..255)}
- Text_Pal[210*3],46*3); {eintragen}
- Show_Pic13; {statisches Bild in VGA kopieren}
- LoadGif('texte'); {Bild mit Texten laden}
- Move(Palette,Text_Pal,14*3); {dessen Palettenteil (Farben 0..13)}
- {eintragen}
- Move(Text_Pal,Palette,768); {fertige Palette setzen}
- SetPal;
- Move(vscreen^, {erster Text kann direkt auf Bildschirm}
- Ptr($a000,160*320)^,19*320);{kopiert werden}
- Screen_On; {jetzt Bild fertig -> einschalten}
- Colors:=14; {in diesem Programm Bilder mit 14 Farben !}
- For i:=1 to 6 do Begin {nacheinander die 6 weiteren Texte einblenden}
- Delay(500); {Zeit zum Lesen}
- Ueberblenden(vscreen, {n„chstes Bild an alte Position (y=160) faden}
- text_pal,i*20,160,19);
- Fade_ResetPic(160,19); {und "resetten"}
- If KeyPressed Then Exit; {wer genug hat, kann hier abbrechen}
- End;
- Readln;
- TextMode(3);
- End.
- {$G+}
- Uses Crt,ModeXLib;
- Type Block=Array[0..99,0..319] of Byte;
- Var
- Src_Frame, {vorheriges Bild}
- Dest_Frame:^Block; {aktuelles Bild}
- Procedure Scroll_Up;assembler;
- {scrollt das Bild um eine Zeile nach oben und interpoliert}
- asm
- push ds
- les di,Dest_Frame {Zeiger auf Zielbild laden}
- lds si,Src_Frame {Zeiger auf Quellbild}
- add si,320 {im Quellbild auf Zeile 1}
- mov cx,320*98 {99 Zeilen scrollen}
- xor bl,bl {wird als Dummy fr High-Byte ben”tigt}
- @lp1:
- xor ax,ax
- xor bx,bx
- mov al,[si-321] {ersten Punkt holen}
- mov bl,[si-320] {zweiten Punkt addieren}
- add ax,bx
- mov bl,[si-319] {n„chsten Punkt addieren}
- add ax,bx
- mov bl,[si-1] {usw...}
- add ax,bx
- mov bl,[si+1]
- add ax,bx
- mov bl,[si+319]
- add ax,bx
- mov bl,[si+320]
- adc ax,bx
- mov bl,[si+321]
- adc ax,bx
- shr ax,3
- or ax,ax {bereits 0 ?}
- je @null
- dec al {wenn nein, dann verringern}
- @null:
- stosb {Wert ins Ziel}
- inc si {n„chsten Punkt}
- dec cx {weitere Punkte ?}
- jne @lp1
- pop ds
- End;
- Procedure New_Line; {baut die untersten Zeilen neu auf}
- Var i,x:Word;
- Begin
- For x:=0 to 319 do Begin {untere 3 Zeilen mit zuf„lligen Werten fllen}
- Dest_Frame^[97,x]:=Random(15)+64;
- Dest_Frame^[98,x]:=Random(15)+64;
- Dest_Frame^[99,x]:=Random(15)+64;
- End;
- For i:=0 to Random(45) do Begin {zuf. Anzahl Hotspots einfgen}
- x:=Random(320); {an zuf„llige Koordinaten}
- asm
- les di,Dest_Frame {Zielbild adressieren}
- add di,98*320 {Zeile 98 (zweitunterste) bearbeiten}
- add di,x {x-Koordinate dazu}
- mov al,0ffh {hellste Farbe}
- mov es:[di-321],al {groáen Hotspot erzeugen (9 Punkte)}
- mov es:[di-320],al
- mov es:[di-319],al
- mov es:[di-1],al
- mov es:[di],al
- mov es:[di+1],al
- mov es:[di+319],al
- mov es:[di+320],al
- mov es:[di+321],al
- End;
- End;
- End;
- Procedure Show_Screen; {kopiert fertigen Bilschirm auf VGA}
- Var temp:Pointer; {zum Tauschen der Zeiger}
- Begin
- asm
- push ds
- lds si,Dest_Frame {fertiges Bild als Quelle}
- mov ax,0a000h {VGA als Ziel}
- mov es,ax
- mov di,320*100 {ab Zeile 100}
- mov cx,320*100/4 {100 Zeilen als Dwords kopieren}
- db 66h {Operand Size Prefix (32 Bit)}
- rep movsw {kopieren}
- pop ds
- End;
- temp:=Dest_Frame; {Zeiger auf Quell- und Zielbild tauschen}
- Dest_Frame:=Src_Frame;
- Src_Frame:=temp;
- End;
- Procedure Prep_Pal; {Palette auf Flames vorbereiten}
- Var i:Word;
- Begin
- FillChar(Palette,80*3,0); {Grundlage: alles schwarz}
- For i:=0 to 7 do Begin
- Palette[i*3+2]:=i*2; {Farbe 0-7: Anstieg Blau}
- Palette[(i+8)*3+2]:=16-i*2; {Farbe 0-7: abfallendes Blau}
- End;
- For i:=8 to 31 do {Farbe 8 -31: Anstieg Rot}
- Palette[i*3]:=(i-8)*63 div 23;
- For i:=32 to 55 do Begin {Farbe 32-55: Anstieg Grn, Rot konstant}
- Palette[i*3]:=63;
- Palette[i*3+1]:=(i-32)*63 div 23;
- End;
- For i:=56 to 79 do Begin {Farbe 56-79: Anstieg Blau,Rot u. Blau konst.}
- Palette[i*3]:=63;
- Palette[i*3+1]:=63;
- Palette[i*3+2]:=(i-56)*63 div 23;
- End;
- FillChar(Palette[80*3],176*3,63); {Rest weiá}
- SetPal; {fertige Palette setzen}
- End;
- begin
- Randomize; {Random Seed bestimmen}
- GetMem(Src_Frame,320*100); {Speicher fr Quellbild holen und l”schen}
- FillChar(Src_Frame^,320*100,0);
- GetMem(Dest_Frame,320*100); {Speicher fr Ziellbild holen und l”schen}
- FillChar(Dest_Frame^,320*100,0);
- Init_Mode13; {Mode 13h setzen}
- Prep_Pal; {Palette vorbereiten}
- Repeat
- Scroll_Up; {Flammen nach oben}
- New_Line; {unten neue Linie anfgen}
- Show_Screen; {fertigen Bildschirm zeigen}
- Until KeyPressed;
- TextMode(3);
- end.
- Uses Crt,Gif,ModeXLib;
- Procedure Fliess;
- var i,
- Old9:Byte;
- Begin
- Port[$3d4]:=9; {CRTC Register 9 (Maximum Row Adress) selekt.}
- Old9:=Port[$3d5] and $80; {alten Inhalt speichern, }
- for i:=2 to 31 do begin {erspart st„ndiges auslesen}
- WaitRetrace; {Synchronisation}
- Port[$3d5]:=old9 or i; {Wert schreiben}
- End;
- End;
- Begin
- asm mov ax,13h; int 10h End; {Mode 13h ein (oder anderer Grafikmodus)}
- LoadGif('beule'); {Hintergrund-Bild laden}
- Move(vscreen^,Ptr($a000,0)^,64000); {und auf Screen}
- ReadLn;
- Fliess; {Wegflieáen ausl”sen}
- ReadLn;
- TextMode(3); {VGA wieder in Ursprungszustand setzen}
- End.
- Unit Font;
- Interface
- Procedure Print_Char(Chr:Char);
- {gibt Zeichen auf Mode X aus}
- Procedure Print_String(Str:String);
- {gibt String auf Mode X aus}
- Procedure Scrl_Move;
- {bewegt sichtbaren Teil des Scrolly nach links}
- Procedure Scrl_Append;
- {h„ngt am rechten Bildrand neue Daten an Scrolly an}
- Var Scrl_Y:Word; {vertikale Position des Scrollys}
- Const
- Scrl_Anzahl=4;
- {Anzahl der in Scrl_Txt vorhandenen Strings}
- Scrl_Txt:Array [1..Scrl_Anzahl] of String =
- {Nur ein Demo-Text, der beliebig ver„ndert oder erg„nzt werden kann !}
- ('Hallo, !!!dies ist ein Demo-Scroller aus dem Buch P C U N D E R G R O U N D'
- +' von Data Becker. Zugegeben, es ist nicht gerade der anspruchsvollste, ',
- 'dafuer kommt er aber mit einem Minimum an Aufwand und vor allem '
- +'Rechenzeit aus. Selbst auf langsameren Rechnern ist es ohne weiteres ',
- 'moeglich, nebenbei ganz andere Effekte zu benutzen; jedenfalls benoetigt '
- +'der Scroller auf einem 486-40 mit ausgeschaltetem Turbo nur etwa ',
- '10 Prozent der verfuegbaren Rechenzeit Achtung Scrolly startet '
- +'jetzt neu --------------------------- ');
- Implementation
- Uses ModeXLib;
- Const
- CharPos:Array[' '..'Z', 0..1] of Word=
- {Positionen und Breiten der einzelnen Zeichen,
- jeweils CPU-adressierte Bytes}
- ((71,4),(0,0),(0,0),(0,0),(0,0),(0,0),
- (0,0),(0,0),(0,0),(0,0),(0,0),(0,0),
- (1906,3),(1909,3),(1912,3),(1915,4), {,-./}
- (3600,5),(3605,3),(3608,5),(3613,5), {0..3}
- (3618,5),(3623,5),(3628,5),(3633,5), {4..7}
- (3638,5),(3643,5),(3648,3),(3651,3), {8..;}
- (3654,5),(3659,5),(3664,5),(3669,4), {<..?}
- (0,0),(0,5),(5,5),(10,5),(15,6),(21,5), {@..E}
- (26,4),(30,7),(37,5),(42,3),(45,4),(49,5),{F..K}
- (54,4),(58,8),(66,5),(1840,7),(1847,5), {L..P}
- (1852,7),(1859,5),(1864,4),(1868,4), {Q..T}
- (1872,5),(1877,6),(1883,8),(1891,5), {U..X}
- (1896,5),(1901,5)); {YZ}
- Var Cur_X, {gegenw„rtige x-}
- Cur_Y:Integer; {und y-Position des Cursors}
- Scrl_Number, {Nummer des gerade aktiven Scroll-Strings}
- Scrl_Pos, {Position innerhalb dieses Strings}
- Scrl_ChrPos:Word; {Position innerhalb des Zeichens}
- Procedure Print_Char(Chr:Char);
- {Gibt ein Zeichen auf Mode X Bildschirm aus und bewegt Cursor
- eine Position weiter}
- Begin
- Chr:=UpCase(Chr); {nur Groábuchstaben verwenden}
- If Chr in [' '..'Z'] Then Begin {ist das Zeichen im Zeichensatz ?, ja:}
- If 80- Cur_X < {noch genug Platz ?}
- CharPos[Chr,1] Then Begin
- Cur_X:=0; {nein, dann n„chste Zeile, x auf 0}
- Inc(Cur_Y,25); {und y eine Zeichenh”he weiter}
- End;
- Copy_Block(Cur_Y*80+Cur_X, 48000+Charpos[Chr,0], CharPos[Chr,1], 22);
- {Zeichen von Font-Position (aus CharPos-Tabelle) an Cursorposition
- (Cur_Y * 80 Byte pro Zeile + Cur_X) kopieren (H”he 22 Zeilen}
- Inc(Cur_X,CharPos[Chr,1]); {Cursor um Zeichenbreite bewegen}
- End;
- End;
- Procedure Print_String(Str:String);
- {gibt einen String auf Mode X Bildschirm aus,
- benutzt dazu Print_Char}
- Var i:Word;
- Begin
- For i:=1 to Length(Str) do {gesamten String an Print_Char schicken}
- Print_Char(Str[i]);
- End;
- Procedure Scrl_Move;
- {verschiebt einfach Bildinhalt an der Stelle des Scrollys um eine
- Position nach links, also 79 Bytes von x-Position 1 nach x-Position 0
- kopieren}
- Begin
- Copy_Block(Scrl_y*80, Scrl_Y*80 +1, 79,22);
- End;
- Procedure Scrl_Append;
- Var Chr:Char; {aktueller Buchstabe}
- Begin
- Chr:=UpCase(Scrl_txt[Scrl_Number,Scrl_pos]);
- {Buchstaben holen, nur Groábuchstaben}
- If Chr in [' '..'Z'] Then Begin {ist das Zeichen im Zeichensatz ?, ja:}
- If CharPos[Chr,1] > 0 Then {nur vorhandene Zeichen darstellen}
- Copy_Block(Scrl_y*80+79, 48000+CharPos[Chr,0]+Scrl_ChrPos, 1, 22);
- {dann 1 Spalte aus Zeichensatz an rechten}
- {Bildschirmrand kopieren}
- Inc(Scrl_ChrPos); {und n„chste Spalte innerhalb des Zeichens}
- If Scrl_ChrPos >= CharPos[Chr,1] Then Begin
- Inc(Scrl_Pos); {wenn Zeichen fertig, n„chstes Zeichen}
- Scrl_ChrPos:=0; {und Spalte wieder auf 0}
- If Scrl_Pos > Length(Scrl_Txt[Scrl_Number]) Then Begin
- Inc(Scrl_Number); {wenn String fertig, n„chsten String}
- Scrl_Pos:=1; {Position wieder auf 0}
- If Scrl_Number > Scrl_Anzahl Then Begin
- Scrl_Number:=1; {wenn Text fertig, wieder von vorn}
- Scrl_Pos:=1;
- Scrl_ChrPos:=0;
- End;
- End;
- End;
- End;
- End;
- Begin
- Cur_X:=0; {Cursor auf linke obere Ecke}
- Cur_Y:=0;
- Scrl_Y:=50; {Default-Wert fr y-Position}
- Scrl_Number:=1; {Start mit String 1, Zeichen 1, Spalte 0}
- Scrl_Pos:=1;
- Scrl_ChrPos:=0;
- End.
- unit gif; {Header zu gif.asm}
- Interface
- uses modexlib; {wg. SetPal}
- var
- vram_pos, {aktuelle Position im VGA-Ram}
- rest, errornr:word; {restliche Bytes im Hauptspeicher und Fehler}
- gifname:String; {Name, erweitert um #0}
- Procedure LoadGif(GName:String);
- {L„dt Gif-Datei "GName.gif" in vscreen}
- Procedure LoadGif_Pos(GName:String;Posit:Word);
- {L„dt Gif-Datei an Bildschirmoffset Posit}
- Implementation
- Procedure ReadGif;external; {eigentlicher Gif-Loader, kompl. in Asm}
- {$l gif}
- Procedure LoadGif;
- {L„dt Gif-Datei "GName.gif" in vscreen}
- Begin
- If pos('.',gname) = 0 then {evtl. Endung ".gif" anh„ngen}
- gname:=gname+'.gif';
- Gifname:=GName+#0;; {ASCIIZ - String erzeugen}
- vram_pos:=0; {im VGA-Ram an Offset 0 beginnen}
- ReadGif; {und Bild laden}
- If Errornr <> 0 Then {bei Fehler abbrechen}
- Halt(Errornr);
- SetPal; {geladene Palette setzen}
- End;
- Procedure LoadGif_pos;
- {L„dt Gif-Datei an Bildschirmoffset Posit}
- Begin
- If pos('.',gname) = 0 then {evtl. Endung ".gif" anh„ngen}
- gname:=gname+'.gif';
- Gifname:=GName+#0; {ASCIIZ - String erzeugen}
- vram_pos:=posit; {im VGA-Ram an bergebenen Offset beginnen}
- ReadGif; {und Bild laden}
- If Errornr <> 0 Then {bei Fehler abbrechen}
- Halt(Errornr);
- SetPal; {geladene Palette setzen}
- End;
- Begin
- errornr:=0; {normalerweise kein Fehler}
- GetMem(VScreen,64000); {virtuellen Bildschirm allokieren}
- End.
- {$G+}
- {$m 1024,0,0} {wenig Stack und kein Heap ben”tigt}
- Uses ModeXLib,Crt,Dos;
- Var OldInt9:Pointer; {Zeiger auf alten Tastaturhandler}
- active:Boolean; {gesetzt, wenn bereits Hardcopy im Gange}
- nr:Word; {Nummer des Bilds, zur Vergabe von Filenamen}
- installiert:Boolean; {bereits installiert ?}
- Mode, {aktueller VGA-Mode: 13h, ffh (Mode X)}
- {oder 0 (keiner der beiden}
- Split_at, {Split-Line (Grafikzeile}
- LSA, {Linear Starting Address}
- Skip:Word; {Anzahl zu berspringender Bytes}
- Procedure GetMode;
- {bestimmt aktuellen Grafikmodus 13h oder Mode X (Nr. 255)}
- {und Rahmendaten (Split-Line, Startadresse)}
- Begin
- Mode:=$13; {Mode 13h Standard}
- asm {Bios-Mode bestimmen}
- mov ax,0f00h {Funktion: Video-Info}
- int 10h
- cmp al,13h {Bios-Mode 13h gesetzt ?}
- je @Bios_ok
- mov mode,0 {wenn nein -> weder Mode 13h noch X aktiv}
- @bios_ok:
- End;
- If Mode=0 Then Exit; {falscher Modus -> abbrechen}
- Port[$3c4]:=4; {TS-Register 4 (Memory Mode) auslesen}
- If Port[$3c5] and 8 = 0 Then {Chain 4 (Bit 3) inaktiv ?}
- Mode:=$ff; {dann Mode X}
- Port[$3d4]:=$0d; {Linear Starting Address Low (CRTC 0dh)}
- LSA:=Port[$3d5]; {auslesen}
- Port[$3d4]:=$0c; {Linear Starting Address High (CRTC 0ch)}
- LSA:=LSA or Port[$3d5] shl 8; {auslesen und eintragen}
- Port[$3d4]:=$18; {Line Compare CRTC 18h}
- Split_at:=Port[$3d5]; {auslesen}
- Port[$3d4]:=7; {Overflow Low}
- Split_at:=Split_at or {Bit 4 ausmaskieren und nach Bit 8 schieben}
- (Port[$3d5] and 16) shl 4;
- Port[$3d4]:=9; {Maximum Row Address}
- Split_at:=Split_at or {Bit 6 ausmaskieren unf nach Bit 9 schieben}
- (Port[$3d5] and 64) shl 3;
- Split_at:=Split_at shr 1; {auf Bildschirmzeilen umrechnen}
- Port[$3d4]:=$13; {Row Offset (CRTC Register 13h)}
- Skip:=Port[$3d5]; {auslesen}
- Skip:=Skip*2-80 {Differenz zum "normalen" Zeilenabstand lesen}
- End;
- Procedure PCXShift;assembler;
- {bereitet aktuelle Palette auf PCX vor (2 nach links shiften)}
- asm
- mov si,offset palette {Zeiger auf Palette in ds:si}
- mov cx,768 {768 Bytes bearbeiten}
- @lp:
- lodsb {Wert holen}
- shl al,2 {shiften}
- mov ds:[si-1],al {zurckschreiben an alte Position}
- loop @lp {und Schleife abschlieáen}
- End;
- Var pcx:File; {PCX-Datei auf Platte}
- Procedure Hardcopy(Startadr,splt:Word;s : string);
- {kopiert Grafik 320x200 (Mode 13 o. X) als PCX in Datei s}
- {aktueller Bildschirmstart (Linear Starting Address) in Startadr}
- {Split-Zeile in splt}
- Var Buf:Array[0..57] of Byte; {nimmt Daten vor Speichern auf}
- Aux_Ofs:Word;
- const
- Header1:Array[0..15] of Byte {PCX-Kopf, erster Teil}
- =($0a,5,1,8, 0,0, 0,0, $3f,1, 199,0,$40,1,200,0);
- Header2:Array[0..5] of Byte {PCX-Kopf, erster Teil}
- =(0,1,$40,1,0,0);
- plane:Byte=0; {aktuelle Planenr}
- var count:Byte; {Anzahl gleicher Zeichen}
- wert, {gerade geholter Wert}
- lastbyt:Byte; {vorheriger Wert}
- i:word; {Byte-Z„hler}
- begin
- asm {Palette auslesen}
- xor al,al {bei Farbe 0 beginnen}
- mov dx,3c7h {dies dem DAC ber Pixel Read Address}
- out dx,al {mitteilen}
- push ds {Zeiger es:di auf Palette}
- pop es
- mov di,offset palette
- mov cx,768 {768 Bytes auslesen}
- mov dx,3c9h {Pixel Color Value}
- rep insb {und lesen}
- cmp mode,13h {Mode X ?}
- je @Linear {dann:}
- mov dx,03ceh {Schreib- und Lesemodus 0 setzen}
- mov ax,4005h {ber GDC-Register 5 (GDC Mode)}
- out dx,ax
- @Linear:
- End;
- Assign(pcx,s); {Datei zum Schreiben ”ffnen}
- Rewrite(pcx,1);
- BlockWrite(pcx,Header1,16); {Header Teil 1 schreiben}
- PCXShift; {Palette vorbereiten}
- BlockWrite(pcx,palette,48); {ersten 16 Farben eintragen}
- BlockWrite(pcx,Header2,6); {Header Teil 1 schreiben}
- FillChar(buf,58,0); {58 Nullen schreiben (Header fllen)}
- BlockWrite(pcx,buf,58);
- plane:=0; {mit Plane 0 beginnen}
- count:=1; {Anzahl mit 1 initialisieren}
- If splt<200 Then
- If Mode = $ff Then
- splt:=splt*80 Else {Split-Offset berechnen}
- splt:=splt*320 Else {je nach Mode unterschiedlich}
- Splt:=$ffff;
- If Mode=$13 Then {LSA bezieht sich auf das Plane-Modell !}
- Startadr:=Startadr*4;
- for i:=0 to 64000 do Begin {jeden Punkt bearbeiten}
- If i shr 2 < splt Then
- aux_ofs:=(i div 320) * skip {Hilfsoffset unter Bercksichtigung}
- {der Zeilenbreite setzen}
- Else
- aux_ofs:=((i shr 2 - splt) div 320) * skip;
- {bei Splitting Bezug auf VGA-Start}
- asm {Punkt auslesen}
- mov ax,0a000h {Segment laden}
- mov es,ax
- mov si,i {Offset laden}
- cmp mode,13h {Mode 13h ?}
- je @Linear1
- shr si,2 {nein, dann Offset berechnen}
- @Linear1:
- cmp si,splt {Split-Line erreicht ?}
- jb @weiter {nein, dann weiter}
- sub si,splt {ansonsten alles weitere auf den}
- sub si,startadr {Bildschirmstart beziehen}
- @weiter:
- add si,startadr {Startadresse drauf}
- add si,aux_ofs {Hilfs-Offset addieren}
- cmp mode,13h {Mode 13h ?}
- je @Linear2 {nein, dann Mode X Lesemethode}
- mov dx,03ceh {ber GDC-Register 4 (Read Plane Select)}
- mov ah,plane {aktuelle Plane selektieren}
- inc plane {und weiterschalten}
- mov al,4
- and ah,03h
- out dx,ax
- @Linear2:
- mov al,es:[si] {Byte auslesen}
- mov wert,al {und in Variable Wert sichern}
- End;
- If i<>0 Then Begin {beim ersten Byte keine Kompression}
- If (Wert = lastbyt) Then Begin{gleiche Bytes ?}
- Inc(Count); {dann Z„hler erh”hen}
- If (Count=64) or {Z„hler schon zu hoch ?}
- (i mod 320 =0) Then Begin {oder Zeilenanfang ?}
- buf[0]:=$c0 or (count-1); {dann Zwischenspeichern}
- buf[1]:=lastbyt; {Z„hlerstand und Wert schreiben}
- count:=1; {Z„hler reinitialisieren}
- BlockWrite(pcx,buf,2); {und auf die Platte damit}
- End;
- End Else {verschiedene Bytes :}
- If (Count > 1) or {waren es mehrere gleiche ?}
- (lastbyt and $c0 <> 0) Then {Wert zu groá zum direkten Schreiben ?}
- Begin
- buf[0]:=$c0 or count; {dann Anzahl und Wert in Datei schreiben}
- buf[1]:=lastbyt;
- lastbyt:=Wert; {aktuellen Wert fr weitere Kompression}
- Count:=1; {sichern und reinitialisieren}
- BlockWrite(pcx,buf,2);
- End Else Begin {einzelnes, legales Byte:}
- buf[0]:=lastbyt; {direkt schreiben}
- lastbyt:=Wert; {aktuellen Wert fr sp„ter sichern}
- BlockWrite(pcx,buf,1);
- End;
- End Else lastbyt:=wert; {beim ersten Byte nur sichern}
- End;
- buf[0]:=$0c; {Kennung Palette einfgen}
- blockwrite(pcx,buf[0],1); {und schreiben}
- blockwrite(pcx,palette,256*3);{und Palette anfgen}
- Close(pcx); {Datei schlieáen}
- End;
- Procedure Action;
- {wird bei Aktivierung des Hot-Keys aufgerufen}
- Var nrs:String; {String zur Namensvergabe}
- Begin
- if not active Then Begin {nur wenn nicht bereits aktiv}
- active:=true; {als aktiv vermerken}
- str(nr,nrs); {Nummer in String umwandeln und erh”hen}
- Inc(nr);
- GetMode; {Grafikmodus etc. ermitteln}
- If Mode <> 0 Then
- HardCopy(LSA,Split_at,'hard'+nrs+'.pcx');
- {Hardcopy durchfhren}
- active:=false; {erneute Aktivierung freigeben}
- End;
- End;
- Procedure Handler9;interrupt;assembler;
- {neuer Interrupt-Handler fr Tastatur-IRQ}
- asm
- pushf
- call [oldint9] {alten IRQ 1 - Handler aufrufen}
- cli {keine weiteren Interrupts}
- in al,60h {Scancode lesen}
- cmp al,34d {G ?}
- jne @fertig {nein -> Handler beenden}
- xor ax,ax {0-Segment laden}
- mov es,ax
- mov al,es:[417h] {Keyboard-Status lesen}
- test al,8 {Bit 8 (Alt-Taste) gesetzt ?}
- je @fertig {nein -> Handler beenden}
- call action {Hardcopy durchfhren}
- @fertig:
- sti {Interrupts wieder zulassen}
- End;
- Procedure kennung;assembler;
- {Dummy-Prozedur, enth„lt Copyrightmeldung fr Installationskennung}
- {KEIN AUSFšHRBARER CODE !}
- asm
- db 'Screen-Grabber, (c) Data Becker 1994';
- End;
- Procedure Check_Inst;assembler;
- {berprft, ob Grabber bereits installiert}
- asm
- mov installiert,1 {Annahme: bereits installiert}
- push ds {ds wird noch ben”tigt !}
- les di,oldint9 {Zeiger auf alten Handler laden}
- mov di,offset kennung {im gleichen Segment auch Prozedur Kennung}
- mov ax,cs {ds:si auf Kennung dieses Programms setzen}
- mov ds,ax
- mov si,offset kennung
- mov cx,20 {20 Zeichen vergleichen}
- repe cmpsb
- pop ds {ds wieder herstellen}
- jcxz @installiert {gleich, dann bereits installiert}
- mov installiert,0 {nicht installiert: merken}
- @installiert:
- End;
- Begin
- nr:=0; {erster Dateiname: hard0.pcx}
- GetIntVec(9,OldInt9); {alten Interrupt-Vektor holen}
- Check_Inst; {prfen, ob schon installiert}
- If not installiert Then Begin {wenn nein:}
- SetIntVec(9,@Handler9); {neuen Handler installieren}
- WriteLn('Grabber installiert');
- WriteLn('(c) Data Becker 1994');
- WriteLn('Aktivierung mit <alt> g');
- Keep(0); {Meldung ausgeben und resident beenden}
- End;
- WriteLn('Grabber bereits installiert');
- {wenn schon installiert, Meldung und beenden}
- End.
- Uses Crt;
- Var x:Word;
- Procedure PutPixel(x,y,col:word);assembler;
- {setzt Punkt (x/y) auf Farbe col (Mode 13h)}
- asm
- mov ax,0a000h {Segment laden}
- mov es,ax
- mov ax,320 {Offset = Y*320 + X}
- mul y
- add ax,x
- mov di,ax {Offset laden}
- mov al,byte ptr col {Farbe laden}
- mov es:[di],al {und Punkt setzen}
- End;
- Procedure Line(x1,y1,x2,y2,col:Word);assembler;
- asm
- {verwendete Register:
- bx/cx: Vor-/Nachkommateil der y-Koordinate
- si : Nachkommateil der Steigung}
- mov si,x1 {x mit Startwert laden}
- mov x,si
- sub si,x2 {und x-Differenz bilden (in si)}
- mov ax,y1 {y (gespeichert in bx) mit Startwert laden}
- mov bx,ax
- sub ax,y2 {und y-Differenz bilden (in ax)}
- mov cx,100 {y-Differenz wg Rechengenauigkeit erweitern}
- imul cx
- idiv si {und durch x-Diff dividieren (Steigung)}
- mov si,ax {Steigung in si sichern}
- xor cx,cx {Nachkommateil der y-Koordinate auf 0}
- @lp:
- push x {x und Vorkommateil von y an PutPixel}
- push bx
- push col
- call PutPixel
- add cx,si {y-Nachkommateil erh”hen}
- cmp cx,100 {Nachkomma-šberlauf ?}
- jb @kein_ueberlauf {nein, dann weiter}
- sub cx,100 {ansonsten Nachkommateil verringern}
- inc bx {und Vorkommateil erh”hen}
- @kein_ueberlauf:
- inc x {auch x weiterz„hlen}
- mov ax,x
- cmp ax,x2 {Ende erreicht ?}
- jb @lp {nein, dann n„chsten Durchlauf}
- end;
- Begin
- asm mov ax,0013h; int 10h end;{Mode 13h einschalten}
- Line(10,10,100,50,1); {Linie ziehen}
- ReadLn;
- Textmode(3);
- End.{$N-} {Coprozessor aus}
- Uses Crt,Tools;
- Var phi, {Winkel}
- x,y:Word; {Koordinaten}
- Zeichen:Byte; {benutztes Zeichen}
- Sinus:Array[1..360] of Word;{nimmt die Sinus-Tabelle auf}
- Procedure Sinus_Real; {zeichnet 26 mal einen Kreis}
- Begin
- For Zeichen:=Ord('A') to Ord('Z')do {26 Durchl„ufe}
- For phi:=1 to 360 do Begin
- x:=Trunc(Round(Sin(phi/180*pi)*20+40)); {x-Koordinate berechnen}
- y:=Trunc(Round(Cos(phi/180*pi)*10+12)); {y-Koordinate berechnen}
- mem[$b800:y*160+x*2]:=Zeichen; {Zeichen auf den Bildschirm}
- End;
- End;
- Procedure Sinus_neu; {zeichnet 26 mal einen Kreis}
- Begin
- For Zeichen:=Ord('A') to Ord('Z')do {26 Durchl„ufe}
- For phi:=1 to 360 do Begin
- x:=Sinus[phi]+40; {x-Koordinate berechnen}
- If phi<=270 Then {y-Koordinate berechnen}
- y:=Sinus[phi+90] div 2 + 12 Else {Kosinus als verschobenen Sinus}
- y:=Sinus[phi-270] div 2 + 12;
- mem[$b800:y*160+x*2]:=Zeichen; {Zeichen auf den Bildschirm}
- End;
- End;
- Begin
- Sin_Gen(Sinus,360,20,0); {Sinus-Tabelle vorbereiten}
- ClrScr; {Bildschirm l”schen}
- Sinus_real; {Kreise zeichnen}
- ClrScr; {Bildschirm l”schen}
- Sinus_neu; {Kreise zeichnen}
- End.
- unit modexlib; {Header fr modexlib.asm}
- Interface
- Var
- Vscreen:Pointer; {Zeiger auf Quellbereich fr p13_2_modex}
- vpage:Word; {Offset der aktuell unsichtbaren Seite}
- palette:Array[0..256*3-1] of Byte; {VGA - Palette}
- Procedure Init_ModeX; {ModeX einschalten}
- Procedure Enter400; {von Mode X nach 400-Zeilen schalten}
- Procedure Double; {virtuelle horiz. Aufl”sung von 640 ein}
- Procedure P13_2_ModeX(start,pic_size:word); {Bild auf Mode X - Screen kop.}
- Procedure CopyScreen(Ziel,Quelle:Word); {Quell-Seite nach Ziel-Seite kop.}
- Procedure Copy_Block(Ziel,Quelle,Breite,Hoehe:Word);
- {kopiert Block von Quell-Offset nach Ziel}
- Procedure ClrX(pmask:byte); {Mode X - Bildschirm l”schen}
- Procedure Split(Row:Byte); {Screen-Splitting in Zeile Row}
- Procedure Squeeze; {Bild zusammenfahren von oben und unten}
- Procedure SetStart(t:Word); {Startadresse des sichtbaren Bilds setzen}
- Procedure Switch; {zwischen Seite 0 und 1 hin und herschalten}
- Procedure WaitRetrace; {wartet auf Vertikal-Retrace}
- Procedure SetPal; {kopiert Palette in VGA-DAC}
- Procedure GetPal; {liest Palette aus VGA-DAC aus}
- Procedure Fade_Out; {blendet Bild aus}
- Procedure Fade_To(Zielpal:Array of Byte; Schritt:Byte);
- {blendet von Palette nach Zielpal}
- Procedure Pal_Rot(Start,Ziel:Word);
- {Rotiert Palettenteil um 1,
- wenn Start>Ziel nach oben, sonst unten}
- {interne Prozeduren:}
- Procedure Screen_Off; {schaltet Bildschirm aus}
- Procedure Screen_On; {schaltet Bildschirm wieder ein}
- Procedure CRTC_Unprotect; {erm”glicht Zugriff auf Horizontal-Timing}
- Procedure CRTC_Protect; {verbietet Zugriff wieder}
- Procedure Init_Mode13; {schaltet Mode 13h ein}
- Procedure Show_Pic13; {Kopiert VScreen auf Mode 13h}
- Procedure Make_bw(Var WorkPal:Array of Byte); {Palette auf schwarz/weiá}
- Implementation
- Procedure Init_ModeX;external;
- Procedure Enter400;external;
- Procedure Double;external;
- Procedure P13_2_ModeX;external;
- Procedure CopyScreen;external;
- Procedure Copy_Block;external;
- Procedure ClrX;external;
- Procedure Split;external;
- Procedure Squeeze;external;
- Procedure SetStart;external;
- Procedure Switch;external;
- Procedure WaitRetrace;external;
- Procedure SetPal;external;
- Procedure GetPal;external;
- Procedure Fade_Out;external;
- Procedure Fade_To;external;
- Procedure Pal_Rot;external;
- {$l modexlib}
- Procedure Screen_Off;
- Begin
- Port[$3c4]:=1; {Register 1 des TS (TS Mode) selektieren}
- Port[$3c5]:=Port[$3c5] or 32; {Bit 5 (Screen Off) setzen}
- End;
- Procedure Screen_On;
- Begin
- Port[$3c4]:=1; {Register 1 des TS (TS Mode) selektieren}
- Port[$3c5]:=Port[$3c5] and not 32; {Bit 5 (Screen Off l”schen}
- End;
- Procedure CRTC_UnProtect;
- Begin
- Port[$3d4]:=$11; {Register 11h des CRTC (Vertical Sync End)}
- Port[$3d5]:=Port[$3d5] and not $80 {Bit 7 (Protection Bit) l”schen}
- End;
- Procedure CRTC_Protect;
- Begin
- Port[$3d4]:=$11; {Register 11h des CRTC (Vertical Sync End)}
- Port[$3d5]:=Port[$3d5] or $80 {Bit 7 (Protection Bit) setzen}
- End;
- Procedure Init_Mode13;assembler;
- asm
- mov ax,13h
- int 10h
- End;
- Procedure Show_Pic13; {Kopiert VScreen auf Mode 13h}
- Begin
- Move(Vscreen^,Ptr($a000,0)^,64000);
- End;
- Procedure Make_bw; {Palette nach schwarz/weiá reduzieren}
- Var i,sum:Word; {Wertung: 30% rot, 59% grn, 11% blau}
- Begin
- For i:=0 to 255 do Begin
- Sum:=Round(WorkPal[i*3]*0.3 + WorkPal[i*3+1]*0.59 + WorkPal[i*3+2]*0.11);
- FillChar(WorkPal[i*3],3,Sum); {Werte eintragen}
- End;
- End;
- Begin
- End.
- Uses Crt,ModeXLib,Gif;
- Var slow_flag:Boolean; {zu Steuerung der langsamen Verl„ufe}
- Begin
- Init_Mode13; {Mode 13h ein}
- LoadGif('palrot'); {Bild laden und anzeigen}
- Show_Pic13;
- Repeat
- Pal_Rot(16,47); {"Schachbrett" bewegen}
- If slow_flag Then Begin {bei jedem 2. Durchlauf:}
- Pal_Rot(63,48); {"Springbrunnen" bewegen}
- Pal_Rot(88,64); {"Radar" bewegen}
- End;
- slow_flag:=not slow_flag; {abwechselnd "Springbrunnen" und "Radar"}
- {erm”glichen und sperren}
- WaitRetrace; {Synchronisation}
- SetPal; {die rotierte Palette setzen}
- Until KeyPressed; {bis Tastendruck}
- TextMode(3);
- End.
- {$G+}
- Uses Crt,Sprites,ModeXLib,Gif,Tools;
- Procedure PutScalSprt(pg_ofs,x,y,scale_y:Integer;qsprite:spritetyp);
- var planecount, {Z„hler der bereits kopierten Planes}
- planemask:Byte; {maskiert Write-Plane in TS-Register 2}
- Skip, {Anzahl zu berspringender Bytes}
- ofs, {aktueller Offset im Bildschirmspeicher}
- plane, {Nummer der aktuellen Plane}
- Breite, {Breite zu kopierender Bytes in einer Zeile,}
- dty:Word; {H”he}
- quelle:Pointer; {Zeiger auf Grafikdaten, wenn ds ver„ndert}
- ppp:Array[0..3] of Byte; {Anzahl Pixel pro Plane}
- rel_y, {Nachkommateil der rel. y-Position}
- add_y:Word; {Nachkommawert des Summanden}
- direction:Integer; {Bewegungs-Richtung (+/- 80)}
- i:Word; {lokaler Schleifenz„hler}
- Begin
- if (x + qsprite.dtx > 319) {Clipping ? dann Abbruch}
- or (x < 0)
- or (y + qsprite.dty*scale_y div 100 > 199) or (y < 0) then exit;
- add_y:=100-abs(scale_y); {Summanden berechnen}
- if scale_y < 0 then direction:=-80 else direction:=80;
- {Richtung festlegen}
- Quelle:=qsprite.adr; {Zeiger Grafik-Daten}
- dty:=qsprite.dty; {lokale Hoehen-Variable laden}
- plane:=x mod 4; {Start-Plane}
- ofs:=pg_ofs+80*y+(x div 4); {und -Offset berechnen}
- Breite:=0; {Breite und Skip vorinitialisieren}
- Skip:=0;
- i:=qsprite.dtx shr 2; {Anzahl glatter Viererbl”cke}
- ppp[0]:=i;ppp[1]:=i; {entspricht Mindestanzahl zu kop. Bytes}
- ppp[2]:=i;ppp[3]:=i;
- For i:=1 to qsprite.dtx and 3 do{"berstehende" Pixel in ppp vermerken}
- Inc(ppp[(plane+i - 1) and 3]);{beginnend mit Startplane Pixel anfgen}
- asm
- push ds {ds sichern}
- mov ax,0a000h {Zielsegment (VGA) laden}
- mov es,ax
- lds si,quelle {Quelle (Zeiger auf Grafikdaten) nach ds:si}
- mov cx,plane {Start-Planemaske erstellen}
- mov ax,1 {dazu Bit 0 um Plane nach links schieben}
- shl ax,cl
- mov planemask,al {Maske sichern}
- shl al,4 {auch in oberes Nibble eintragen}
- or planemask,al
- mov planecount,4 {4 Planes zu kopieren}
- @lplane: {wird einmal pro Plane durchlaufen}
- mov cl,byte ptr plane {aktuelle Plane laden}
- mov di,cx {in di}
- mov cl,byte ptr ppp[di] {cx mit zugeh”riger ppp-Anzahl laden}
- mov byte ptr Breite,cl {Skip jeweils neu ausrechnen}
- mov ax,direction {dazu Differenz Direction-Breite bilden}
- sub ax,cx
- mov skip,ax {und in skip schreiben}
- mov rel_y,0 {Start wieder bei y=0,0}
- mov cx,Breite {cx mit Breite laden}
- or cl,cl {Breite 0, dann Plane fertig}
- je @plane_fertig
- mov di,ofs {Zieloffset im Bildschirmspeicher nach di}
- mov ah,planemask {Planemaske auf bit [0..3] reduzieren}
- and ah,0fh
- mov al,02h {und ber TS - Register 2 (Write Plane Mask)}
- mov dx,3c4h {setzen}
- out dx,ax
- mov bx,dty {y-Z„hler initialisieren}
- @lcopy_y: {y-Schleife, pro Zeile einmal durchlaufen}
- @lcopy_x: {x-Schleife, pro Punkt einmal durchlaufen}
- lodsb {Byte holen}
- or al,al {wenn 0, dann berspringen}
- je @Wert0
- stosb {ansonsten: setzen}
- @entry:
- loop @lcopy_x {und Schleife weiter}
- mov ax,rel_y {Summanden auf Nachkommateil}
- add ax,add_y
- cmp ax,100 {Vorkommastelle erh”ht ?}
- jb @noaddovfl {nein, dann weiter}
- sub ax,100 {ansonsten Nachkommastelle zurcksetzen}
- sub di,direction {und in n„chste/vorherige Zeile}
- @noaddovfl:
- mov rel_y,ax {und in Nachkommateil zurckschreiben}
- dec bx {y-Z„hler weiter}
- je @plane_fertig {y-Z„hler = 0, dann n„chste Plane}
- add di,skip {sonst auf n„chsten Zeilenanfang springen}
- mov cx,Breite {x-Z„hler reinitialisieren,}
- jmp @lcopy_y {wieder in y-Schleife springen}
- @wert0: {Sprite-Farbe 0:}
- inc di {Zielbyte berspringen}
- jmp @entry {und wieder in Schleife zurck}
- @plane_fertig: {hier ist y-Schleife beendet}
- rol planemask,1 {n„chste Plane maskieren}
- mov cl,planemask {plane 0 selektiert ?}
- and cx,1 {(Bit 1 gesetzt), dann}
- add ofs,cx {Zieloffset erh”hen um 1 (Bit 1 !)}
- inc plane {Plane-Nummer (Index in ppp) weiter}
- and plane,3 {auf 0 bis 3 reduzieren}
- dec planecount {schon 4 Planes kopiert ?, dann Ende}
- jne @lplane
- pop ds {ds restaurieren, und Tschá}
- End;{asm}
- End;
- Var Logo:SpriteTyp;
- Sinus:Array[0..99] of Word;
- Hoehe:Integer;
- i:Word;
- Begin
- Init_ModeX; {Mode X einschalten}
- LoadGif('sprites'); {Bild mit Logo laden}
- GetSprite(88+ 6*320,150,82,Logo); {Logo initialisieren}
- LoadGif('phint'); {Hintergrundbild laden}
- p13_2_ModeX(48000,16000); {und auf Hintergrundseite kopieren}
- Sin_Gen(Sinus,100,100,0); {Sinus vorberechnen}
- I:=0; {Index im Sinus auf 0}
- repeat
- Inc(i); {Index weiterz„hlen}
- Hoehe:=Integer(Sinus[i mod 100]); {Hoehe aus Sinus holen}
- CopyScreen(vpage,48000); {Hintergrund l”schen}
- PutScalSprt(vpage,85,100-Hoehe *84 div 200,Hoehe,Logo);
- {Sprite skaliert auf aktuelle Seite kopieren}
- Switch; {auf diese Seite umschalten}
- WaitRetrace; {und auf den Retrace warten}
- Until KeyPressed;
- ReadLn;
- TextMode(3); {normalen Text-Mode ein}
- End.
- uses crt,Gif,ModeXLib;
- Var x, {derzeitiger Offset in x-Richtung}
- x_dir, {gibt Scroll Richtung fr x-an}
- y, {derzeitiger Offset fr y-Richtung}
- y_dir:word; {gibt Scroll Richtung fr y an}
- split_line:word; {derzeitige Position der Split-Line}
- split_dir:word; {gibt Bewegungsrichtung der Split-Line an}
- Begin
- Init_ModeX; {Mode X einschalten}
- double; {160-Byte Modus einschalten}
- Screen_Off; {Bildschirm aus}
- LoadGif_Pos('640400',160*50);{groáes Bild an Position (0/50) laden}
- p13_2_ModeX(vram_pos,rest div 4); {Rest in VGA-Speicher kopieren}
- LoadGif('corner'); {kleines Bild an Position (0/0) laden}
- p13_2_ModeX(0,160*50); {und auf Bildschirm kopieren}
- Screen_On; {Bildschirm ein}
- split_line:=150; {Split zun„chst auf Zeile 150 setzen}
- split_dir:=1; {Split-Line zun„chst nach unten verschieben}
- x:=1; {x-Beginn mit Spalte 1}
- x_dir:=1; {x-Richtung 1 Byte pro Durchlauf}
- y:=160; {y-Beginn mit Zeile 1}
- y_dir:=160; {y-Richtung +160 Byte pro Durchlauf}
- Repeat
- Inc(x,x_dir); {x-Bewegung}
- Inc(y,y_dir); {y-Bewegung}
- Inc(Split_line,Split_dir); {Split Line bewegen}
- WaitRetrace; {Auf Retrace warten}
- SetStart(50*160+y+x); {und neuen Start in Register schreiben,}
- {dabei ersten 50 Zeilen berspringen}
- Split(Split_line); {Bildschirm an Split Line splitten}
- if (x >= 80) {x-Rand erreicht -> x-Richtung umdrehen}
- or (x <= 1) Then x_dir:=-x_dir;
- if (y >= 200*160) {y-Rand erreicht -> y-Richtung umdrehen}
- or (y <= 160) Then y_dir:=-y_dir;
- if (split_line >= 200) {hat Split Rand erreicht -> Richtung wechseln}
- or (split_line <= 150) then split_dir:=-split_dir
- Until KeyPressed; {laufe, bis Taste gedrckt}
- TextMode(3);
- End.
- Uses Crt,Gif,ModeXLib;
- Var x, {derzeitiger Offset in x-Richtung}
- x_dir, {gibt Scroll Richtung fr x-an}
- y, {derzeitiger Offset fr y-Richtung}
- y_dir:word; {gibt Scroll Richtung fr y an}
- Begin
- Init_ModeX; {Mode X einschalten}
- double; {160-Byte Modus ein (640*400 Punkte gesamt}
- LoadGif('640400'); {Bild laden}
- p13_2_ModeX(vram_pos,rest div 4); {Rest des Bildes in Bildschirmspeicher}
- x:=1; {x-Beginn mit Spalte 1}
- x_dir:=1; {x-Richtung 1 Byte pro Durchlauf}
- y:=160; {y-Beginn mit Zeile 1}
- y_dir:=160; {y-Richtung +160 Byte pro Durchlauf}
- Repeat
- Inc(x,x_dir); {x-Bewegung}
- Inc(y,y_dir); {y-Bewegung}
- WaitRetrace; {Auf Retrace warten}
- SetStart(y+x); {und neuen Start in Register schreiben}
- if (x >= 80) {x-Rand erreicht -> x-Richtung umdrehen}
- or (x <= 1) Then x_dir:=-x_dir;
- if (y >= 200*160) {y-Rand erreicht -> y-Richtung umdrehen}
- or (y <= 160) Then y_dir:=-y_dir;
- Until KeyPressed; {laufe, bis Taste gedrckt}
- TextMode(3);
- End.
- Uses ModeXLib,Crt;
- Var x, {x-Position in Pixel}
- x_dir, {x-Richtung}
- y, {y-Position in Pixel}
- y_dir:Word; {y-Richtung}
- Procedure Wait_In_Display;assembler;
- {Gegenstck zu Wait_In_Retrace, wartet auf Bildaufbau durch Kathodenstrahl}
- asm
- mov dx,3dah {Input Status 1}
- @wait2:
- in al,dx
- test al,8h
- jnz @wait2 {Display ein ? -> dann fertig}
- End;
- Procedure Wait_In_Retrace;assembler;
- {wartet auf Retrace, setzt auáerdem durch Lesezugriff
- auf Input Status 1 den ATC Flip-Flop zurck}
- asm
- mov dx,3dah {Input Status 1}
- @wait1:
- in al,dx
- test al,8h
- jz @wait1 {Retrace aktiv ? -> dann fertig}
- End;
- Procedure FillScreen;
- {Fllt Bildschirmspeicher mit Testbild der GrӇe 160*50 Zeichen}
- var i:word;
- Begin
- For i:=0 to 160*50 do Begin {Zeichen-Schleife}
- If i mod 10 <> 0 Then {Spaltenz„hler schreiben ?}
- mem[$b800:i shl 1]:= {nein, dann '-'}
- Ord('-') Else
- mem[$b800:i shl 1]:= {ja, dann Spaltennummer in Zehnern}
- ((i mod 160) div 10) mod 10 + Ord('0');
- If i mod 160 = 0 Then {Spalte 0 ? -> Zeilenz„hler schreiben}
- mem[$b800:i shl 1]:=(i div 160) mod 10 + Ord('0');
- End;
- End;
- Procedure V_Pan(n:Byte);assembler;
- {fhrt vertikales Paning durch}
- asm
- mov dx,3d4h {CRTC Register 8 (Inittial Row Adress)}
- mov al,8
- mov ah,n {Paning-Weite setzen}
- out dx,ax
- End;
- Procedure H_Pan(n:Byte);assembler;
- {fhrt vertikales Paning durch}
- asm
- mov dx,3c0h {ATC Index/Data Port}
- mov al,13h or 32d {Register 13h (Horizontal Pixel Paning)}
- out dx,al {anw„hlen; Bit 5 (Palette RAM Address Source)}
- mov al,n {setzen, um Bildschirm nicht abzuschalten}
- or al,32d {Paning-Wert schreiben}
- out dx,al
- End;
- Begin
- TextMode(3); {BIOS-Modus 3 (80*25 Zeichen, Color) setzen}
- FillScreen; {Testbild aufbauen}
- portw[$3d4]:=$5013; {doppelte virtuelle Screen-Breite(160 Zeichen)}
- x:=0; {Koordinaten und Richtungen initialisieren}
- x_dir:=1;
- y:=0;
- y_dir:=1;
- Repeat
- Inc(x,x_dir); {Bewegung in x- und y-Richtung}
- Inc(y,y_dir);
- If (x<=0) or (x>=80*9) {Umkehr an den R„ndern}
- Then x_dir:=-x_dir;
- if (y<=0) or (y>=25*16)
- Then y_dir:=-y_dir;
- Wait_in_Display; {warten, bis Bildaufbau l„uft}
- SetStart((y div 16 *160) {Startadresse setzen (Grobscrolling}
- + x div 9);
- Wait_in_Retrace; {warten, bis Retrace aktiv}
- V_Pan(y mod 16); {Vertikal-Panning (Feinscrolling)}
- H_Pan((x-1) mod 9); {Horizontal-Panning (Feinscrolling)}
- Until KeyPressed; {warten auf Taste}
- TextMode(3); {und normalen Videomodus setzen}
- End.
- Uses Crt,Gif,ModeXLib;
- Var y:Word; {derzeitiger Wert der Linear Start. Adress}
- y_dir:Integer; {gibt Scroll Richtung an}
- Begin
- Init_ModeX; {Mode X einschalten}
- Screen_Off; {Bildschirm aus}
- LoadGif('320800'); {Bild laden}
- p13_2_ModeX(vram_pos,rest div 4);
- Screen_On;
- y:=600*80; {Beginn mit Zeile 1}
- y_dir:=-80; {Bewegungsrichtung +80 Byte pro Durchlauf}
- Repeat
- Inc(y,y_dir); {Bewegung}
- WaitRetrace; {Auf Retrace warten}
- SetStart(y); {und neuen Start in Register schreiben}
- if (y >= 600*80) {Rand erreicht -> Richtung umdrehen}
- or (y <= 80) Then y_dir:=-y_dir;
- Until KeyPressed; {laufe, bis Taste gedrckt}
- TextMode(3);
- End.
- Uses Crt,Tools,ModeXLib,Gif,Font;
- Var Sinus:Array[0..127] of Word;{Sinus-Tabelle fr vertikale Schwingung}
- t:Word; {"Zeit", Position innerhalb des Sinus}
- Begin
- Init_ModeX; {Mode X ein}
- LoadGif('pfont4'); {Zeichensatz laden}
- p13_2_ModeX(48000,16000); {und auf Seite 3 kopieren}
- Sin_Gen(Sinus,128,Scrl_y div 2,Scrl_y div 2);
- {Sinus-Tabelle fr vert. Bewegung vorbereiten}
- t:=0; {Zeit startet bei 0}
- Repeat
- WaitRetrace; {Synchronisation}
- Scrl_Move; {sichtbaren Teil nach rechts bewegen}
- Scrl_Append; {rechts neue Spalte anh„ngen}
- SetStart(Sinus[t and 127]*80); {fr vert. Bewegung sorgen}
- Inc(t); {weiter in Sinus-Tabelle}
- Until KeyPressed;
- TextMode(3);
- End.
- Uses Crt,Gif,ModeXLib;
- Var i:Word;
- begin
- Init_ModeX; {Mode X initialisieren}
- LoadGif('beule'); {erstes Bild (Hintergrund) laden}
- p13_2_ModeX(16000,16000);
- LoadGif('corner'); {zweites Bild laden}
- p13_2_modex(0,16000);
- SetStart(16000); {Hintergrund anzeigen}
- Repeat
- For i:=200 downto 0 do Begin{Split-Line nach oben ziehen}
- WaitRetrace;
- Split(i);
- If KeyPressed Then Exit;
- End;
- For i:=0 to 200 do Begin {Split-Line nach unten}
- WaitRetrace;
- Split(i);
- If KeyPressed Then Exit;
- End;
- Until KeyPressed;
- TextMode(3);
- End.
- {$G+}
- Unit Sprites;
- Interface
- Type SpriteTyp=Record {Aufbau eines Sprite-Datenblocks}
- Adr:Pointer; {Zeiger auf Grafik-Daten}
- dtx,dty:Word; {Breite und H”he in Pixel}
- px,py, {gegenw„rtige Position, optional *}
- sx,sy:Integer; {gegenw„rtige Geschwindigkeit, optional *}
- End;
- {*: optional bedeutet, daá die Sprite-Routinen GetSprite und PutSprite
- von diesen Angaben keinen Gebrauch machen, die Variablen dienen lediglich
- dazu, eine Steuerung seitens des Hauptprogramms zu erleichtern}
- Procedure GetSprite(Ofs,dtx,dty:Word;var zSprite:SpriteTyp);
- {lies ein Sprite aus vscreen-Offset ofs, mit Breite dtx und H”he dty,
- zsprite ist der Sprite-Record, in dem Sprite gespeichert werden soll}
- Procedure PutSprite(pg_ofs,x,y:Integer;qsprite:spritetyp);
- {kopiert Sprite aus Hauptspeicher (Lage und GrӇe werden qsprite entnommen)
- auf Bildschirmspeicher Seite pg an Position (x/y)}
- Implementation
- Uses ModeXLib;
- Var i:Word;
- Procedure GetSprite;
- Var ppp:Array[0..3] of Byte; {Tabelle mit Anzahl zu kopierender Pixel}
- {pro Plane}
- Skip:word; {Anzahl zu berspringender Bytes}
- Plane_Count:Word; {Z„hler der bereits kopierten Planes}
- Begin
- GetMem(zsprite.adr,dtx*dty); {Hauptspeicher allokieren}
- zsprite.dtx:=dtx; {im Sprite-Record Breite und H”he vermerken}
- zsprite.dty:=dty;
- i:=dtx shr 2; {Anzahl glatter Viererbl”cke}
- ppp[0]:=i;ppp[1]:=i; {entspricht Mindestanzahl zu kop. Bytes}
- ppp[2]:=i;ppp[3]:=i;
- For i:=1 to dtx and 3 do {"berstehende" Pixel in ppp vermerken}
- Inc(ppp[(i-1) and 3]); {beginnend mit Startplane Pixel anfgen}
- Plane_Count:=4; {4 Planes kopieren}
- asm
- push ds
- mov di,word ptr zsprite {zun„chst Zeiger auf Daten-Block laden}
- les di,[di] {Zeiger auf Grafikdaten in es:di laden}
- lea bx,ppp {bx zeigt auf ppp-Array}
- lds si,vscreen {Zeiger auf Bild laden}
- add Ofs,si {Offset der eigentlichen Sprite-Daten dazu}
- @lcopy_plane: {wird einmal pro Plane durchlaufen}
- mov si,ofs {si mit Startadresse der Sprite-Daten laden}
- mov dx,dty {y-Z„hler mit Zeilenzahl laden}
- xor ah,ah {ah l”schen}
- mov al,ss:[bx] {al mit aktuelem ppp-Eintrag laden}
- shl ax,2 {es werden jeweils 4er-Bl”cke bewegt}
- sub ax,320 {Differenz zur 320 bilden}
- neg ax {aus ax-320 320-ax machen}
- mov skip,ax {Wert in Skip sichern}
- @lcopy_y: {wird einmal pro Zeile durchlaufen}
- mov cl,ss:[bx] {Breite aus ppp-Array laden}
- @lcopy_x: {wird einmal pro Punkt durchlaufen}
- movsb {Byte kopieren}
- add si,3 {auf n„chsten Punkt dieser Plane}
- dec cl {alle Punkte dieser Zeile kopieren}
- jne @lcopy_x
- add si,skip {danach auf Anfang der n„chsten Zeile}
- dec dx {alle Zeilen kopieren}
- jne @lcopy_y
- inc bx {auf n„chsten ppp-Eintrag positionieren}
- inc ofs {auf neuen Plane-Start positionieren}
- dec plane_count {alle Planes kopieren}
- jne @lcopy_plane
- pop ds
- End;
- End;
- Procedure PutSprite;
- var plane_count, {Z„hler der bereits kopierten Planes}
- planemask:Byte; {maskiert Write-Plane in TS-Register 2}
- Skip, {Anzahl zu berspringender Bytes}
- ofs, {aktueller Offset im Bildschirmspeicher}
- plane, {Nummer der aktuellen Plane}
- Breite, {Breite zu kopierender Bytes in einer Zeile,}
- dty:Word; {H”he}
- quelle:Pointer; {Zeiger auf Grafikdaten, wenn ds ver„ndert}
- clip_lt, clip_rt:integer; {Anzahl links und rechts berstehender PIXEL}
- clipakt_lt, {bei aktueller Plane aktive Anzahl}
- clipakt_rt, {berstehender BYTES}
- clip_dn,clip_up:Word; {Anzahl oben und unten berstehender ZEILEN}
- ppp:Array[0..3] of Byte; {Anzahl Pixel pro Plane}
- cpp:Array[0..3] of Byte; {berstehende BYTES pro Plane}
- Begin
- if (x > 319) or {Darstellung berflssig, }
- (x+qsprite.dtx < 0) or {weil gar nicht im Bild ?}
- (y > 199) or
- (y+qsprite.dty < 0) then exit;
- clip_rt:=0; {im Normalfall kein Clipping}
- clip_lt:=0; {-> alle Clipping-Variablen auf 0}
- clip_dn:=0;
- clip_up:=0;
- clipakt_rt:=0;
- clipakt_lt:=0;
- with qsprite do begin
- if y+dty > 200 then begin {erster Clipping Fall: unten}
- clip_dn:=(y+dty-200); {berstehende Zeilen vermerken}
- dty:=200-y; {und Sprite-H”he reduzieren}
- End;
- if y<0 then begin {zweiter Clipping Fall: oben}
- clip_up:=-y; {berstehende Zeilen vermerken}
- dty:=dty+y; {und Sprite-H”he reduzieren}
- y:=0; {Start-y ist 0, weil oberer Bildrand}
- End;
- if x+dtx > 320 then begin {dritter Clipping Fall: rechts}
- clip_rt:=x+dtx-320; {berstehende Pixel vermerken}
- dtx:=320-x; {Breite reduzieren}
- End;
- if x<0 then begin {vierter Clipping Fall: links}
- clip_lt:=-x; {berstehende Pixel vermerken}
- plane:=4-(clip_lt mod 4); {neue Startplane fr Spalte 0 berechnen}
- plane:=plane and 3; {diese auf 0..3 reduzieren}
- ofs:=pg_ofs+80*y+((x+1) div 4) - 1; {Ofs auf korrekten 4er-Block setzen}
- x:=0; {Darstellung in Spalte beginnen}
- End Else Begin {rechts kein Clipping ?}
- plane:=x mod 4; {dann konventionelle Berechnung von Plane}
- ofs:=pg_ofs+80*y+(x div 4); {und Offset}
- End;
- End;
- Quelle:=qsprite.adr; {Zeiger Grafik-Daten}
- dty:=qsprite.dty; {und H”he in lok. Variablen sichern}
- Breite:=0; {Breite und Skip vorinitialisieren}
- Skip:=0;
- i:=qsprite.dtx shr 2; {Anzahl glatter Viererbl”cke}
- ppp[0]:=i;ppp[1]:=i; {entspricht Mindestanzahl zu kop. Bytes}
- ppp[2]:=i;ppp[3]:=i;
- For i:=1 to qsprite.dtx and 3 do{"berstehende" Pixel in ppp vermerken}
- Inc(ppp[(plane+i - 1) and 3]);{beginnend mit Startplane Pixel anfgen}
- i:=(clip_lt+clip_rt) shr 2;
- cpp[0]:=i;cpp[1]:=i; {Clipping-Vorgabe : alle Seiten 0}
- cpp[2]:=i;cpp[3]:=i;
- For i:=1 to clip_rt and 3 do {wenn rechts Clipping entsprechende Anzahl}
- Inc(cpp[i-1]); {in Planes eintragen}
- For i:=1 to clip_lt and 3 do {wenn rechts Clipping entsprechende Anzahl}
- Inc(cpp[4-i]); {in Planes eintragen}
- asm
- mov dx,3ceh {GDC Register 5 (GDC Mode)}
- mov ax,4005h {auf Write Mode 0 setzen}
- out dx,ax
- push ds {ds sichern}
- mov ax,0a000h {Zielsegment (VGA) laden}
- mov es,ax
- lds si,quelle {Quelle (Zeiger auf Grafikdaten) nach ds:si}
- mov cx,plane {Start-Planemaske erstellen}
- mov ax,1 {dazu Bit 0 um Plane nach links schieben}
- shl ax,cl
- mov planemask,al {Maske sichern}
- shl al,4 {auch in oberes Nibble eintragen}
- or planemask,al
- mov plane_count,4 {4 Planes zu kopieren}
- @lplane: {wird einmal pro Plane durchlaufen}
- mov cl,byte ptr plane {aktuelle Plane laden}
- mov di,cx {in di}
- mov cl,byte ptr ppp[di] {cx mit zugeh”riger ppp-Anzahl laden}
- mov byte ptr Breite,cl {Skip jeweils neu ausrechnen}
- mov ax,80 {dazu Differenz 80-Breite bilden}
- sub al,cl
- mov byte ptr skip,al {und in skip schreiben}
- mov al,byte ptr cpp[di] {Plane-spezifische Clipping-Weite laden}
- cmp clip_lt,0 {wenn links kein Clipping, weiter mit rechts}
- je @rechts
- mov clipakt_lt,ax {in clip_akt_lt sichern}
- sub Breite,ax {Breite zu kopierender Bytes reduzieren}
- jmp @clip_rdy {rechts kein Clipping}
- @rechts: {wenn links kein Clipping}
- mov clipakt_rt,ax {dazu Clipping fr alle Planes, in clip_akt}
- @clip_rdy:
- mov ax,Breite {Gesamtbreite in Byte berechnen}
- add ax,clipakt_rt
- add ax,clipakt_lt
- mul clip_up {mit Anzahl Zeilen des oberen Clipping mul.}
- add si,ax {diese Bytes werden nicht dargestellt}
- mov cx,Breite {cx mit Breite laden}
- or cl,cl {Breite 0, dann Plane fertig}
- je @plane_fertig
- mov di,ofs {Zieloffset im Bildschirmspeicher nach di}
- mov ah,planemask {Planemaske auf bit [0..3] reduzieren}
- and ah,0fh
- mov al,02h {und ber TS - Register 2 (Write Plane Mask)}
- mov dx,3c4h {setzen}
- out dx,ax
- mov bx,dty {y-Z„hler initialisieren}
- @lcopy_y: {y-Schleife, pro Zeile einmal durchlaufen}
- add si,clipakt_lt {Quellzeiger um linkes Clipping weiter}
- add di,clipakt_lt {auch Zielzeiger}
- @lcopy: {x-Schleife, pro Punkt einmal durchlaufen}
- lodsb {Byte holen}
- or al,al {wenn 0, dann berspringen}
- je @Wert0
- stosb {ansonsten: setzen}
- @entry:
- loop @lcopy {und Schleife weiter}
- add si,clipakt_rt {nach kompletter Zeile rechtes Clipping}
- dec bx {y-Z„hler weiter}
- je @plane_fertig {y-Z„hler = 0, dann n„chste Plane}
- add di,skip {sonst auf n„chsten Zeilenanfang springen}
- mov cx,Breite {x-Z„hler reinitialisieren,}
- jmp @lcopy_y {wieder in y-Schleife springen}
- @wert0: {Sprite-Farbe 0:}
- inc di {Zielbyte berspringen}
- jmp @entry {und wieder in Schleife zurck}
- @plane_fertig: {hier ist y-Schleife beendet}
- mov ax,Breite {Gesamtbreite in Byte berechnen}
- add ax,clipakt_rt
- add ax,clipakt_lt
- mul clip_dn {mit Anzahl Zeilen des unteren Clipping mul.}
- add si,ax {diese Bytes werden nicht dargestellt}
- rol planemask,1 {n„chste Plane maskieren}
- mov cl,planemask {plane 0 selektiert ?}
- and cx,1 {(Bit 1 gesetzt), dann}
- add ofs,cx {Zieloffset erh”hen um 1 (cx Bit 1 !)}
- inc plane {Plane-Nummer (Index in ppp) weiter}
- and plane,3 {auf 0 bis 3 reduzieren}
- dec plane_count {schon 4 Planes kopiert ?, dann Ende}
- jne @lplane
- pop ds {ds restaurieren, und Tschá}
- End;{asm}
- End;
- Begin
- End.
- Uses Crt,Gif,ModeXLib,Sprites;
- Const Sprite_Anzahl=3; {Anzahl im Programm verwendeter Sprites}
- Var Sprite:Array[1..Sprite_Anzahl] of SpriteTyp;
- {Daten-Records der Sprites}
- i:Word; {Z„hler}
- Begin
- Init_ModeX; {Mode X einschalten}
- LoadGif('sprites'); {Bild mit den drei Sprites laden}
- GetSprite(62 +114*320,58,48,Sprite[1]); {Koordinaten (62/114), Breite 58*48}
- GetSprite(133+114*320,58,48,Sprite[2]); {(133/114), 58*48}
- GetSprite(203+114*320,58,48,Sprite[3]); {(203/114), 58*48}
- {die drei Sprites laden}
- LoadGif('phint'); {Hintergrundbild laden}
- p13_2_ModeX(48000,16000); {und auf Hintergrundseite kopieren}
- With Sprite[1] do Begin {Koordinaten und Geschwindigkeiten}
- px:=160;py:=100; {aller drei Sprites auf (willkrliche Werte)}
- sx:=1;sy:=2;
- End;
- With Sprite[2] do Begin
- px:=0;py:=0;
- sx:=1;sy:=-1;
- End;
- With Sprite[3] do Begin
- px:=250;py:=150;
- sx:=-2;sy:=-1;
- End;
- Repeat
- CopyScreen(vpage,48000); {Hintergrundbild auf aktuelle Seite}
- For i:=1 to Sprite_Anzahl do{fr alle 3 Sprites durchlaufen}
- With Sprite[i] do Begin
- Inc(px,sx); Inc(py,sy); {Bewegung}
- If (px < -dtx div 2) {am linken oder rechten Rand ? -> umkehren}
- or (px > 320-dtx div 2) Then sx:=-sx;
- If (py < -dty div 2) {am oberen oder unteren Rand ? -> umkehren}
- or (py > 200-dty div 2) Then sy:=-sy;
- PutSprite(vpage,px,py,Sprite[i]);
- {Sprite zeichnen}
- End;
- switch; {auf berechnete Seite umschalten}
- WaitRetrace; {Bildschirm darf erst nach n„chstem Retrace}
- Until KeyPressed; {wieder ver„ndert werden}
- ReadLn;
- TextMode(3);
- End.
- uses Crt,ModeXLib,Gif;
- Begin
- Init_ModeX; {Einschalten des Mode X}
- LoadGif('squeeze'); {Laden des Bilds}
- p13_2_ModeX(vram_pos,rest div 4);
- ReadLn; {Warten auf Enter}
- Squeeze; {Zusammenschieben des Bilds}
- ReadLn;
- TextMode(3);
- End.
- Uses Crt;
- Var Sterne:Array[0..500] of Record
- x,y,Ebene:Integer;
- End;
- st_nr:Word;
- Procedure PutPixel(x,y,col:word);assembler;
- {setzt Punkt (x/y) auf Farbe col (Mode 13h)}
- asm
- mov ax,0a000h {Segment laden}
- mov es,ax
- mov ax,320 {Offset = Y*320 + X}
- mul y
- add ax,x
- mov di,ax {Offset laden}
- mov al,byte ptr col {Farbe laden}
- mov es:[di],al {und Punkt setzen}
- End;
- Begin
- Randomize; {Zufallszahlen initialisieren}
- asm mov ax,13h; int 10h End; {Mode 13h setzen}
- Repeat {pro Bildaufbau einmal ausgefhrt}
- For St_nr:=0 to 500 do Begin{fr jeden Stern neue Posit. berechnen}
- With Sterne[st_nr] do Begin
- PutPixel(x,y,0); {alten Punkt l”schen}
- Dec(x,Ebene shr 5 + 1); {weiterbewegen}
- if x <= 0 Then Begin {links raus ?}
- x:=319; {dann neu initialisieren}
- y:=Random(200);
- Ebene:=Random(256);
- End;
- PutPixel(x,y,Ebene shr 4 + 16); {neuen Punkt setzen}
- End;
- End;
- Until KeyPressed; {Lauf, bis Taste gedrckt}
- TextMode(3);
- End.
- {$G+}
- Uses ModeXLib,Crt;
- Var Sterne:Array[0..500] of Record
- x,y,Ebene:Integer;
- End;
- st_nr:Word;
- vscreen:Pointer;
- vpage:Word;
- palette:Array[0..768] of Byte;
- Procedure PutPixel(x,y,col:word);assembler;
- {setzt Punkt (x/y) auf Farbe col (Mode X)}
- asm
- mov ax,0a000h {Segment laden}
- mov es,ax
- mov cx,x {Write Plane bestimmen}
- and cx,3 {als x mov 4}
- mov ax,1
- shl ax,cl {entsprechendes Bit setzen}
- mov ah,al
- mov dx,03c4h {Timing Sequenzer}
- mov al,2 {Register 2 - Write Plane Mask}
- out dx,ax
- mov ax,80 {Offset = Y*80 + X div 4}
- mul y
- mov di,ax
- mov ax,x
- shr ax,2
- add di,ax {Offset laden}
- mov al,byte ptr col {Farbe laden}
- mov es:[di],al {und Punkt setzen}
- End;
- Begin
- Randomize; {Zufallszahlen initialisieren}
- Init_ModeX;
- Repeat {pro Bildaufbau einmal ausgefhrt}
- For St_nr:=0 to 500 do Begin{fr jeden Stern neue Posit. berechnen}
- With Sterne[st_nr] do Begin
- PutPixel(x,y,0); {alten Punkt l”schen}
- Dec(x,Ebene shr 5 + 1); {weiterbewegen}
- if x <= 0 Then Begin {links raus ?}
- x:=319; {dann neu initialisieren}
- y:=Random(200);
- Ebene:=Random(256);
- End;
- PutPixel(x,y,Ebene shr 4 + 16); {neuen Punkt setzen}
- End;
- End;
- Until KeyPressed; {Lauf, bis Taste gedrckt}
- TextMode(3);
- End.
- Unit Tools;
- Interface
- procedure sin_gen(var tabelle:Array of word;periode,amplitude,offset:word);
- Procedure Draw_Ansi(Name:String);
- Implementation
- procedure sin_gen(var tabelle:Array of word;periode,amplitude,offset:word);
- {berechet eine Sinus-Tabelle der L„nge periode vor,
- legt diese im Array tabelle ab.
- Dabei wird die "H”he" in der Variablen Amplitude und
- die Lage des Nullpunkts in offset verlangt}
- Var i:Word;
- Begin
- for i:=0 to periode-1 do
- tabelle[i]:=round(sin(i*2*pi/periode)*amplitude)+offset;
- End;
- Procedure Draw_Ansi(Name:String);
- {gibt ein Ansi-File auf dem Bildschirm aus (ANSI.SYS erforderlich !)}
- Var Ansi:File; {Ansi-Datei}
- StdOut:File; {Standard-Ausgabe Datei (Int 21h)}
- Puffer:Pointer; {Zwischenpuffer fr Bildschirm}
- Groesse:Word; {DateigrӇe}
- Begin
- Assign(Ansi,Name); {Ansi-File ”ffnen}
- Assign(StdOut,'CON'); {Ausgabe-File ”ffnen}
- Reset(Ansi,1); {Ansi-File mit BlockgrӇe 1 Byte init.}
- Groesse:=FileSize(Ansi); {GrӇe (in Byte) bestimmen}
- Reset(Ansi,Groesse); {Datei mit dieser GrӇe erneut initialisieren}
- Reset(StdOut,Groesse); {Ausgabe-Datei initialisieren}
- GetMem(Puffer,Groesse); {Puffer allokieren}
- BlockRead(Ansi,Puffer^,1); {File lesen ...}
- BlockWrite(StdOut,Puffer^,1); {... und ausgeben}
- FreeMem(Puffer,Groesse); {Puffer freigeben}
- Close(Ansi); {Dateien schlieáen}
- Close(StdOut);
- End;
- Begin
- End.
- Unit Var_3d;
- Interface
- Uses Tools;
- Const Txt_Anzahl=5; {Anzahl benutzter Texturen}
- Txt_Groesse: {GrӇenangaben der Texturen}
- Array[0..Txt_Anzahl-1] of Word=
- ($0a0a,$0a0a,$0a0a,$0a0a,$0a0a);
- Var vz:Word; {Verschiebung in den Bildschirm hinein}
- rotx, {Rotationswinkel}
- roty,
- rotz:word; {3 Grad-Schritte}
- fl_sort:Boolean; {Fl„chen sortieren ?}
- Fuellen:Boolean; {true: Fllen / false:Linien}
- fl_ruecken:Boolean; {Fl„chenrcken unterdrcken ?}
- Texture:Boolean; {Texturen verwenden ?}
- lightsrc:Boolean; {Lichtquelle verwenden ?}
- Glas:Boolean; {Glas-Fl„chen ?}
- Txt_Daten:Array[0..Txt_Anzahl-1] of Pointer;
- {Lage der Texturen im Speicher}
- Txt_Offs:Array[0..Txt_Anzahl-1] of Word;
- {Offset innerhalb des Textur-Bilds}
- Txt_Pic:Pointer; {Zeiger auf Textur-Bild}
- Sinus:Array[0..149] of Word;{Sinus-Tabelle fr Rotationen}
- Implementation
- Begin
- Sin_Gen(Sinus,120,16384,0);
- Move(Sinus[0],Sinus[120],60);
- End.
- {$G+}
- Uses Crt,Gif,ModeXLib;
- Var x,y:Integer; {Koordinaten des Trapez}
- Procedure Draw_Voxel;external;
- {$l voxel.obj}
- Begin
- asm mov ax,0; int 33h End; {Maustreiber zurcksetzen}
- Init_ModeX; {Mode X einschalten}
- LoadGif('landsc3'); {Landschaft laden}
- x:=195; {Startkoordinate festlegen}
- y:=130;
- Repeat
- ClrX($0f); {Bildschirm l”schen}
- Draw_Voxel; {Landschaft zeichnen}
- Switch; {fertige Bildschirmseite aktivieren}
- WaitRetrace; {auf Retrace warten}
- asm
- mov ax,000bh {Funktion 0bh: relative Koordinaten lesen}
- int 33h
- sar cx,2 {Division durch 2}
- sar dx,2
- add x,cx
- add y,dx
- End;
- If x < 0 Then x:=0; If x > 130 Then x:=130;
- If y < 0 Then y:=0; If y > 130 Then y:=130;
- Until KeyPressed; {bis Taste}
- TextMode(3);
- End.
- Uses Crt,Gif,ModeXLib,Tools;
- const y=246; {H”he und Position hier festgelgt}
- hoehe=90; {drfen natrich auch Variablen sein}
- Var Sinus:Array[0..63] of Word; {Sinustabelle, wird sp„ter gefllt}
- i:Word; {tempor„rer Z„hler}
- Procedure Make_Wob(wob_pos,wob_hoehe,wob_offset:word);external;
- {$l wobbler}
- begin
- TextMode(3); {Wobbler funktioniert in JEDEM Videomodus ! }
- Draw_Ansi('db6.ans'); {Ansi-File laden}
- Sin_Gen(Sinus,64,4,83); {Sinus vorberechnen}
- CRTC_Unprotect; {horizontales Timing freischalten}
- ReadKey; {warten}
- i:=0;
- Repeat
- inc(i); {Bewegung erzeugen}
- Make_Wob(y,hoehe,i); {Wobble zeichnen}
- Until KeyPressed;
- CRTC_Protect; {CRTC wieder schtzen}
- End.
- .286
- w equ word ptr
- code segment public
- assume cs:code
- public wurzel
- public wurzfkt
- ;Radikand Wert in dx:ax
- wurzel proc pascal ;Ergebnis in ax (Function)
- .386
- xor esi,esi ;Zwischenergebnis (in esi) l”schen
- shrd ebx,edx,16d ;dx nach ebx (obere 16 Bit)
- mov bx,ax ;ax nach ebx (unten) - dx:ax jetzt in ebx
- xor edx,edx ;edx l”schen
- mov ecx,ebx ;Startwert in ecx sichern
- mov eax,ebx ;auch eax laden
- iterat:
- idiv ebx ;durch Xn dividieren
- xor edx,edx ;Rest interessiert nicht
- add eax,ebx ;Xn addieren
- shr eax,1 ;durch 2 dividieren
- sub esi,eax ;Differenz zum vorherigen Ergebnis
- cmp esi,1 ;kleiner gleich 1
- jbe fertig ;dann fertig
- mov esi,eax ;Ergebnis als vorheriges sichern
- mov ebx,eax ;als Xn vermerken
- mov eax,ecx ;Startwert fr Division erneut laden
- jmp iterat ;und zum Schleifenstart
- fertig:
- ret ;Ergebnis steht jetzt in eax
- wurzel endp
- wurzfkt proc pascal a:dword ;bersetzt Prozedur in Pascal-Funktion
- mov ax,word ptr a ;Parameter in Register schreiben
- mov dx,word ptr a+2
- call wurzel ;und Wurzel ziehen
- ret
- wurzfkt endp
- code ends
- end
- .286 ;wenigstens 286-Befehle aktivieren
- e equ db 66h ;Operand Size Prefix (32-Bit Befehle)
- w equ word ptr
- code segment public
- assume cs:code
- public wurzel
- public wurzfkt
- ;Radikand Wert in dx:ax
- wurzel proc pascal ;Ergebnis in ax (Function)
- e ;mit 32 Bit rechnen
- xor si,si ;Zwischenergebnis (in esi) l”schen
- db 66h,0fh,0ach,0d3h,10h ;shrd ebx,edx,16d - dx nach ebx (obere 16 Bit)
- mov bx,ax ;ax nach ebx (unten) - dx:ax jetzt in ebx
- e
- xor dx,dx ;edx l”schen
- e
- mov cx,bx ;Startwert in ecx sichern
- e
- mov ax,bx ;auch eax laden
- iterat:
- e
- idiv bx ;durch Xn dividieren
- e
- xor dx,dx ;Rest interessiert nicht
- e
- add ax,bx ;Xn addieren
- e
- shr ax,1 ;durch 2 dividieren
- e
- sub si,ax ;Differenz zum vorherigen Ergebnis
- e
- cmp si,1 ;kleiner gleich 1
- jbe fertig ;dann fertig
- e
- mov si,ax ;Ergebnis als vorheriges sichern
- e
- mov bx,ax ;als Xn vermerken
- e
- mov ax,cx ;Startwert fr Division erneut laden
- jmp iterat ;und zum Schleifenstart
- fertig:
- ret ;Ergebnis steht jetzt in eax
- wurzel endp
- wurzfkt proc pascal a:dword ;bersetzt Prozedur in Pascal-Funktion
- mov ax,word ptr a ;Parameter in Register schreiben
- mov dx,word ptr a+2
- call wurzel ;und Wurzel ziehen
- ret
- wurzfkt endp
- code ends
- endType Fest=Record {Aufbau einer Festkommazahl}
- Vork,
- Nachk:Integer
- End;
- Var Var1, {Beispielvariablen}
- Var2:Fest;
- Const Nachk_Max=100; {2 Nachkommastellen}
- Nachk_Stellen=2;
- Function Strg(FZahl:Fest):String;
- {wandelt eine Festkommazahl in einen String um}
- Var Nachk_Str, {String zum bilden des Nachkommateils}
- Vork_Str:String; {String zum bilden des Vorkommateils}
- i:Word;
- Begin
- If FZahl.Nachk < 0 Then {bei Ausgabe Nachkommateil ohne Vorzeichen}
- FZahl.Nachk:=-FZahl.Nachk;
- Str(FZahl.Nachk:Nachk_Stellen,Nachk_Str);
- {Nachkommstring generieren}
- For i:=0 to Nachk_Stellen do {und Leerzeichen durch 0en ersetzen}
- If Nachk_Str[i] = ' ' Then Nachk_Str[i]:='0';
- Str(FZahl.Vork,Vork_Str); {Vorkommstring generieren}
- Strg:=Vork_Str+','+Nachk_Str; {String zusammensetzen}
- End;
- Procedure Convert(RZahl:Real;Var FZahl:Fest);
- {Konvertiert Real RZahl in Festkommazahl FZahl}
- Begin
- FZahl.Vork:=Trunc(RZahl);
- {Vorkommateil bestimmen}
- FZahl.Nachk:=Trunc(Round(Frac(RZahl)*Nachk_Max));
- {Nachommateil bestimmen und als ganze Zahl speichern}
- End;
- Procedure Adjust(Var FZahl:Fest);
- {bringt bergebene Festkommazahl wieder in legales Format}
- Begin
- If FZahl.Nachk > Nachk_Max Then Begin
- Dec(FZahl.Nachk,Nachk_Max); {wenn Nachkommateil positiv bergelaufen}
- Inc(FZahl.Vork); {zurcksetzen und Vorkommateil verringern}
- End;
- If FZahl.Nachk < -Nachk_Max Then Begin
- Inc(FZahl.Nachk,Nachk_Max); {wenn Nachkommateil positiv bergelaufen}
- Dec(FZahl.Vork); {zurcksetzen und Vorkommateil erh”hen}
- End;
- End;
- Procedure Add(Var Summe:Fest;FZahl1,FZahl2:Fest);
- {Addiert FZahl1 und FZahl2 und legt Ergebnis in Summe ab}
- Var Ergebnis:Fest;
- Begin
- Ergebnis.Nachk:=FZahl1.Nachk+FZahl2.Nachk;
- {Nachkommateil addieren}
- Ergebnis.Vork:=FZahl1.Vork+FZahl2.Vork;
- {Vorkommateil addieren}
- Adjust(Ergebnis);
- {Ergebnis wieder auf richtiges Format bringen}
- Summe:=Ergebnis;
- End;
- Procedure Sub(Var Differenz:Fest;FZahl1,FZahl2:Fest);
- {Subtrahiert FZahl1 von FZahl2 und legt Ergebnis in Differenz ab}
- Var Ergebnis:Fest;
- Begin
- Ergebnis.Nachk:=FZahl1.Nachk-FZahl2.Nachk;
- {Nachkommateil subtrahieren}
- Ergebnis.Vork:=FZahl1.Vork-FZahl2.Vork;
- {Vorkommateil subtrahieren}
- Adjust(Ergebnis);
- {Ergebnis wieder auf richtiges Format bringen}
- Differenz:=Ergebnis;
- End;
- Procedure Mul(Var Produkt:Fest;FZahl1,FZahl2:Fest);
- {multipliziert FZahl1 und FZahl und legt Ergebnis in Produkt ab}
- Var Ergebnis:LongInt;
- Begin
- Ergebnis:=Var1.Vork*Nachk_Max + Var1.Nachk;
- {ersten Faktor bilden}
- Ergebnis:=Ergebnis * (Var2.Vork*Nachk_Max + Var2.Nachk);
- {zweiten Faktor bilden}
- Ergebnis:=Ergebnis div Nachk_Max;
- {Hilfsfaktor Nachk_Max ausgleichen}
- Produkt.Vork:=Ergebnis div Nachk_Max;
- {Vor- und Nachkommateil extrahieren}
- Produkt.Nachk:=Ergebnis mod Nachk_Max;
- End;
- Procedure Divi(Var Quotient:Fest;FZahl1,FZahl2:Fest);
- {dividiert FZahl1 durch FZahl2 und legt Ergebnis in Quotient ab}
- Var Ergebnis:LongInt; {Zwischenergebnis}
- Begin
- Ergebnis:=FZahl1.Vork*Nachk_Max + FZahl1.Nachk;
- {Z„hler bilden}
- Ergebnis:=Ergebnis * Nachk_Max div (FZahl2.Vork*Nachk_Max+FZahl2.Nachk);
- {durch Nenner teilen, vorher mehr Stellen zur Verfgung stellen}
- Quotient.Vork:=Ergebnis div Nachk_Max;
- {Vor- und Nachkommateil extrahieren}
- Quotient.Nachk:=Ergebnis mod Nachk_Max;
- End;
- Begin
- WriteLn;
- Convert(-10.2,Var1); {zwei Demo-Zahlen laden}
- Convert(25.3,Var2);
- {zur Demonstration einige Rechnungen:}
- Write(Strg(Var1),'*',Strg(Var2),'= ');
- Mul(Var1,Var1,Var2);
- WriteLn(Strg(Var1));
- Write(Strg(Var1),'-',Strg(Var2),'= ');
- Sub(Var1,Var1,Var2);
- WriteLn(Strg(Var1));
- Write(Strg(Var1),'/',Strg(Var2),'= ');
- Divi(Var1,Var1,Var2);
- WriteLn(Strg(Var1));
- Write(Strg(Var1),'+',Strg(Var2),'= ');
- Add(Var1,Var1,Var2);
- WriteLn(Strg(Var1));
- End.
- {$n-} {Coprozessor aus}
- Function Wurzfkt(Radikand:LongInt):Integer;external;
- {$l Wurzel}
- {Hier muá der Pfad des Assembler-Moduls Wurzel.obj eingetragen werden !}
- var i:word; {Schleifenz„hler}
- n:Integer; {Ergebnis der Integer-Rechnung}
- r:Real; {Ergebnis der Real-Rechnung}
- Procedure Wurzel_neu; {berechnet Wurzel nach Integer-N„herung}
- Begin
- For i:=1 to 10000 do {10000 mal durchlaufen,}
- n:=Wurzfkt(87654321); {um Geschwindigkeitsvergleich zu erhalten}
- End;
- Procedure Wurzel_real; {berechnet Wurzel durch Pascal-Funktion}
- Begin
- For i:=1 to 10000 do {10000 mal durchlaufen,}
- r:=Sqrt(87654321); {um Geschwindigkeitsvergleich zu erhalten}
- End;
- Begin
- writeLn;
- WriteLn('Wurzelberechnung durch Pascal - Funktion beginnt');
- Wurzel_Real;
- WriteLn('Ergebnis: ',r:0:0);
- WriteLn('Wurzelberechnung durch Integer - Funktion beginnt');
- Wurzel_neu;
- WriteLn('Ergebnis: ',n);
- End.
- unit DMA;
- interface
- TYPE DMAarray = array[0..7] of byte;
- CONST
- { Adressen der DMA-Controller }
- DMA_Adress : DMAarray = ($00,$02,$04,$06,$C0,$C4,$C8,$CC);
- DMA_Count : DMAarray = ($01,$03,$05,$07,$C2,$C6,$CA,$CE);
- DMARead_status_Reg : DMAarray = ($08,$08,$08,$08,$D0,$D0,$D0,$D0);
- DMAWrite_status_Reg : DMAarray = ($08,$08,$08,$08,$D0,$D0,$D0,$D0);
- DMAWrite_requ_Reg : DMAarray = ($09,$09,$09,$09,$D2,$D2,$D2,$D2);
- DMAWr_single_mask_Reg : DMAarray = ($0A,$0A,$0A,$0A,$D4,$D4,$D4,$D4);
- DMAWr_mode_Reg : DMAarray = ($0B,$0B,$0B,$0B,$D6,$D6,$D6,$D6);
- DMAClear_Flipflop : DMAarray = ($0C,$0C,$0C,$0C,$D8,$D8,$D8,$D8);
- DMARead_Temp_Reg : DMAarray = ($0D,$0D,$0D,$0D,$DA,$DA,$DA,$DA);
- DMAMaster_Clear : DMAarray = ($0D,$0D,$0D,$0D,$DA,$DA,$DA,$DA);
- DMA_Clear_Mask_Reg : DMAarray = ($0E,$0E,$0E,$0E,$DC,$DC,$DC,$DC);
- DMA_Wr_All_Mask_Reg : DMAarray = ($0F,$0F,$0F,$0F,$DE,$DE,$DE,$DE);
- DMA_Lower_Page : DMAarray = ($87,$83,$81,$82,$00,$8B,$89,$8A);
- DMA_Higher_Page : Array[0..7] of word
- = ($487,$483,$481,$482,$0,$48B,$489,$48A);
- { Modus Register DMA_Wr_mode_Reg }
- Anforderungsmodus = $00;
- Einzelmodus = $40;
- Blockmodus = $80;
- Kaskadierungsmodus = $C0;
- Adressen_Decrement = $20;
- Adressen_Increment = $00;
- Autoinit_Enable = $10;
- Autoinit_Disable = $00;
- Pruef_transfer = $00;
- Schreib_Transfer = $04;
- Lese_Transfer = $08;
- Set_Request_Bit = $04;
- Clear_Request_Bit = $00;
- Set_Mask_Bit = $04;
- Clear_Mask_Bit = $00;
- procedure DMA_Modus_setzen(Kanal,Modus : byte);
- procedure DMA_NormModus_setzen(Kanal,Modus : byte);
- procedure DMA_Clear_Flipflop(Kanal : byte);
- procedure DMA_Startadresse(Kanal : byte; Start : pointer);
- procedure DMA_Blockgroesse(Kanal : byte; size : word);
- procedure DMA_Kanal_Einmaskieren(Kanal : byte);
- procedure DMA_Kanal_Ausmaskieren(Kanal : byte);
- procedure DMA_Init_Transfer(Kanal,Modus : byte; p : pointer; s : word);
- implementation
- TYPE
- pt = record { erm”glicht die einfache }
- ofs,sgm : word; { Behandlung von Pointern }
- end;
- procedure DMA_Modus_setzen(Kanal,Modus : byte);
- begin;
- port[DMAWr_Mode_Reg[Kanal]] := Modus;
- end;
- procedure DMA_NormModus_setzen(Kanal,Modus : byte);
- begin;
- port[DMAWr_Mode_Reg[Kanal]] := Modus+Adressen_Increment+Lese_Transfer+
- Autoinit_Disable+Kanal;
- end;
- procedure DMA_Clear_Flipflop(Kanal : byte);
- begin;
- port[DMAClear_Flipflop[Kanal]] := 0;
- end;
- procedure DMA_Startadresse(Kanal : byte; Start : pointer);
- var l : longint;
- pn,offs : word;
- begin;
- l := 16*longint(pt(Start).sgm)+pt(Start).ofs;
- pn := pt(l).sgm;
- offs := pt(l).ofs;
- port[DMA_Adress[Kanal]] := lo(offs);
- port[DMA_Adress[Kanal]] := hi(offs);
- port[DMA_Lower_Page[Kanal]] := lo(pn);
- port[DMA_Higher_Page[Kanal]] := hi(pn);
- end;
- procedure DMA_Blockgroesse(Kanal : byte; size : word);
- begin;
- DMA_Clear_Flipflop(Kanal);
- port[DMA_Count[Kanal]]:= lo(size);
- port[DMA_Count[Kanal]] := hi(size);
- end;
- procedure DMA_Kanal_Einmaskieren(Kanal : byte);
- begin;
- port[DMAWr_single_mask_Reg[Kanal]] := Kanal + Set_Mask_Bit;
- end;
- procedure DMA_Kanal_Ausmaskieren(Kanal : byte);
- begin;
- port[DMAWr_single_mask_Reg[Kanal]] := Kanal + Clear_Mask_Bit;
- end;
- procedure DMA_Init_Transfer(Kanal,Modus : byte; p : pointer; s : word);
- begin;
- DMA_Kanal_Einmaskieren(Kanal);
- DMA_Startadresse(Kanal,p);
- DMA_Blockgroesse(Kanal,s);
- DMA_NormModus_Setzen(Kanal,Modus+Kanal);
- DMA_Kanal_Ausmaskieren(Kanal);
- end;
- begin;
- end.
- {
- Beispiel fr den Einsatz der Unit "DMA".
- }
- [ ... ]
- procedure Spiele_Sb16(dsize : word;p : pointer);
- {
- Bei Benutzung der Unit DMA ....
- }
- var li : word;
- begin;
- DMA_Init_Transfer(dma_ch,Blockmodus,p,dsize-1);
- if sb16_outputlaenge <> dsize then begin;
- wr_dsp_sb16($C6); { DSP-Befehl 8-Bit ber DMA }
- if stereo then { fr SB16 Nur zum Starten ! }
- wr_dsp_sb16($20)
- else
- wr_dsp_sb16($00);
- wr_dsp_sb16(Lo(dsize-1)); { GrӇe des Blockes an }
- wr_dsp_sb16(Hi(dsize-1)); { den DSP }
- sb16_outputlaenge := dsize;
- end else begin;
- wr_dsp_sb16($45); { DMA Continue SB16 8-Bit }
- end;
- end;
- [ ... ]
- procedure Spiele_Sb16(Segm,Offs,dsize : word);
- {
- Ohne die Unit DMA ....
- }
- var li : word;
- begin;
- port[$0A] := dma_ch+4; { DMA-Kanal sperren }
- Port[$0c] := 0; { Adresse des Puffers (blk) }
- Port[$0B] := $49; { fr Soundausgabe }
- {
- Fehler im Sorce des Buches !!!!!!!!!!!!!!
- muá
- Port[$0B] := $48 + dma_ch;
- heiáen !!!!!!!!!!!!!!!!!!!!
- }
- Port[dma_adr[dma_ch]] := Lo(offs); { an DMA-Controller }
- Port[dma_adr[dma_ch]] := Hi(offs);
- Port[dma_wc[dma_ch]] := Lo(dsize-1); { GrӇe des Blockes (block- }
- Port[dma_wc[dma_ch]] := Hi(dsize-1); { groesse) an DMA-Controller }
- Port[dma_page[dma_ch]] := Segm;
- if sb16_outputlaenge <> dsize then begin;
- wr_dsp_sb16($C6); { DSP-Befehl 8-Bit ber DMA }
- if stereo then { fr SB16 Nur zum Starten ! }
- wr_dsp_sb16($20)
- else
- wr_dsp_sb16($00);
- wr_dsp_sb16(Lo(dsize-1)); { GrӇe des Blockes an }
- wr_dsp_sb16(Hi(dsize-1)); { den DSP }
- sb16_outputlaenge := dsize;
- end else begin;
- wr_dsp_sb16($45); { DMA Continue SB16 8-Bit }
- end;
- Port[$0A] := dma_ch; { DMA-Kanal freigeben }
- end;
- ;****************************************************************************
- ;*** DATA BECKERs "PC UNDERGROUND" ***
- ;*** ================================ ***
- ;*** ***
- ;*** Unit zur Nutzung des Flat-Modells ***
- ;*** ***
- ;*** Die Unit stellt Routinen zur Verfgung, mit der im Realmode auf den ***
- ;*** gesamten Speicher des PC zugegriffen werden kann. ***
- ;*** Es darf KEIN Memory-Manager wie EMM386 oder QEMM installiert sein. ***
- ;*** HIMEM.SYS wird ben”tigt ! ***
- ;*** ***
- ;*** Autor : Boris Bertelsons (InspirE) ***
- ;*** Dateiname : RMEM.PAS ***
- ;*** Letzte Žnderung : 28.04.1994 ***
- ;*** Version : 1.0 ***
- ;*** Compiler : Turbo Pascal 6.0 und h”her ***
- ;****************************************************************************
- .386P
- .model tpascal
- .data
- extrn GDT_Off : byte
- extrn GDT : byte
- .code
- extrn xms_enable_a20 : far
- public mem_lesen
- public mem_Write
- public Enable_4Giga
- public Multitasker_aktiv
- ;*************************************************************************
- ;*** ***
- ;*** Prft, ob ein Multitasker wie QEMM oder EMM386 aktiv ist ***
- ;*** ***
- ;*************************************************************************
- Multitasker_aktiv proc pascal
- mov eax,cr0
- and ax,1
- ret
- Multitasker_aktiv endp
- ;*************************************************************************
- ;*** ***
- ;*** Kopiert einen Block aus dem RMEM in den Hauptspeicher ***
- ;*** ***
- ;*************************************************************************
- mem_Lesen proc pascal quellp:dword,zielofs : word,zielseg : word,laenge:word
- call xms_Enable_A20
- mov ax,zielseg ; Hauptspeicher-addy nach ES:SI
- mov es,ax
- mov di,zielofs
- xor ax,ax ; RMEM Quelladresse nach GS:EAX
- mov gs,ax
- mov eax,quellp
- mov cx,laenge
- lloop: mov bl,byte ptr gs:[eax] ; Bytes kopieren
- mov es:[di],bl
- inc eax
- inc di
- loop lloop
- ret
- mem_Lesen endp
- ;*************************************************************************
- ;*** ***
- ;*** Kopiert einen Block aus dem Hauptspeicher ins RMEM ***
- ;*** ***
- ;*************************************************************************
- mem_Write proc pascal quellp:dword, zielofs:word, zielseg:word, laenge:word
- call xms_Enable_A20
- mov ax,zielseg ; Hauptspeicher-addy nach ES:SI
- mov es,ax
- mov di,zielofs
- xor ax,ax ; RMEM Quelladresse nach GS:EAX
- mov gs,ax
- mov eax,quellp
- mov cx,laenge
- nloop:
- mov bl,es:[di] ; Bytes kopieren
- mov byte ptr gs:[eax],bl
- inc eax
- inc di
- loop nloop
- ret
- mem_Write endp
- ;*************************************************************************
- ;*** ***
- ;*** Schaltet den Processor ins Flat - Model ***
- ;*** ***
- ;*************************************************************************
- Enable_4Giga proc pascal
- mov GDT_Off[0],16
- mov eax,seg GDT
- shl eax,4
- mov bx,offset GDT
- movzx ebx,bx
- add eax,ebx
- mov dword ptr GDT_Off[2],eax
- lgdt pword ptr GDT_Off ; GDT laden
- mov bx,08h ; bx zeigt auf den 1. Eintrag des GDT
- push ds
- cli ; Interrupts ausschalten
- mov eax,cr0 ; In den Protected mode schalten
- or eax,1
- mov cr0,eax
- jmp In_den_Protectedmode ; Executionpipe l”schen
- In_den_Protectedmode:
- mov gs,bx ; Segmente auf 4 GB anpassen
- mov fs,bx
- mov es,bx
- mov ds,bx
- and al,0FEh ; Zurck in den Real-mode schalten, ohne den
- mov cr0,eax ; Processor zu resetten
- jmp In_den_Realmode ; Executionpipe l”schen
- In_den_Realmode:
- sti ; Interrupts wieder einschalten
- pop ds
- ret
- Enable_4Giga endp
- END
- {
- ****************************************************************************
- *** DATA BECKERs "PC UNDERGROUND" ***
- *** ================================ ***
- *** ***
- *** Demoprogramm zum Einsatz der Unit RMEM ***
- *** ***
- *** Das Programm demonstriert den Einsatz der Unit RMEM. ***
- *** Ein Bild wird ins RMEM geladen, und dann aus dem RMEM angezeigt. ***
- *** ***
- *** Autor : Boris Bertelsons (InspirE) ***
- *** Dateiname : DEMORMEM.PAS ***
- *** Letzte Žnderung : 28.04.1994 ***
- *** Version : 1.0 ***
- *** Compiler : Turbo Pascal 6.0 und h”her ***
- ****************************************************************************
- }
- program demo386;
- uses dos,crt,rmem,gifunit;
- var bildposition : longint;
- procedure lade_das_gifbild;
- begin;
- getmem(vscreen,64000);
- Init_ModeX;
- blackpal;
- LoadGif('beispiel.gif',vscreen,0,0);
- textmode(3);
- end;
- procedure zeige_das_gifbild;
- begin;
- Init_ModeX;
- p13_2_modex(0,16000);
- setpal;
- end;
- begin
- memory_checks(500,2700);
- enable_Realmem(2700);
- if not Rgetmem(bildposition,64000) then begin;
- textmode(3);
- writeln('Fehler beim Reservieren des Speichers !!!');
- end;
- lade_das_gifbild;
- writeln('Habe das GIF-Bild in den Speicher geladen.');
- writeln('Sichere nun das Bild ins RMEM und l”sche den Lade-Puffer !');
- Rmem_write(vscreen,bildposition,64000);
- fillchar(vscreen^,64000,0);
- writeln('Habe den Lade-Puffer gel”scht !');
- writeln('Lade nun das Bild aus dem RMEM');
- writeln('<ENTER>, um das Bild anzuzeigen ... ');
- readln;
- Rmem_lesen(bildposition,vscreen,64000);
- zeige_das_gifbild;
- readln;
- textmode(3);
- Exit_Rmem;
- end.
- unit gifunit;
- interface uses dos;
- const clr=256; {gif}
- eof=257;
- pakt : byte = 0;
- Const Maxsprites=14;
- o_dtx=4; o_dty=6;
- sampr : integer = 22;
- var palette:Array[0..767] of Byte;
- Var Handle:Word;
- Puf:Array[0..767] of Byte;
- PufInd:Word;
- Stack:Array[0..1280] of byte;
- ab_prfx,ab_tail:Array[0..4096] of word;
- Byt:Byte;
- free,breite,max,
- stackp,restbits,restbyte,sonderfall,
- code,old_code,readbyt,bits,bits2get:Word;
- lbyte:Word;
- mask:Word;
- zseg,zofs,
- GifName:String[15];
- VScreen:Pointer;
- Procedure LoadGif(name:String;var zielvar:Pointer;startadr:word;seek:Longint);
- Procedure SetPal;
- procedure Blackpal;
- Procedure p13_2_modex(start,pic_size:word);
- Procedure Split(row:byte);
- Procedure Start(Ofst:Word);
- Procedure Init_ModeX;
- Procedure Init_Mode13;
- Procedure WaitRetrace;
- implementation
- Procedure SetPal;assembler;
- asm
- mov si,offset palette
- mov cx,256*3
- xor al,al
- mov dx,03c8h
- out dx,al
- inc dx
- @lp:
- rep outsb
- End;
- procedure Blackpal;
- begin;
- fillchar(palette,768,0);
- setpal;
- end;
- Procedure GifOpen;assembler;
- asm
- mov ax,03d00h
- lea dx,gifname + 1
- int 21h
- mov handle,ax
- End;
- Procedure GifRead(n:Word);assembler;
- asm
- mov ax,03f00h
- mov bx,handle
- mov cx,n
- lea dx,puf
- int 21h
- end;
- Procedure GifSeekdelta(delta:Longint);assembler;
- asm
- mov ax,04200h
- mov bx,handle
- mov cx,word ptr delta + 2
- mov dx,word ptr delta
- int 21h
- End;
- Procedure GifClose;Assembler;
- asm
- mov ax,03e00h
- mov bx,handle
- int 21h
- End;
- Procedure ShiftPal;assembler;
- asm
- push ds
- pop es
- mov si,offset Puf
- mov di,offset Palette
- mov cx,768
- @l1:
- lodsb
- shr al,2
- stosb
- loop @l1
- End;
- Procedure FillPuf;
- Begin
- GifRead(1);
- restbyte:=puf[0];
- GifRead(restbyte);
- End;
- Function GetPhysByte:Byte;assembler;
- asm
- push bx
- cmp restbyte,0
- ja @restda
- pusha
- call fillpuf
- popa
- mov pufind,0
- @restda:
- mov bx,PufInd
- mov al,byte ptr Puf[bx]
- inc pufind
- pop bx
- End;
- Function GetLogByte:Word;assembler;
- asm
- push si
- mov ax,breite
- mov si,ax
- mov dx,restbits
- mov cx,8
- sub cx,dx
- mov ax,lByte
- shr ax,cl
- mov code,ax
- sub si,dx
- @nextbyte:
- call getphysbyte
- xor ah,ah
- mov lByte,ax
- dec restbyte
- mov bx,1
- mov cx,si
- shl bx,cl
- dec bx
- and ax,bx
- mov cx,dx
- shl ax,cl
- add code,ax
- sbb dx,breite
- add dx,8
- jns @positiv
- add dx,8
- @positiv:
- sub si,8
- jle @fertig { <= 0 }
- add dx,breite
- sub dx,8
- jmp @nextbyte
- @fertig:
- mov restbits,dx
- mov ax,code
- pop si
- End;
- Procedure p13_2_modex(start,pic_size:word);assembler;
- Var Plane_l:Byte;
- Plane_Pos:Word;
- asm
- mov plane_l,1
- mov plane_pos,0
- push ds
- lds si,vscreen
- mov plane_pos,si
- mov ax,0a000h
- mov es,ax
- mov di,start
- mov cx,pic_size
- @lpplane:
- mov al,02h
- mov ah,plane_l
- mov dx,3c4h
- out dx,ax
- @lp1:
- movsb
- add si,3
- loop @lp1
- { dec cx
- jne @lp1}
- mov di,start
- inc plane_pos
- mov si,plane_pos
- mov cx,pic_size
- shl plane_l,1
- cmp plane_l,10h
- jne @lpplane
- pop ds
- End;
- Procedure LoadGif(name:String;var zielvar:Pointer;startadr:word;seek:Longint);
- Var ziel,
- quelle,qseg:Word;
- { pic_size,pic_height,pic_width:word;}
- x_count:Word;
- zielvarlok:Pointer;
- Begin
- gifName:=Name+#0;
- if zielvar = Nil Then
- getMem(zielvar,64000);
- GifOpen;
- gifseekdelta(seek+13);
- gifread(768);
- Shiftpal;
- gifread(1);
- While Puf[0] = $21 do Begin {Erw - Block berlesen}
- gifread(2);
- gifread(puf[1]+1);
- End;
- GifRead(10);
- { pic_width:=puf[4]+puf[5]*256;
- pic_height:=puf[6]+puf[7]*256;
- pic_size:=pic_width div 4 * pic_height;}
- If Puf[8] and 128 = 128 Then Begin
- gifread(768);
- Shiftpal;
- End;
- lByte:=0;
- Zielvarlok:=Zielvar;
- asm
- les di,zielvarlok
- mov free,258 {1. freie Posit in Alphabet}
- mov breite,9 {Zeichenbreite in bit}
- mov max,511 {maximaler darstellbarer Wert bei akt breite}
- mov stackp,0
- mov restbits,0
- mov restbyte,0
- @mainloop:
- call getlogByte
- cmp ax,eof
- je @abbruch
- cmp ax,clr
- je @clear
- mov readbyt,ax
- cmp ax,free
- jb @code_in_ab
- mov ax,old_code
- mov code,ax
- mov bx,stackp
- mov cx,sonderfall
- mov word ptr stack[bx],cx
- inc stackp
- @code_in_ab:
- cmp ax,clr
- jb @konkret
- @fillstack_loop:
- mov bx,code
- shl bx,1
- push bx
- mov ax,word ptr ab_tail[bx]
- mov bx,stackp
- shl bx,1
- mov word ptr stack[bx],ax
- inc stackp
- pop bx
- mov ax,word ptr ab_prfx[bx]
- mov code,ax
- cmp ax,clr
- ja @fillstack_loop
- @konkret:
- mov bx,stackp
- shl bx,1
- mov word ptr stack[bx],ax
- mov sonderfall,ax
- inc stackp
- mov bx,stackp
- dec bx
- shl bx,1
- @readstack_loop:
- mov ax,word ptr stack[bx]
- stosb
- or di,di
- jne @noovl1
- push startadr
- push 16384
- add startadr,16384
- call p13_2_modex
- les di,zielvarlok
- @noovl1:
- { add si,4
- and si,12
- or di,di
- jne @rsnc
- mov ax,es
- add ax,1000h
- mov es,ax
- @rsnc:}
- dec bx
- dec bx
- jns @readstack_loop
- mov stackp,0
- mov bx,free
- shl bx,1
- mov ax,old_code
- mov word ptr ab_prfx[bx],ax
- mov ax,code
- mov word ptr ab_tail[bx],ax
- mov ax,readbyt
- mov old_code,ax
- inc free
- mov ax,free
- cmp ax,max
- jbe @mainloop
- cmp byte ptr breite,12
- jae @mainloop
- inc breite
- mov cl,byte ptr breite
- mov ax,1
- shl ax,cl
- dec ax
- mov max,ax
- jmp @mainloop
- @clear:
- mov breite,9
- mov max,511
- mov free,258
- call getlogbyte
- mov sonderfall,ax
- mov old_code,ax
- stosb
- or di,di
- jne @noovl2
- push startadr
- push 16384
- add startadr,16384
- call p13_2_modex
- les di,zielvarlok
- @noovl2:
- { add si,4
- and si,12
- or di,di
- jne @mainloop
- mov ax,es
- add ax,1000h
- mov es,ax }
- jmp @mainloop
- @abbruch:
- End;
- gifclose;
- End;
- procedure disable4; assembler;
- asm;
- mov dx,3c4h
- mov ax,0f02h
- out dx,ax
- mov dx,3ceh
- mov ax,4005h
- out dx,ax
- end;
- Procedure ShowPic;assembler;
- asm
- push ds
- mov di,0a000h
- mov es,di
- xor di,di
- mov si,word ptr VScreen
- mov ax,word ptr Vscreen + 2
- mov ds,ax
- mov cx,32000
- rep movsw
- pop ds
- End;
- Procedure ClearPic(Size:Word);assembler;
- asm
- mov ax,word ptr vscreen + 2
- mov es,ax
- mov di,word ptr vscreen
- mov cx,Size
- xor ax,ax
- rep stosw
- End;
- Procedure WaitRetrace;assembler;
- asm
- mov dx,3dah
- @wait1:
- in al,dx
- test al,8h
- jz @wait1
- @wait2:
- in al,dx
- test al,8h
- jnz @wait2
- End;
- Procedure Init_Mode13;assembler;
- asm
- mov ax,13h
- int 10h
- End;
- Procedure Init_ModeX;assembler;
- asm
- mov ax,0013h { Den normalen Mode 13h setzen }
- int 10h
- mov dx,3c4h { Verknpfung aufheben, Einzelzugriff }
- mov al,4 { erm”glichen }
- out dx,al
- inc dx
- in al,dx
- and al,0f7h
- or al,4h
- out dx,al
- dec dx
- mov ax,0f02h
- out dx,ax
- mov ax,0a000h { Bildschirmspeicher l”schen }
- mov es,ax
- xor di,di
- xor ax,ax
- mov cx,8000h
- cld
- rep stosw
- mov dx,3d4h
- mov al,14h
- out dx,al
- inc dx
- in al,dx
- and al,0bfh
- out dx,al
- dec dx
- mov al,17h
- out dx,al
- inc dx
- in al,dx
- or al,40h
- out dx,al
- End;
- Procedure Start(Ofst:Word);assembler;
- asm
- mov dx,3d4h
- mov al,0ch
- mov ah,byte ptr ofst + 1
- out dx,ax
- inc al
- mov ah,byte ptr ofst
- out dx,ax
- End;
- Procedure Split(row:byte);assembler;
- asm
- mov bl,row
- xor bh,bh
- shl bx,1
- mov cx,bx
- mov dx,3d4h
- mov al,07h
- out dx,al
- inc dx
- in al,dx
- and al,11101111b
- shr cx,4
- and cl,16
- or al,cl
- out dx,al
- dec dx
- mov al,09h
- out dx,al
- inc dx
- in al,dx
- and al,10111111b
- shr bl,3
- and bl,64
- or al,bl
- out dx,al
- dec dx
- mov al,18h
- mov ah,row
- shl ah,1
- out dx,ax
- End;
- Procedure enable4;assembler;
- asm
- mov dx,3c4h
- mov ax,0f02h
- out dx,ax
- mov dx,3ceh
- mov ax,4105h
- out dx,ax
- End;
- begin;
- end.{
- ****************************************************************************
- *** DATA BECKERs "PC UNDERGROUND" ***
- *** ================================ ***
- *** ***
- *** Unit zur Nutzung des Flat-Modells ***
- *** ***
- *** Die Unit stellt Routinen zur Verfgung, mit der im Realmode auf den ***
- *** gesamten Speicher des PC zugegriffen werden kann. ***
- *** Es darf KEIN Memory-Manager wie EMM386 oder QEMM installiert sein. ***
- *** HIMEM.SYS wird ben”tigt ! ***
- *** ***
- *** Autor : Boris Bertelsons (InspirE) ***
- *** Dateiname : RMEM.PAS ***
- *** Letzte Žnderung : 28.04.1994 ***
- *** Version : 1.0 ***
- *** Compiler : Turbo Pascal 6.0 und h”her ***
- ****************************************************************************
- }
- unit rmem;
- interface
- uses crt;
- const Rmem_Max : longint = 3*1024*1024-70000;
- const GDT : array[1..16] of byte =(
- $00,$00,$00,$00,$00,$00,$00,$00, {GDT Eintrag 0 (null segment)}
- $FF,$FF,$00,$00,$00,$92,$CF,$FF); {GDT Eintrag 1 (seg 0, limit 4GB)}
- var GDT_Off : array[1..6] of byte;
- procedure memory_checks(minmain,minxms : word);
- procedure enable_Realmem(Min : word);
- procedure Exit_Rmem;
- function Rgetmem(Var rpos : longint;rsize : longint) : boolean;
- procedure Rmem_Lesen(quelle:longint; ziel:pointer;laenge:word);
- procedure Rmem_write(quelle:pointer;ziel:longint;laenge:word);
- implementation
- uses dos;
- TYPE XMSHandle = word;
- XMS_Copyblock = Record { Wird fr die Kopier-Routinen ben”tigt }
- Size : longint;
- Q_Handle : Word;
- Q_Offset : pointer;
- Z_Handle : Word;
- Z_Offset : pointer;
- end;
- VAR XMS_Vorhanden : boolean; { TRUE, wenn XMS vorhanden ist }
- XMST : pointer; { Treiber - Einsprungadresse }
- XMS_Version : word; { Die Version des XMS-Treibers }
- XC : XMS_Copyblock;
- xms_frei : longint;
- error : byte;
- My_XmsHandle : XmsHandle;
- Xms_startposi : longint;
- Old_ExitprocRmem : pointer;
- function XMS_free : longint;
- var xms_in_kb : word;
- xms_long: longint;
- begin;
- asm
- mov ax,0800h { 8 = Freien Speicher Ermitteln }
- call dword ptr [XMST]
- mov xms_in_kb,dx
- end;
- xms_long := xms_in_kb;
- XMS_free := xms_long * 1024;
- end;
- Function Getmem_XMS(VAR H : XMSHandle; Size : longint) : byte;
- var bsize : word;
- Fresult : byte;
- xmsh : word;
- begin;
- bsize := (size DIV 1024) + 1;
- asm
- mov ax,0900h { 9 = Speicherbereich allocieren }
- mov dx,bsize
- call dword ptr [XMST]
- cmp ax,1
- jne @Fehler_GetmemXms
- mov xmsh,dx
- mov Fresult,0
- jmp @Ende_GetmemXms
- @Fehler_GetmemXMS:
- mov Fresult,bl
- @Ende_GetmemXms:
- end;
- h := xmsh;
- Getmem_Xms := Fresult;
- end;
- Function Freemem_XMS(H : XMSHandle) : byte;
- var fresult : byte;
- begin;
- asm { A = Speicherbereich deallocieren }
- mov ax,0a00h
- mov dx,h
- call dword ptr [XMST]
- cmp ax,1
- jne @Fehler_FreememXms
- mov Fresult,0
- jmp @Ende_FreememXms
- @Fehler_FreememXms:
- mov Fresult,bl
- @Ende_FreememXms:
- end;
- end;
- Procedure Check_for_XMS; assembler;
- asm
- mov ax,4300h { Prfen, ob Treiber Installiert }
- int 2Fh
- cmp al,80h
- jne @Kein_XMSTreiber
- mov ax,4310h { Einsprungadresse des Treibers ermitteln }
- int 2Fh
- mov word ptr XMST + 2,es
- mov word ptr XMST + 0,bx
- xor ax,ax { Versionsnummer ermitteln }
- call dword ptr [XMST]
- cmp ax,0200h
- jb @Kein_XMSTreiber { Wenn Version < 2.0 dann Abbrechen ! }
- mov XMS_Version,ax
- mov XMS_Vorhanden,0
- @Kein_XMSTreiber:
- mov XMS_Vorhanden,1
- @Ende_XMS_Check:
- end;
- function XMS_lock(H : XMSHandle) : longint; assembler;
- asm;
- mov ax,0c00h
- mov dx,h
- call dword ptr [XMST]
- mov ax,bx
- end;
- procedure XMS_unlock(H : XMSHandle); assembler;
- asm;
- mov ax,0d00h
- mov dx,h
- call dword ptr [XMST]
- end;
- procedure XMS_Enable_A20; assembler;
- asm
- mov ax,0500h
- call dword ptr [XMST]
- end;
- procedure XMS_Disable_A20; assembler;
- asm
- mov ax,0600h
- call dword ptr [XMST]
- end;
- const MByte1: longint = $100000;
- var Offs,Segm : word;
- Rmemposi : longint;
- {$l rmemasm.obj}
- procedure mem_write(q:longint;zl,zh,l:word); far; external;
- {
- *************************************************************************
- *** ***
- *** Kopiert einen Block aus dem Hauptspeicher ins RMEM ***
- *** ***
- *************************************************************************
- }
- procedure mem_lesen(q:longint;zl,zh,l:word); far; external;
- {
- *************************************************************************
- *** ***
- *** Kopiert einen Block aus dem RMEM in den Hauptspeicher ***
- *** ***
- *************************************************************************
- }
- procedure Enable_4Giga; far; external;
- {
- *************************************************************************
- *** ***
- *** Schaltet den Processor ins Flat - Model ***
- *** ***
- *************************************************************************
- }
- function multitasker_aktiv : boolean; far; external;
- {
- *************************************************************************
- *** ***
- *** Prft, ob ein Multitasker wie QEMM oder EMM386 aktiv ist ***
- *** ***
- *************************************************************************
- }
- procedure Rmem_Lesen(quelle:longint; ziel:pointer;laenge:word);
- {
- *************************************************************************
- *** ***
- *** Kopiert einen Block aus dem RMEM in den Hauptspeicher ***
- *** ***
- *************************************************************************
- }
- begin
- if quelle + laenge < Rmem_Max then begin
- Segm:=seg(ziel^);
- Offs:=ofs(ziel^);
- inc(Segm,Offs div 16);
- Offs:=Offs mod 16;
- inc(quelle,MByte1);
- mem_lesen(quelle,Offs,Segm,laenge);
- end else begin;
- asm mov ax,0003; int 10h; end;
- writeln('Error reading back XMS Realmemory !');
- writeln('System halted');
- halt(0);
- end;
- end;
- procedure Rmem_write(quelle:pointer;ziel:longint;laenge:word);
- {
- *************************************************************************
- *** ***
- *** Kopiert einen Block aus dem Hauptspeicher ins RMEM ***
- *** ***
- *************************************************************************
- }
- begin
- if ziel+laenge < Rmem_Max then begin
- Segm := seg(quelle^);
- Offs := ofs(quelle^);
- inc(Segm,Offs div 16);
- Offs := Offs mod 16;
- inc(ziel,MByte1);
- mem_write(ziel, Offs,Segm,laenge);
- end else begin;
- asm mov ax,0003; int 10h; end;
- writeln('XMS allocation error ! Not enough memory ?');
- writeln('System halted');
- halt(0);
- end;
- end;
- procedure memory_checks(minmain,minxms : word);
- {
- *************************************************************************
- *** ***
- *** Prft, ob gengend Speicher zur Verfgung steht ***
- *** ***
- *************************************************************************
- }
- var xmsfree,mainfree : word;
- begin;
- { Freien XMS - Speicher ermitteln }
- xmsfree := xms_free;
- { Hauptspeicher ermitteln }
- mainfree := memavail div 1024;
- { Meldung, wenn nicht genug ferier Speicher }
- if (xmsfree < minxms) or (mainfree < minmain) then begin;
- asm mov ax,0003; int 10h; end;
- writeln('Sorry, not enough memory available !');
- writeln(' You need Available');
- writeln('XMS : ',minxms :6,' KB ',xmsfree:4,' KB');
- writeln('Main: ',minmain:6,' KB ',mainfree:4,' KB');
- halt(0);
- end;
- end;
- function Rgetmem(Var rpos : longint;rsize : longint) : boolean;
- {
- *************************************************************************
- *** ***
- *** Eine vereinfachte Getmem-Procedure fr das RMEM ***
- *** ***
- *************************************************************************
- }
- begin;
- if Rmemposi+rsize > Rmem_max then begin;
- Rgetmem := false;
- end else begin;
- rpos := Rmemposi;
- inc(Rmemposi,rsize);
- Rgetmem := true;
- end;
- end;
- procedure Exit_Rmem;
- {
- *************************************************************************
- *** ***
- *** Exit-Procedure des RMEM, MUSS aufgerufen werden ! ***
- *** ***
- *************************************************************************
- }
- begin;
- { Block entsperren }
- XMS_unlock(My_XmsHandle);
- { Speicher freigeben }
- Freemem_XMS(My_XmsHandle);
- end;
- procedure enable_Realmem(Min : word);
- {
- *************************************************************************
- *** ***
- *** Schaltet in den RMEM - Modus ***
- *** Es muá "MIN" KB freier XMS-Speicher vorhanden sein ! ***
- *** ***
- *************************************************************************
- }
- begin
- { Auf Multitasker prfen ... }
- if multitasker_aktiv then begin;
- asm mov ax,0003; int 10h; end;
- writeln('Processor already in V86 mode !');
- writeln('Please reboot without any EMS-drivers such as EMM386, QEMM etc.');
- writeln('HIMEM.SYS is required ! ');
- halt(0);
- end;
- { XMS Treiber installiert ? }
- if not XMS_Vorhanden then begin;
- asm mov ax,0003; int 10h; end;
- writeln('No XMS or Himem-driver available');
- writeln('Please reboot your System using HIMEM.SYS !!!');
- halt(0);
- end;
- { Ben”tigten Speicher belegen }
- error := Getmem_XMS(My_XmsHandle,min*1024);
- if error <> 0 then begin;
- asm mov ax,0003; int 10h; end;
- writeln('Error during memory-allocation !');
- writeln('We need at least ',Min,' KB of free XMS Memory !!!');
- writeln('Please reboot your System using HIMEM.SYS');
- writeln;
- halt(0);
- end;
- { Physikalische Startposition ermitteln }
- Rmemposi := XMS_lock(My_XmsHandle);
- if rmemposi < 1000000 then begin;
- asm mov ax,0003; int 10h; end;
- writeln('Error during memory-fixing !');
- writeln('We need at least ',Min,' KB of free XMS Memory !!!');
- writeln('Please reboot your System using HIMEM.SYS');
- writeln;
- halt(0);
- end;
- { Freischalten }
- Enable_4Giga;
- end;
- begin;
- Check_for_XMS;
- Rmem_Max := XMS_Free;
- end.
- unit gifunit;
- interface uses dos;
- const clr=256; {gif}
- eof=257;
- pakt : byte = 0;
- Const Maxsprites=14;
- o_dtx=4; o_dty=6;
- sampr : integer = 22;
- var palette:Array[0..767] of Byte;
- Var Handle:Word;
- Puf:Array[0..767] of Byte;
- PufInd:Word;
- Stack:Array[0..1280] of byte;
- ab_prfx,ab_tail:Array[0..4096] of word;
- Byt:Byte;
- free,breite,max,
- stackp,restbits,restbyte,sonderfall,
- code,old_code,readbyt,bits,bits2get:Word;
- lbyte:Word;
- mask:Word;
- zseg,zofs,
- GifName:String[15];
- VScreen:Pointer;
- Procedure LoadGif(name:String;var zielvar:Pointer;startadr:word;seek:Longint);
- Procedure SetPal;
- procedure Blackpal;
- Procedure p13_2_modex(start,pic_size:word);
- Procedure Split(row:byte);
- Procedure Start(Ofst:Word);
- Procedure Init_ModeX;
- Procedure Init_Mode13;
- Procedure WaitRetrace;
- implementation
- Procedure SetPal;assembler;
- asm
- mov si,offset palette
- mov cx,256*3
- xor al,al
- mov dx,03c8h
- out dx,al
- inc dx
- @lp:
- rep outsb
- End;
- procedure Blackpal;
- begin;
- fillchar(palette,768,0);
- setpal;
- end;
- Procedure GifOpen;assembler;
- asm
- mov ax,03d00h
- lea dx,gifname + 1
- int 21h
- mov handle,ax
- End;
- Procedure GifRead(n:Word);assembler;
- asm
- mov ax,03f00h
- mov bx,handle
- mov cx,n
- lea dx,puf
- int 21h
- end;
- Procedure GifSeekdelta(delta:Longint);assembler;
- asm
- mov ax,04200h
- mov bx,handle
- mov cx,word ptr delta + 2
- mov dx,word ptr delta
- int 21h
- End;
- Procedure GifClose;Assembler;
- asm
- mov ax,03e00h
- mov bx,handle
- int 21h
- End;
- Procedure ShiftPal;assembler;
- asm
- push ds
- pop es
- mov si,offset Puf
- mov di,offset Palette
- mov cx,768
- @l1:
- lodsb
- shr al,2
- stosb
- loop @l1
- End;
- Procedure FillPuf;
- Begin
- GifRead(1);
- restbyte:=puf[0];
- GifRead(restbyte);
- End;
- Function GetPhysByte:Byte;assembler;
- asm
- push bx
- cmp restbyte,0
- ja @restda
- pusha
- call fillpuf
- popa
- mov pufind,0
- @restda:
- mov bx,PufInd
- mov al,byte ptr Puf[bx]
- inc pufind
- pop bx
- End;
- Function GetLogByte:Word;assembler;
- asm
- push si
- mov ax,breite
- mov si,ax
- mov dx,restbits
- mov cx,8
- sub cx,dx
- mov ax,lByte
- shr ax,cl
- mov code,ax
- sub si,dx
- @nextbyte:
- call getphysbyte
- xor ah,ah
- mov lByte,ax
- dec restbyte
- mov bx,1
- mov cx,si
- shl bx,cl
- dec bx
- and ax,bx
- mov cx,dx
- shl ax,cl
- add code,ax
- sbb dx,breite
- add dx,8
- jns @positiv
- add dx,8
- @positiv:
- sub si,8
- jle @fertig { <= 0 }
- add dx,breite
- sub dx,8
- jmp @nextbyte
- @fertig:
- mov restbits,dx
- mov ax,code
- pop si
- End;
- Procedure p13_2_modex(start,pic_size:word);assembler;
- Var Plane_l:Byte;
- Plane_Pos:Word;
- asm
- mov plane_l,1
- mov plane_pos,0
- push ds
- lds si,vscreen
- mov plane_pos,si
- mov ax,0a000h
- mov es,ax
- mov di,start
- mov cx,pic_size
- @lpplane:
- mov al,02h
- mov ah,plane_l
- mov dx,3c4h
- out dx,ax
- @lp1:
- movsb
- add si,3
- loop @lp1
- { dec cx
- jne @lp1}
- mov di,start
- inc plane_pos
- mov si,plane_pos
- mov cx,pic_size
- shl plane_l,1
- cmp plane_l,10h
- jne @lpplane
- pop ds
- End;
- Procedure LoadGif(name:String;var zielvar:Pointer;startadr:word;seek:Longint);
- Var ziel,
- quelle,qseg:Word;
- { pic_size,pic_height,pic_width:word;}
- x_count:Word;
- zielvarlok:Pointer;
- Begin
- gifName:=Name+#0;
- if zielvar = Nil Then
- getMem(zielvar,64000);
- GifOpen;
- gifseekdelta(seek+13);
- gifread(768);
- Shiftpal;
- gifread(1);
- While Puf[0] = $21 do Begin {Erw - Block berlesen}
- gifread(2);
- gifread(puf[1]+1);
- End;
- GifRead(10);
- { pic_width:=puf[4]+puf[5]*256;
- pic_height:=puf[6]+puf[7]*256;
- pic_size:=pic_width div 4 * pic_height;}
- If Puf[8] and 128 = 128 Then Begin
- gifread(768);
- Shiftpal;
- End;
- lByte:=0;
- Zielvarlok:=Zielvar;
- asm
- les di,zielvarlok
- mov free,258 {1. freie Posit in Alphabet}
- mov breite,9 {Zeichenbreite in bit}
- mov max,511 {maximaler darstellbarer Wert bei akt breite}
- mov stackp,0
- mov restbits,0
- mov restbyte,0
- @mainloop:
- call getlogByte
- cmp ax,eof
- je @abbruch
- cmp ax,clr
- je @clear
- mov readbyt,ax
- cmp ax,free
- jb @code_in_ab
- mov ax,old_code
- mov code,ax
- mov bx,stackp
- mov cx,sonderfall
- mov word ptr stack[bx],cx
- inc stackp
- @code_in_ab:
- cmp ax,clr
- jb @konkret
- @fillstack_loop:
- mov bx,code
- shl bx,1
- push bx
- mov ax,word ptr ab_tail[bx]
- mov bx,stackp
- shl bx,1
- mov word ptr stack[bx],ax
- inc stackp
- pop bx
- mov ax,word ptr ab_prfx[bx]
- mov code,ax
- cmp ax,clr
- ja @fillstack_loop
- @konkret:
- mov bx,stackp
- shl bx,1
- mov word ptr stack[bx],ax
- mov sonderfall,ax
- inc stackp
- mov bx,stackp
- dec bx
- shl bx,1
- @readstack_loop:
- mov ax,word ptr stack[bx]
- stosb
- or di,di
- jne @noovl1
- push startadr
- push 16384
- add startadr,16384
- call p13_2_modex
- les di,zielvarlok
- @noovl1:
- { add si,4
- and si,12
- or di,di
- jne @rsnc
- mov ax,es
- add ax,1000h
- mov es,ax
- @rsnc:}
- dec bx
- dec bx
- jns @readstack_loop
- mov stackp,0
- mov bx,free
- shl bx,1
- mov ax,old_code
- mov word ptr ab_prfx[bx],ax
- mov ax,code
- mov word ptr ab_tail[bx],ax
- mov ax,readbyt
- mov old_code,ax
- inc free
- mov ax,free
- cmp ax,max
- jbe @mainloop
- cmp byte ptr breite,12
- jae @mainloop
- inc breite
- mov cl,byte ptr breite
- mov ax,1
- shl ax,cl
- dec ax
- mov max,ax
- jmp @mainloop
- @clear:
- mov breite,9
- mov max,511
- mov free,258
- call getlogbyte
- mov sonderfall,ax
- mov old_code,ax
- stosb
- or di,di
- jne @noovl2
- push startadr
- push 16384
- add startadr,16384
- call p13_2_modex
- les di,zielvarlok
- @noovl2:
- { add si,4
- and si,12
- or di,di
- jne @mainloop
- mov ax,es
- add ax,1000h
- mov es,ax }
- jmp @mainloop
- @abbruch:
- End;
- gifclose;
- End;
- procedure disable4; assembler;
- asm;
- mov dx,3c4h
- mov ax,0f02h
- out dx,ax
- mov dx,3ceh
- mov ax,4005h
- out dx,ax
- end;
- Procedure ShowPic;assembler;
- asm
- push ds
- mov di,0a000h
- mov es,di
- xor di,di
- mov si,word ptr VScreen
- mov ax,word ptr Vscreen + 2
- mov ds,ax
- mov cx,32000
- rep movsw
- pop ds
- End;
- Procedure ClearPic(Size:Word);assembler;
- asm
- mov ax,word ptr vscreen + 2
- mov es,ax
- mov di,word ptr vscreen
- mov cx,Size
- xor ax,ax
- rep stosw
- End;
- Procedure WaitRetrace;assembler;
- asm
- mov dx,3dah
- @wait1:
- in al,dx
- test al,8h
- jz @wait1
- @wait2:
- in al,dx
- test al,8h
- jnz @wait2
- End;
- Procedure Init_Mode13;assembler;
- asm
- mov ax,13h
- int 10h
- End;
- Procedure Init_ModeX;assembler;
- asm
- mov ax,0013h { Den normalen Mode 13h setzen }
- int 10h
- mov dx,3c4h { Verknpfung aufheben, Einzelzugriff }
- mov al,4 { erm”glichen }
- out dx,al
- inc dx
- in al,dx
- and al,0f7h
- or al,4h
- out dx,al
- dec dx
- mov ax,0f02h
- out dx,ax
- mov ax,0a000h { Bildschirmspeicher l”schen }
- mov es,ax
- xor di,di
- xor ax,ax
- mov cx,8000h
- cld
- rep stosw
- mov dx,3d4h
- mov al,14h
- out dx,al
- inc dx
- in al,dx
- and al,0bfh
- out dx,al
- dec dx
- mov al,17h
- out dx,al
- inc dx
- in al,dx
- or al,40h
- out dx,al
- End;
- Procedure Start(Ofst:Word);assembler;
- asm
- mov dx,3d4h
- mov al,0ch
- mov ah,byte ptr ofst + 1
- out dx,ax
- inc al
- mov ah,byte ptr ofst
- out dx,ax
- End;
- Procedure Split(row:byte);assembler;
- asm
- mov bl,row
- xor bh,bh
- shl bx,1
- mov cx,bx
- mov dx,3d4h
- mov al,07h
- out dx,al
- inc dx
- in al,dx
- and al,11101111b
- shr cx,4
- and cl,16
- or al,cl
- out dx,al
- dec dx
- mov al,09h
- out dx,al
- inc dx
- in al,dx
- and al,10111111b
- shr bl,3
- and bl,64
- or al,bl
- out dx,al
- dec dx
- mov al,18h
- mov ah,row
- shl ah,1
- out dx,ax
- End;
- Procedure enable4;assembler;
- asm
- mov dx,3c4h
- mov ax,0f02h
- out dx,ax
- mov dx,3ceh
- mov ax,4105h
- out dx,ax
- End;
- begin;
- end.Unit Memory;
- {
- **************************************************************************
- *** Die Memory - Unit des Buches PC Underground von DATA BECKER ***
- *** Autor : Boris Bertelsons ***
- *** Erstellt : 26.01.1994 ***
- *** Letzte Žnderung : 18.03.1994 ***
- *** ------------------------------------------------------------------ ***
- *** Die Unit stellt Routinen fr den Umgang mit dem Speicher zur ***
- *** Verfgung. Dies beinhaltet insbesondere Routinen zum Handling von ***
- *** XMS und EMS ! ***
- **************************************************************************
- }
- Interface
- uses dos;
- TYPE XMSHandle = word;
- EMSHandle = word;
- XMS_Copyblock = Record { Wird fr die Kopier-Routinen ben”tigt }
- Size : longint;
- Q_Handle : Word;
- Q_Offset : pointer;
- Z_Handle : Word;
- Z_Offset : pointer;
- end;
- EMS_Header = Record { Zur Erkennung des EMS }
- dummy : array[0..9] of byte;
- Kennung : array[1..7] of char;
- end;
- VAR XMS_Vorhanden : boolean; { TRUE, wenn XMS vorhanden ist }
- XMST : pointer; { Treiber - Einsprungadresse }
- XMS_Version : word; { Die Version des XMS-Treibers }
- XC : XMS_Copyblock;
- EMS_Vorhanden : boolean; { TRUE, wenn EMS vorhanden }
- EMS_Version : word; { Die Nummer der EMS-Version. Dabei steht
- Vers.MAJ im Hi-Byte und VERS.MIN im
- Lo-Byte ! }
- EMS_Seiten_Frei : word; { Die Anzahl der Freien EMS-Seiten }
- EMS_Seiten_Insg : word; { Die Anzahl der insgesamt verfgbaren
- EMS-Seiten }
- function base_free : longint;
- {
- Die Function liefert die GrӇe des maximal insgesamt verfgbaren
- Hauptspeichers in Bytes zurck
- }
- function XMS_free : longint;
- {
- Die Function liefert die GrӇe des maximal insgesamt verfgbaren
- XMS-Speichers in Bytes zurck
- }
- Function Getmem_XMS(VAR H : XMSHandle; Size : longint) : byte;
- {
- Die Function allociert einen Size Bytes groáen Block im XMS. Dabei wird
- Size auf die n„chste KB-Grenze aufgerundet. Die Nummer des Handels, unter
- dem der Block angesprochen werden kann, wird in H zurckgeliefert, und
- darf nicht verloren gehen, weil sonst der Block erst wieder durch ein
- Reset angesprochen werden kann. Konnte der Speicher allociert werden, so
- liefert die Function den Wert 0, sonst gilt die im Buch vorgestellte
- Fehlertabelle.
- }
- Function Freemem_XMS(H : XMSHandle) : byte;
- {
- Die Function gibt einen ber GETMEM_XMS belegten Speicherbereich im XMS
- wieder frei. Das Functions-Ergebnis gilt anhand der XMS-Fehlertabelle.
- }
- Function XMS_2_XMS(h1,h2 : XMSHandle; Size : Word) : byte;
- {
- Diese Function kopiert im XMS von h1 in h2 die in Size bergebene
- Anzahl Bytes. Dabei muá Size einen GERADEN Wert haben. Fr das Functions-
- Ergebnis gilt oben gesagtes.
- }
- Function RAM_2_XMS(q : pointer; h : XMSHandle; Size : Word) : byte;
- {
- Diese Function dient dazu, Daten aus dem Ram ins XMS zu kopieren.
- q ist ein Pointer auf die Quell-Daten im RAM. h ist das Handle, das
- Sie durch die Function GETMEM_XMS erhalten haben. Size ist die GrӇe
- des zu kopierenden Blocks in Byte. Auch hier gilt oben gesagtes fr
- die GrӇe des Blocks und das Functions-Ergebnis.
- }
- Function XMS_2_Ram(d : pointer; h : XMSHandle; Size : Word) : byte;
- {
- Diese Function dient dazu, Daten aus dem XMS ins Ram zu kopieren.
- d ist ein Pointer auf den Ziel-Bereich im RAM. h ist das Handle, das
- Sie durch die Function GETMEM_XMS erhalten haben. Size ist die GrӇe
- des zu kopierenden Blocks in Byte. Auch hier gilt oben gesagtes fr
- die GrӇe des Blocks und das Functions-Ergebnis.
- }
- Procedure Check_for_XMS;
- {
- Die Procedure prft, ob XMS vorhanden ist, und initialisiert die von der
- Unit ben”tigten Variablen. XMS_Vorhanden wird auf TRUE gesetzt, wenn ein
- XMS-Treiber vorhanden ist, die Versionsnummer des Treibers finden Sie in
- XMS_Version.
- }
- procedure Check_for_EMS;
- {
- Die Procedure prft, ob EMS vorhanden ist, und initialisiert entsprechende
- Variablen
- }
- Function EMS_free : longint;
- {
- Die Function liefert die grӇe des freien EMS-Speichers in Bytes zurck.
- }
- Function EMS_Segment_ermitteln(VAR Segment : word) : byte;
- {
- Diese Function ermittelt das Segment, ab dem das EMS im Hauptspeicher
- eingeblendet wird.
- }
- Function EMS_Ermittle_Seitenzahl : byte;
- {
- Diese Function ermittelt, wieviele Seiten im EMS insgesamt zur Verfgung
- stehen, und wiviele davon noch frei sind. Die Werte werden in den globalen
- Variablen "EMS_Seiten_Insg" und "EMS_Seiten_frei" abgelegt.
- }
- Function Getmem_EMS(VAR H : EMSHandle; Size : longint) : byte;
- {
- Diese Function allociert die angegebene Menge Speicher im EMS. Der
- Speicher ist dann ber das Handle "H" ansprechbar. Bitte beachten Sie,
- daá die Function wenigstens eine Seite, also 16KB im EMS, allociert.
- Es sollten also m”glichst nur gr”áere Datenstrukturen im EMS ausgelagert
- werden.
- }
- Function Freemem_EMS(H : EMSHandle) : byte;
- {
- Diese Function gibt den ber Getmem_EMS belegten Speicher wieder frei.
- }
- Function EMS_Zuordnung(H : EMSHandle;PageSeite,EMSSeite : word) : byte;
- {
- Mit dieser Funktion k”nnen Sie die Zuordnung der EMS-Seiten fr das
- entsprechende Handle festlegen. Dabei kann PageSeite einen Wert von 0
- bis 3 einnehmen, und steht fr die Seitenposition, an der sie im RAM
- eingeblendet wird. EMSSeite ist die Seite im EMS, die eingeblendet
- werden soll. Wenn Sie also dem Handle EMSH an erster Stelle die Seite 7
- des EMS (interessant bei Bl”cken > 64 KB !) zuweisen wollen, máen Sie
- die Function mit den Parametern (EMSH,0,7) aufrufen.
- }
- Function EMS_Sichere_Zuordnung(H : EMSHandle) : byte;
- {
- Diese Function sichert die ber EMS_Zuordnung eingestellte Ordnung der
- EMS-Pages fr das angegebene Handle vor Ver„nderungen.
- }
- Function EMS_Entsichere_Zuordnung(H : EMSHandle) : byte;
- {
- Ein ber EMS_Sichere_Zuordnung gesichertes Handle muá zun„chst mit dieser
- Function entsichert werden, bevor die Zuordnung ver„ndert werden kann.
- }
- Function RAM_2_EMS(q : pointer; H : EMSHandle; Size : longint) : byte;
- {
- Mit dieser Function kopieren Sie den angegebenen Block aus dem Ram ins
- EMS. Size bezeichnet die GrӇe in Bytes, q steht fr einen Pointer auf den
- Quellbereich und H ist das ber Getmem_EMS ermittelte Handle.
- }
- Function EMS_2_RAM(q : pointer; H : EMSHandle; Size : longint) : byte;
- {
- Analog zu RAM_2_EMS kopiert diese Function einen Speicherbereich aus dem
- Ram ins EMS.
- }
- Function EMS_Handles_vergeben(Var Anzahl : word) : byte;
- {
- Diese Function liefert Ihnen die Anzahl der bereits vergebenen EMS-Handles.
- Es k”nnen maximal 256 Handles vergeben werden.
- }
- function XMS_lock(H : XMSHandle) : longint;
- {
- Die Funktion sperrt einen XMS-Block gegen das Verschieben und liefert
- seine absolute Adresse
- }
- procedure XMS_unlock(H : XMSHandle);
- {
- Die Procedure entsichert einen gegen Verschieben gesicherten XMS-Block
- }
- implementation
- function base_free : longint;
- begin;
- base_free := MemAvail;
- end;
- function XMS_free : longint;
- var xms_in_kb : word;
- xms_long: longint;
- begin;
- asm
- mov ax,0800h { 8 = Freien Speicher Ermitteln }
- call dword ptr [XMST]
- mov xms_in_kb,dx
- end;
- xms_long := xms_in_kb;
- XMS_free := xms_long * 1024;
- end;
- Function Getmem_XMS(VAR H : XMSHandle; Size : longint) : byte;
- var bsize : word;
- Fresult : byte;
- xmsh : word;
- begin;
- bsize := (size DIV 1024) + 1;
- asm
- mov ax,0900h { 9 = Speicherbereich allocieren }
- mov dx,bsize
- call dword ptr [XMST]
- cmp ax,1
- jne @Fehler_GetmemXms
- mov xmsh,dx
- mov Fresult,0
- jmp @Ende_GetmemXms
- @Fehler_GetmemXMS:
- mov Fresult,bl
- @Ende_GetmemXms:
- end;
- h := xmsh;
- Getmem_Xms := Fresult;
- end;
- Function Freemem_XMS(H : XMSHandle) : byte;
- var fresult : byte;
- begin;
- asm { A = Speicherbereich deallocieren }
- mov ax,0a00h
- mov dx,h
- call dword ptr [XMST]
- cmp ax,1
- jne @Fehler_FreememXms
- mov Fresult,0
- jmp @Ende_FreememXms
- @Fehler_FreememXms:
- mov Fresult,bl
- @Ende_FreememXms:
- end;
- end;
- Function XMS_2_XMS(h1,h2 : XMSHandle; Size : Word) : byte;
- VAR fresult : byte;
- begin;
- XC.Size := Size; { GrӇe des Blocks in Byte }
- XC.Q_Handle := h1; { Quell-Handle }
- XC.Q_Offset := nil; { Quell-Offset, 0 = Blockanfang }
- XC.Z_Handle := h2; { Ziel-Handle }
- XC.Z_Offset := nil; { Ziel-Offset }
- asm
- mov si,offset XC
- mov ax,0B00h
- call dword ptr [XMST]
- cmp ax,1
- jne @Fehler_RAM2XMS
- mov fresult,0
- jmp @Ende_Ram2XMS
- @Fehler_Ram2XMS:
- mov fresult,bl
- @Ende_Ram2XMS:
- end;
- end;
- Function RAM_2_XMS(q : pointer; h : XMSHandle; Size : Word) : byte;
- VAR fresult : byte;
- begin;
- XC.Size := Size;
- XC.Q_Handle := 0; { 0 = RAM }
- XC.Q_Offset := q;
- XC.Z_Handle := h;
- XC.Z_Offset := nil;
- asm
- mov si,offset XC
- mov ax,0B00h
- call dword ptr [XMST]
- cmp ax,1
- jne @Fehler_RAM2XMS
- mov fresult,0
- jmp @Ende_Ram2XMS
- @Fehler_Ram2XMS:
- mov fresult,bl
- @Ende_Ram2XMS:
- end;
- end;
- Function XMS_2_Ram(d : pointer; h : XMSHandle; Size : Word) : byte;
- VAR fresult : byte;
- begin;
- XC.Size := Size;
- XC.Q_Handle := h;
- XC.Q_Offset := nil;
- XC.Z_Handle := 0; { 0 = RAM }
- XC.Z_Offset := d;
- asm
- mov si,offset XC
- mov ax,0B00h
- call dword ptr [XMST]
- cmp ax,1
- jne @Fehler_XMS2RAM
- mov fresult,0
- jmp @Ende_XMS2Ram
- @Fehler_XMS2Ram:
- mov fresult,bl
- @Ende_XMS2Ram:
- end;
- end;
- Procedure Check_for_XMS; assembler;
- asm
- mov ax,4300h { Prfen, ob Treiber Installiert }
- int 2Fh
- cmp al,80h
- jne @Kein_XMSTreiber
- mov ax,4310h { Einsprungadresse des Treibers ermitteln }
- int 2Fh
- mov word ptr XMST + 2,es
- mov word ptr XMST + 0,bx
- xor ax,ax { Versionsnummer ermitteln }
- call dword ptr [XMST]
- cmp ax,0200h
- jb @Kein_XMSTreiber { Wenn Version < 2.0 dann Abbrechen ! }
- mov XMS_Version,ax
- mov XMS_Vorhanden,0
- @Kein_XMSTreiber:
- mov XMS_Vorhanden,1
- @Ende_XMS_Check:
- end;
- procedure Check_for_EMS;
- var emsseg : word;
- emsptr : pointer;
- emshead : EMS_Header;
- begin;
- asm
- mov ax,3567h
- int 21h
- mov emsseg,es
- end;
- move(ptr(emsseg,0)^,emshead,17);
- if emshead.Kennung = 'EMMXXXX' then begin;
- EMS_Vorhanden := true;
- asm
- mov ah,40h { EMS-Treiber Status ermitteln }
- int 67h
- cmp ah,0
- jne @EMS_Vers_Fehler
- mov ah,46h { EMS - Version ermitteln }
- int 67h
- cmp ah,0
- jne @EMS_Vers_Fehler
- mov bl,al
- shr al,4
- mov bh,al { bh = Vers.maj }
- or bl,0Fh { bl = Vers.min }
- mov EMS_Version,bx
- jmp @EMS_Vers_Ende
- @EMS_Vers_Fehler:
- mov EMS_Vorhanden,1
- @EMS_Vers_Ende:
- end;
- end else begin;
- EMS_Vorhanden := false;
- end;
- end;
- Function EMS_Segment_ermitteln(VAR Segment : word) : byte;
- VAR hseg : word;
- fergebnis : byte;
- begin;
- asm
- mov ah,41h
- int 67h
- cmp ah,0
- jne @EMS_Segerm_Fehler
- mov hseg,bx
- mov fergebnis,0
- jmp @EMS_Segerm_Ende
- @EMS_Segerm_Fehler:
- mov fergebnis,ah
- @EMS_Segerm_Ende:
- end;
- Segment := hseg;
- EMS_Segment_ermitteln := fergebnis;
- end;
- Function EMS_Ermittle_Seitenzahl : byte;
- var fergebnis : byte;
- begin;
- asm
- mov ah,42h
- int 67h
- cmp ah,0
- jne @EMS_ErmSeiten_Fehler
- mov EMS_Seiten_Frei,bx
- mov EMS_Seiten_Insg,dx
- mov fergebnis,0
- jmp @EMS_ErmSeiten_Ende
- @EMS_ErmSeiten_Fehler:
- mov fergebnis,ah
- @EMS_ErmSeiten_Ende:
- end;
- EMS_Ermittle_Seitenzahl := fergebnis;
- end;
- function EMS_free : longint;
- var hilfe : longint;
- begin;
- EMS_Ermittle_Seitenzahl;
- hilfe := EMS_Seiten_Frei;
- EMS_free := hilfe SHL 14;
- end;
- Function Getmem_EMS(VAR H : EMSHandle; Size : longint) : byte;
- var Fergebnis : byte;
- ESeiten : word;
- Hhandle : word;
- begin;
- ESeiten := (Size DIV 16384) + 1;
- asm
- mov ah,43h
- mov bx,ESeiten
- int 67h
- cmp ah,0
- jne @Getmem_Ems_Fehler
- mov Hhandle,dx
- mov fergebnis,0
- jmp @Getmem_Ems_Ende
- @Getmem_Ems_Fehler:
- mov Fergebnis,ah
- @Getmem_Ems_Ende:
- end;
- H := Hhandle;
- Getmem_EMS := Fergebnis;
- end;
- Function Freemem_EMS(H : EMSHandle) : byte;
- var Fergebnis : byte;
- begin;
- asm
- mov ah,45h
- mov dx,H
- int 67h
- mov Fergebnis,ah
- end;
- Freemem_EMS := Fergebnis;
- end;
- Function EMS_Zuordnung(H : EMSHandle;PageSeite,EMSSeite : word) : byte;
- VAR Fergebnis : byte;
- begin;
- asm
- mov ah,44h
- mov al,byte ptr PageSeite
- mov bx,EMSSeite
- mov dx,H
- int 67h
- mov Fergebnis,ah
- end;
- EMS_Zuordnung := Fergebnis;
- end;
- Function EMS_Sichere_Zuordnung(H : EMSHandle) : byte;
- VAR Fergebnis : byte;
- begin;
- asm
- mov ah,47h
- mov dx,H
- int 67h
- mov Fergebnis,ah
- end;
- EMS_Sichere_Zuordnung := Fergebnis;
- end;
- Function EMS_Entsichere_Zuordnung(H : EMSHandle) : byte;
- VAR Fergebnis : byte;
- begin;
- asm
- mov ah,48h
- mov dx,H
- int 67h
- mov Fergebnis,ah
- end;
- EMS_Entsichere_Zuordnung := Fergebnis;
- end;
- Function RAM_2_EMS(q : pointer; H : EMSHandle; Size : longint) : byte;
- VAR fergebnis : byte;
- EMSseg : word;
- hp : ^byte;
- li : word;
- begin;
- EMS_Segment_ermitteln(EMSseg);
- hp := q;
- if Size > 16384 then begin;
- { Mehr al eine Page erforderlich }
- for li := 0 to (Size SHR 14)-1 do begin;
- EMS_Zuordnung(H,0,li);
- move(hp^,ptr(EMSseg,0)^,16384);
- dec(Size,16384);
- inc(hp,16384);
- end;
- EMS_Zuordnung(H,0,li+1);
- move(hp^,ptr(EMSseg,0)^,16384);
- dec(Size,16384);
- inc(hp,16384);
- end else begin;
- EMS_Zuordnung(H,0,0);
- move(hp^,ptr(EMSseg,0)^,16384);
- dec(Size,16384);
- inc(hp,16384);
- end;
- end;
- Function EMS_2_RAM(q : pointer; H : EMSHandle; Size : longint) : byte;
- VAR fergebnis : byte;
- EMSseg : word;
- hp : ^byte;
- li : word;
- begin;
- EMS_Segment_ermitteln(EMSseg);
- hp := q;
- if Size > 16384 then begin;
- { Mehr al eine Page erforderlich }
- for li := 0 to (Size SHR 14)-1 do begin;
- EMS_Zuordnung(H,0,li);
- move(ptr(EMSseg,0)^,hp^,16384);
- dec(Size,16384);
- inc(hp,16384);
- end;
- EMS_Zuordnung(H,0,li+1);
- move(ptr(EMSseg,0)^,hp^,16384);
- dec(Size,16384);
- inc(hp,16384);
- end else begin;
- EMS_Zuordnung(H,0,0);
- move(ptr(EMSseg,0)^,hp^,16384);
- dec(Size,16384);
- inc(hp,16384);
- end;
- end;
- Function EMS_Seiten_belegt(H : EMSHandle;var Seiten : word) : byte;
- var fergebnis : byte;
- Hs : word;
- begin;
- asm
- mov ah,4Ch
- mov dx,H
- int 67h
- mov HS,bx
- mov fergebnis,ah
- end;
- Seiten := Hs;
- EMS_Seiten_belegt := Fergebnis;
- end;
- Function EMS_Handles_vergeben(Var Anzahl : word) : byte;
- Var Fergebnis : byte;
- Han : word;
- begin;
- asm
- mov ah,4Bh
- int 67h
- mov Han,bx
- mov Fergebnis,ah
- end;
- Anzahl := Han;
- EMS_Handles_vergeben := Fergebnis;
- end;
- function XMS_lock(H : XMSHandle) : longint; assembler;
- asm;
- mov ax,0c00h
- mov dx,h
- call dword ptr [XMST]
- mov ax,bx
- end;
- procedure XMS_unlock(H : XMSHandle); assembler;
- asm;
- mov ax,0d00h
- mov dx,h
- call dword ptr [XMST]
- end;
- begin;
- Check_for_XMS;
- Check_for_EMS;
- end.
- program Mem_test;
- uses Memory,crt,gifunit;
- var xmsh : array[1..2] of XMSHandle;
- emsh : array[1..2] of EMSHandle;
- procedure xms_testen;
- var ta : array[1..20] of word;
- li : integer;
- begin;
- { Array mit Zahlen versorgen & testweise ausgeben }
- gotoxy(1,5); write('Orginal: ');
- for li := 1 to 20 do begin;
- ta[li] := li;
- gotoxy(14,li+4);
- write(ta[li]);
- end;
- readln;
- { Array ins XMS sichern, mit 0 fllen und zur Kontrolle ausgeben }
- gotoxy(21,5); write('Ins XMS gesichert &');
- gotoxy(21,6); write('mit 0 gefllt:');
- Getmem_XMS(xmsh[1],40);
- RAM_2_XMS(@ta,xmsh[1],40);
- fillchar(ta,40,0);
- for li := 1 to 20 do begin;
- gotoxy(44,li+4);
- write(ta[li]);
- end;
- readln;
- { Speicher im XMS kopieren, Array aus der Kopie im XMS wieder herstellen }
- gotoxy(54,5); write('Aus XMS wieder');
- gotoxy(54,6); write('hergestellt: ');
- Getmem_XMS(xmsh[2],40);
- XMS_2_XMS(xmsh[1],xmsh[2],40);
- XMS_2_RAM(@ta,xmsh[2],40);
- for li := 1 to 20 do begin;
- gotoxy(74,li+4);
- write(ta[li]);
- end;
- readln;
- Freemem_XMS(xmsH[1]);
- Freemem_XMS(xmsH[2]);
- end;
- procedure Ems_testen;
- var ta : array[1..20] of word;
- li : integer;
- picptr : pointer;
- begin;
- getmem(picptr,64000);
- Init_ModeX;
- blackpal;
- LoadGif('Beispiel.gif',picptr,0,0);
- Getmem_EMS(emsh[1],64000);
- RAM_2_EMS(picptr,emsh[1],64000);
- freemem(picptr,64000);
- getmem(vscreen,64000);
- fillchar(vscreen^,64000,123);
- EMS_2_RAM(vscreen,emsh[1],64000);
- p13_2_modex(0,16000);
- setpal;
- readln;
- freemem(vscreen,64000);
- Freemem_EMS(emsH[1]);
- asm mov ax,0003; int 10h; end;
- end;
- begin;
- clrscr;
- writeln('Programm zur Demonstration der Unit > MEMORY <');
- writeln('(c) 1994 by DATA BECKER Autor: Boris Bertelsons');
- writeln;
- writeln('Freier Hauptspeicher: ',Base_Free,' Bytes');
- writeln('Freies XMS : ',XMS_Free,' Bytes');
- writeln('Freies EMS : ',EMS_Free,' Bytes');
- writeln('XMS Version : ',hi(XMS_Version),'.',lo(XMS_Version));
- writeln('EMS Version : ',hi(EMS_Version),'.',lo(EMS_Version));
- readln;
- clrscr;
- writeln('Programm zur Demonstration der Unit > MEMORY <');
- writeln('(c) 1994 by DATA BECKER Autor: Boris Bertelsons');
- writeln;
- writeln(' X M S - T E S T');
- if XMS_Vorhanden then
- xms_testen
- else
- writeln('Es ist kein XMS-Speicher vorhanden !');
- clrscr;
- writeln('Programm zur Demonstration der Unit > MEMORY <');
- writeln('(c) 1994 by DATA BECKER Autor: Boris Bertelsons');
- writeln;
- writeln(' E M S - T E S T');
- if EMS_Vorhanden then
- ems_testen
- else
- writeln('Es ist kein EMS-Speicher vorhanden !');
- end..386p
- .MODEL TPASCAL
- .DATA
- oldint3 dd ?
- alter_interrupt3 dd ?
- .CODE
- public PIQ_Stop_System
- public Keyboard_aus
- public Keyboard_ein
- public No_Stepping
- keyb_off macro
- push ax
- in al,21h
- or al,02
- out 21h,al
- pop ax
- endm
- keyb_on macro
- push ax
- in al,21h
- and al,0Fdh
- out 21h,al
- pop ax
- endm
- PIQ_Stop_System proc near
- push ds
- push ax
- push bx
- push cs
- pop ds ; CS nach DS
- mov cs:word ptr [@int_21_funkt],4CB4h ; Funktion Prg. beenden
- @int_21_funkt:
- mov ah,30h ; Funktion DOS-Vers. ermitteln
- int 21h
- pop bx
- pop ax
- pop ds
- ret
- PIQ_Stop_System endp
- Keyboard_aus proc near
- keyb_off
- ret
- Keyboard_aus endp
- Keyboard_ein proc near
- keyb_on
- ret
- Keyboard_ein endp
- No_Stepping proc near
- push ax
- jmp @Nostep+2
- @Nostep:
- mov ds:byte ptr [06EBh],00
- mov ax,4C01h
- int 21h
- pop ax
- ret
- No_Stepping endp
- public protected_stopping
- protected_stopping proc pascal
- pusha
- cli ; Interrupts ausschalten
- mov eax,cr0 ; In den Protected-Mode schalten
- or eax,1
- mov cr0,eax
- jmp PROTECTION_ENABLED ; Executionpipe l”schen
- PROTECTION_ENABLED:
- and al,0FEh ; Wieder in den Real-Mode schalten
- mov cr0,eax ; CPU nicht resetten
- jmp PROTECTION_DISABLED ; Executionpipe l”schen
- PROTECTION_DISABLED:
- sti ; Interrupts wieder einschalten
- popa
- ret
- protected_stopping endp
- public Check_auf_vector
- Check_auf_vector proc pascal check : dword;
- mov bx,0
- mov es,bx
- mov bx,18
- mov eax,es:[bx]
- mov oldint3,eax
- mov eax,check
- mov es:[bx],eax
- ret
- Check_auf_vector endp
- public Vector_ok
- Vector_ok proc pascal check : dword;
- mov bx,0
- mov es,bx
- mov bx,18
- mov eax,es:[bx]
- cmp eax,check
- je @check_ok
- mov al,0
- jmp @check_ende
- @check_ok:
- mov al,1
- @check_ende:
- ret
- Vector_ok endp
- public restore_Checkvector
- restore_Checkvector proc pascal
- mov bx,0
- mov es,bx
- mov bx,18
- mov eax,oldint3
- mov es:[bx],eax
- ret
- restore_Checkvector endp
- public Copy_int21_int3
- Copy_int21_int3 proc pascal
- mov bx,0
- mov es,bx
- mov bx,18
- mov eax,es:[bx]
- mov alter_interrupt3,eax ; alten int3 sichern
- mov bx,84 ; Int 21 laden
- mov eax,es:[bx]
- mov bx,18 ; in int3 speichern
- mov es:[bx],eax
- ret
- Copy_int21_int3 endp
- end{$M $4000,550000,550000}
- program nodebug;
- uses crt;
- {$L nodeb.obj}
- procedure PIQ_Stop_System; far; external;
- procedure keyboard_aus; far; external;
- procedure keyboard_ein; far; external;
- procedure no_stepping; far; external;
- procedure protected_stopping; far; external;
- procedure check_auf_Vector(check : longint); far; external;
- procedure Restore_checkVector; far; external;
- function Vector_OK(check : longint) : boolean; far; external;
- procedure Copy_int21_int3; far; external;
- begin;
- clrscr;
- writeln('Checksumme auf Int3-Vector');
- check_auf_Vector(12345678);
- writeln('Keyboard ausschalten');
- keyboard_aus;
- writeln('Stepping-Falle');
- no_stepping;
- writeln('PIQ-Trick');
- PIQ_Stop_System;
- writeln('Protected-Mode switching');
- Protected_stopping;
- writeln('Vector-Checking');
- If NOT Vector_Ok(12345678) then begin;
- clrscr;
- writeln('Na na, nicht debuggen !');
- halt(0);
- end;
- writeln('Check-Vector wieder herstellen');
- Restore_checkVector;
- writeln('Keyboard wieder einschalten');
- keyboard_ein;
- writeln('Und wir sind im Programm');
- readln;
- end.
- {$M $4000,550000,550000}
- program nodebug;
- uses crt;
- {$L nodeb.obj}
- procedure PIQ_Stop_System; far; external;
- procedure keyboard_aus; far; external;
- procedure keyboard_ein; far; external;
- procedure no_stepping; far; external;
- procedure protected_stopping; far; external;
- procedure check_auf_Vector(check : longint); far; external;
- procedure Restore_checkVector; far; external;
- function Vector_OK(check : longint) : boolean; far; external;
- procedure Copy_int21_int3; far; external;
- begin;
- clrscr;
- writeln('Checksumme auf Int3-Vector');
- check_auf_Vector(12345678);
- writeln('Keyboard ausschalten');
- keyboard_aus;
- writeln('Stepping-Falle');
- no_stepping;
- writeln('PIQ-Trick');
- PIQ_Stop_System;
- writeln('Protected-Mode switching');
- Protected_stopping;
- writeln('Vector-Checking');
- If NOT Vector_Ok(12345678) then begin;
- clrscr;
- writeln('Na na, nicht debuggen !');
- halt(0);
- end;
- writeln('Check-Vector wieder herstellen');
- Restore_checkVector;
- writeln('Keyboard wieder einschalten');
- keyboard_ein;
- writeln('Und wir sind im Programm');
- readln;
- end.
- data segment public
- start_meldung: db 'Kein Reset mehr m”glich',0dh,0ah,'$'
- puffer: db 40d ;L„nge des Eingabe-Puffers
- db 40 dup (0) ;Puffer
- old_int9 dd 0 ;alter Interrupt-Hanlder
- data ends
- code segment public
- assume cs:code,ds:data
- handler9 proc near ;neuer Interrupt 9-Handler
- push ax ;benutzte Register sichern
- push bx
- push ds
- push es
- mov ax,data ;ds laden
- mov ds,ax
- in al,60h ;Zeichen von Tastatur lesen in al
- xor bx,bx ;es auf Segment 0
- mov es,bx
- mov bl,byte ptr es:[417h] ;Tastatur-Status in bl laden
- cmp al,83d ;Scan-Code der Entf-Taste ?
- jne kein_Reset ;nein, dann kein Reset
- and bl,0ch ;Strg u. Alt maskieren
- cmp bl,0ch ;beide gedrckt ?
- jne kein_Reset ;nein, dann kein Reset
- Block: ;Reset oder Break, also blockieren
- mov al,20h ;EoI an Interrupt-Controller senden
- out 20h,al
- jmp fertig ;und Interrupt verlassen
- kein_Reset: ;kein Reset, jetzt noch Brak prfen
- cmp al,224d ;erweiterte Taste ?
- je evtl_Break ;ja -> eventuell Break ausgel”st
- cmp al,46d ;Taste 'C' ?
- jne legal ;nein -> legale Taste
- evtl_Break:
- test bl,4 ;Tastatur-Status auf Strg testen
- jne Block ;gedrckt, dann blockieren
- legal: ;legale Taste -> alten Handler aufrufen
- pushf
- call dword ptr [old_int9] ;Original-Handler aufrufen
- fertig:
- pop es
- pop ds ;Register zurckholen
- pop bx
- pop ax
- iret
- handler9 endp
- start proc near
- mov ax,data ;ds laden
- mov ds,ax
- mov dx,offset start_meldung ;dx mit Offset d. Meldung laden
- mov ah,09h ;Meldung ausgeben
- int 21h
- mov ax,3509h ;alten Interrupt-Vektor lesen
- int 21h
- mov word ptr old_int9,bx ;und speichern
- mov word ptr old_int9 + 2, es
- push ds ;ds sichern
- mov ax,cs ;mit cs laden
- mov ds,ax
- mov dx,offset handler9 ;auch Offset des Handlers laden
- mov ax,2509h ;Vektor setzen
- int 21h
- pop ds
- ;-------------------------------------------------------------------------
- ;Hier kann statt des Dos-Aufrufs ein Call zu Ihrem Hauptprogramm stehen
- mov ah,0ah ;Zeichenkette einlesen
- lea dx,puffer ;als Beispiel-Hauptprogramm
- int 21h
- ;-------------------------------------------------------------------------
- push ds
- lds dx,old_int9 ;alten Vektor wieder setzen
- mov ax,2509h
- int 21h
- pop ds
- mov ax,4c00h ;Programm beenden
- int 21h
- start endp
- code ends
- end start
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement