

                    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 Farbeintrge 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 schlieen

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                      ; Lsche DF - INC DI (stosb/lodsb)

checkbyte:
    cmp si, bx               ; Noch Daten da?
    je exit                  ; Wenn nicht : EXIT
    lodsb                    ; Lade nchstes 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 : Wiederholungszhler
    mov cl, al               ; Wiederholungsanzahl nach CL
    jmp checkbyte            ; Prfe nchste Data

VorWriteByte:
    mov cl,1

WriteByte:
    stosb                    ; AL in VideoSpeicher, INC DI

    cmp di,64000
    je Exit                  ; Wenn 64000 Punkte gesetzt wurden,
                             ; nchstes Fenster einblenden
    loop writebyte

    jmp checkbyte            ; Prfe nchste 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 (?)          ; Lnge 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 knnte es zu Problemen kommen. Der
QuellCode ist zwar einigermaen dokumentiert, lt 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 tatschlich benutzt habe.

Nachdem die Datei geffnet und der Header ausgelesen wurde, be-
ginnt die Ausgabe des Bildes (Marke: Schleife). Es werden nach
Mglichkeit 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 reprsentiert den
Index, der in CX (dem Wiederholungszhler) gespeichert wird.
Das nchste 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 erhht, der
gleichzeitig als 'Pixelzhler' eingesetzt werden kann. Wurden
64000 Pixel gesetzt (320x200), so steht das Bild vollstndig
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 geklrt, aber
das Grundprinzip drfte wohl verstanden sein.
Alle die, die noch kein Vorwissen ber den 320x200x256-Grafikmo-
dus haben, sollten sich das nchste STOD antun, da dort auch
darber etwas zufinden sein wird.

Da ich mich noch nicht besonders gut mit den Schlsselwrtern
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

