PCX-Bilder in Assembler ----------------------- Nachdem Ihr sicherlich schon die Theorieabhandlung des PCX-For- mats gelesen habt, gibt's jetzt etwas Handfestes in Assembler. Das folgende Programm liest ein 320x200x256-PCX-Bild ein und bringt es auf die (dann bunte) Mattscheibe. Ich werde mich dabei wieder an die im 'Theorie-Text' beschriebene Struktur halten. O.K, ersteinmal das Listing, danach ein paar Anmerkungen: SHOWPCX320x200x256 PROC lea dx,DateiName mov ax,3d00h int 21h ; Datei ”ffnen mov Handle,ax ; FileHandle nach Handle mov ax,3F00h mov bx,Handle mov cx,128 lea dx,Header int 21h ; Header auslesen mov Video_Offset,0 mov repeatCount,0 Schleife: mov ax,3F00h mov bx,Handle mov cx,Buff_Size lea dx,DatenPuffer int 21h ; 50000b aus PCX-File lesen jc Ende ; Wenn Fehler aufgetreten -> Ende cmp ax,0 je MakePalette ;0 Byte gelesen -> Ende mov BytesRead,ax call Decode ;Gelesene Bytes decodieren jmp Schleife MakePalette: mov ah,42h mov al,02h mov bx,Handle mov cx,0 mov dx,0 int 21h ;Laenge der Datei bestimmen sub ax,768 ;DWord (DX:AX) um 768 erniedrigen jnc nextpal sub dx,1 nextpal: mov cx,dx mov dx,ax mov ah,42h mov al,00h mov bx,Handle int 21h ;FilePointer 768b vor Ende setzen mov ah,3Fh mov bx,Handle mov cx,768 lea dx,Palette int 21h ; 768b aus File lesen (in Palette) lea bx,Palette mov cx,768 decrease: mov ah,[bx] shr ah,2 mov [bx],ah inc bx loop decrease ;Alle Farbeintr„ge durch 4 teilen mov ax,1012h mov bx,0 mov cx,256 mov dx,Seg Palette mov es,dx lea dx,Palette int 10h ;256 Farben setzen DateiSchliessen: mov ah,3Eh mov bx,Handle int 21h ; Datei schlieáen ENDE: ret ShowPCX320x200x256 ENDP Decode Proc mov ax, Page_Addr ; Video-Segment nach AX mov es, ax ; Video-Segment nach ES mov di, Video_Offset ; Video_Offset nach DI xor cx, cx ; CX auf null mov cl, RepeatCount ; Anzahl der Wiederholungen nach CL mov bx, BytesRead ; Anzahl der gelesenen Bytes nach BX lea si, DatenPuffer ; Offset von DatenPuffer nach SI add bx, si ; Offset-Ende vom Puffer in BX cld ; L”sche DF - INC DI (stosb/lodsb) checkbyte: cmp si, bx ; Noch Daten da? je exit ; Wenn nicht : EXIT lodsb ; Lade n„chstes Byte nach AL cmp cl, 0 ; Wiederholungsschleife ? jne WriteByte ; Wenn ja : WriteByte cmp al, 11000000b ; Sonst prfe BIT 7+6 (> 192) jb VorWriteByte ; Nicht gesetzt -> VorWriteByte and al, 00111111b ; BIT 0-5 : Wiederholungsz„hler mov cl, al ; Wiederholungsanzahl nach CL jmp checkbyte ; Prfe n„chste Data VorWriteByte: mov cl,1 WriteByte: stosb ; AL in VideoSpeicher, INC DI cmp di,64000 je Exit ; Wenn 64000 Punkte gesetzt wurden, ; n„chstes Fenster einblenden loop writebyte jmp checkbyte ; Prfe n„chste Data exit: mov Video_Offset, di mov repeatcount, cl ret ;Werte zwischenspeichern und zurck Decode Endp Das Listing beinhaltet nur die Prozedur zum darstellen des PCX- Bildes. Der VideoModus 13h (320x200x256) muá gesetzt sein, und folgendes muá im Hauptprogramm deklariert sein: Page_Addr equ 0A000h Buff_Size equ 50000 .DATA Handle dw (?) ; Filehandle zum Zugriff auf Datei Header db 128 dup (?) ; Buffer fr Header RepeatCount db (?) ; Wiederholungszaehler BytesRead dw (?) ; L„nge der gelesenen Daten in Byte Video_Offset dw (?) ; Offset-Addy vom ViedeoRam DatenPuffer db Buff_Size dup (?) ; Tab fr gelesene Bytes Palette db 768 dup (?) ; Nimmt Palette auf DateiName db 'test.pcx',0 ; Beliebiger Dateiname Der angegebene Dateiname sollte wirklich existieren und auch ein PCX-Bild sein, sonst k”nnte es zu Problemen kommen. Der QuellCode ist zwar einigermaáen dokumentiert, l„át aber bestimmt noch einige Fragen offen. Wenn Ihr genau hinschaut, seht Ihr aber, daá ich das im Theorieteil beschriebene Schema zum anzei- gen eines Bildes tats„chlich benutzt habe. Nachdem die Datei ge”ffnet und der Header ausgelesen wurde, be- ginnt die Ausgabe des Bildes (Marke: Schleife). Es werden nach M”glichkeit 50000 Byte ausgelesen. Die reale Anzahl der gele- senen Bytes steht im AX-Register. Sollte hier eine Null zu finden sein, so wurden alle Daten ausgelesen. Danach wird dann die Pa- lette gesetzt und die Prozedur verlassen. Sollten Daten gelesen worden sein, so wird die Prozedur 'Decode' angesprungen. Hier geht's nun (nach der Initialisierung einiger Werte) in 'CheckByte' richtig los. Es wird ein Byte ausgelesen und ber- prft, ob die obersten beiden Bits gesetzt sind (192...). Ist das der Fall, so werden diese beiden Bits ausgeblendet (Byte AND 00111111b). Der verbleibende Wert repr„sentiert den Index, der in CX (dem Wiederholungsz„hler) gespeichert wird. Das n„chste Byte wird ausgelesen. Da CX > 0 ist, wird WriteByte angesprungen, wo dieses neue Byte nun in den Videospeicher ge- schrieben wird (mit STOSB). Dabei wird auch DI erh”ht, der gleichzeitig als 'Pixelz„hler' eingesetzt werden kann. Wurden 64000 Pixel gesetzt (320x200), so steht das Bild vollst„ndig auf dem Bildschirm, und die Palette kann gesetzt werden. Wenn nicht, wird, nachdem die Pixel gesetzt wurden, wieder von vorne begonnen. Sollte bei einem ausgelesenem Byte nicht die obersten beiden Bits gesetzt sein, so wird das Byte nur einmal in den Speicher ge- schrieben (VorWriteByte: CX (=Index) auf 1). Tja, wahrscheinlich ist immer noch nicht alles gekl„rt, aber das Grundprinzip drfte wohl verstanden sein. Alle die, die noch kein Vorwissen ber den 320x200x256-Grafikmo- dus haben, sollten sich das n„chste STOD antun, da dort auch darber etwas zufinden sein wird. Da ich mich noch nicht besonders gut mit den Schlsselw”rtern Public und Extern etc. auskenne, weiá ich auch nicht, wie ich obiges als externe Linkdatei angeben kann. Daher diese etwas aufwendige Methode mit der Deklaration der benutzten Variablen im Hauptprogramm und nicht in der Prozedur selber. Sollte es jemand besser wissen, kann er ja mal schreiben... Tja, das war's dann auch schon mit diesem Artikel. Wenn noch Fragen offen stehen sollten: immer her damit! Das Listing befindet sich natrlich auch in dem QuellCode-Pfad 'SOURCES'. Kemil