;²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²
; lbm.asm - IFF/ILBM decoder for VGA 640x480x16 graphics mode
;²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²

ideal
p386
model   flat,c

;ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
; PUBLICS
;ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ

global  putlbm:proc

;ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
; EQUATES AND STRUCTURES
;ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ

ID_FORM         = 4D524F46h             ; IFF/ILBM chunk IDs
ID_ILBM         = 4D424C49h
ID_BMHD         = 44484D42h
ID_CMAP         = 50414D43h
ID_BODY         = 59444F42h

struc   Form                            ; IFF/ILBM header file format
  ID            dd      ?
  Length        dd      ?
  Type          dd      ?
ends    Form

struc   Chunk                           ; IFF/ILBM header chunk format
  ID            dd      ?
  Length        dd      ?
ends    Chunk

struc   BMHD                            ; IFF/ILBM BMHD chunk format
  Width         dw      ?
  Height        dw      ?
  PosX          dw      ?
  PosY          dw      ?
  Planes        db      ?
  Masking       db      ?
  Compression   db      ?
  Pad           db      ?
  Transparent   dw      ?
  AspectX       db      ?
  AspectY       db      ?
  PageWidth     dw      ?
  PageHeight    dw      ?
ends    BMHD

struc   CMAP                            ; IFF/ILBM CMAP chunk format
  Colors        db      768 dup (?)
ends    CMAP

;ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
; DATA
;ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
dataseg

width   dd      ?                       ; current picture width and height
height  dd      ?

;ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
; CODE
;ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ
codeseg

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; bswap - macro to reverse the byte order of a 32-bit register, converting
;         a value in little/big endian form to big/little endian form.
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
macro   bswap   reg
        xchg    al,ah
        rol     eax,16
        xchg    al,ah
endm

;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
; putlbm - draw the IFF/ILBM picture on VGA 640x480x16 graphics mode
; In:
;  ESI = IFF/ILBM image file address
;°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
putlbm:
        pushad

; check if this is a valid IFF/ILBM Deluxe Paint file

        cmp     [esi+Form.ID],ID_FORM
        jne     putlbmd0
        cmp     [esi+Form.Type],ID_ILBM
        jne     putlbmd0

; get the IFF/ILBM file length in bytes

        mov     eax,[esi+Form.Length]
        bswap   eax
        mov     ecx,eax

; decrease the file length and updates the file pointer

        sub     ecx,4
        add     esi,size Form

; IFF/ILBM main parser body loop

putlbml0:
        test    ecx,ecx
        jle     putlbmd1

; get the next chunk ID and length in bytes

        mov     ebx,[esi+Chunk.ID]
        mov     eax,[esi+Chunk.Length]
        bswap   eax
        xchg    ebx,eax
        add     esi,size Chunk

; word align the chunk length and decrease the file length counter

        inc     ebx
        and     bl,not 1
        sub     ecx,size Chunk
        sub     ecx,ebx

; check for the BMHD/CMAP/BODY chunk headers

        cmp     eax,ID_BMHD
        je      putlbmf0
        cmp     eax,ID_CMAP
        je      putlbmf1
        cmp     eax,ID_BODY
        je      putlbmf2

; advance to the next IFF/ILBM chunk structure

putlbmc0:
        add     esi,ebx
        jmp     putlbml0

; process the BMHD bitmap header chunk

putlbmf0:
        cmp     [esi+BMHD.Planes],4
        jne     putlbmd0
        cmp     [esi+BMHD.Compression],1
        jne     putlbmd0
        cmp     [esi+BMHD.Pad],0
        jne     putlbmd0
        movzx   eax,[esi+BMHD.Width]
        xchg    al,ah
        add     eax,7
        shr     eax,3
        mov     [width],eax
        movzx   eax,[esi+BMHD.Height]
        xchg    al,ah
        mov     [height],eax
        jmp     putlbmc0

; process the CMAP colormap chunk

putlbmf1:
        mov     dx,3C8h
        xor     al,al
        out     dx,al
        inc     dx
putlbml1:
        mov     al,[esi]
        shr     al,2
        out     dx,al
        inc     esi
        dec     ebx
        jg      putlbml1
        jmp     putlbml0

; process the BODY bitmap body chunk

putlbmf2:
        pushad
        push    es
        mov     ax,ds
        mov     es,ax
        mov     edi,0A0000h
        cld
        mov     dx,3CEh
        mov     ax,0FF08h
        out     dx,ax
        mov     dx,3C4h
        mov     al,02h
        out     dx,al
        inc     dx
        mov     ecx,[height]
putlbml2:
        push    ecx
        mov     al,11h
putlbml3:
        push    eax
        push    edi
        out     dx,al
        mov     ebx,[width]
putlbml4:
        lodsb
        test    al,al
        jl      putlbmf3
        movzx   ecx,al
        inc     ecx
        sub     ebx,ecx
        rep     movsb
        jmp     putlbmc4
putlbmf3:
        neg     al
        movzx   ecx,al
        inc     ecx
        sub     ebx,ecx
        lodsb
        rep     stosb
putlbmc4:
        test    ebx,ebx
        jg      putlbml4
        pop     edi
        pop     eax
        add     al,al
        jnc     putlbml3
        add     edi,80
        pop     ecx
        loop    putlbml2
        pop     es
        popad
        jmp     putlbmc0

putlbmd1:
        clc
        popad
        ret
putlbmd0:
        stc
        popad
        ret

end

