;; wresrle.asm: WinRes RLE Decoding
;; Copr. 1996 Matthias K"oppe

;    $Id: wresrle.asm 1.3 1999/02/09 11:09:19 mkoeppe Exp $
 
;    This library is free software; you can redistribute it and/or
;    modify it under the terms of the GNU Library General Public
;    License as published by the Free Software Foundation; either
;    version 2 of the License, or (at your option) any later version.

;    This library is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;    Library General Public License for more details.

;    You should have received a copy of the GNU Library General Public
;    License along with this library; if not, write to the Free
;    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

	
	IDEAL
	LOCALS @@
	JUMPS

STRUC	TBitmap
  bmType	DW	?
  bmWidth	DW	?
  bmHeight	DW	?
  bmWidthBytes	DW	?
  bmPlanes	DB	?
  bmBitsPixel	DB	?
  bmBits	DD	?
  bmPalette	DD	?
  bmFast	DD	?
ENDS

SEGMENT	DATA WORD PUBLIC

	ASSUME	DS:DATA

	EXTRN	RLEBitmapChunkSize: DWORD

ENDS

SEGMENT	CODE BYTE PUBLIC

	ASSUME	CS:CODE

	PUBLIC	DecodeRLE4, \
		DecodeRLE8

	P386

	;; destination overflow is not handled yet.
	;; Must pass: 	pixel count (or byte + half-flag)
	;;		fill byte
	;; (only delta fills need to be handled; absolute data
	;; shouldn't be allowed to overlap line ends.)

PROC	DecodeRLE4 NEAR
	ARG	Bitmap: DWORD, Buffer: DWORD = ArgSize
	LOCAL	ChunkEnd: WORD, BitmapStart: WORD, BitmapEnd: WORD, \
		BitmapWidth: WORD = LocalSize

	enter	LocalSize, 0
	mov	eax, [RLEBitmapChunkSize]
	push	ds
	lds	si, [Buffer]
	add	ax, si
	mov	[ChunkEnd], ax

	les	bx, [Bitmap]
	mov	ax, [(TBitmap (es:bx)).bmWidthBytes]
	mov	[BitmapWidth], ax
	mov	cx, [(TBitmap (es:bx)).bmHeight]
	or	cx, cx
	jns	SHORT @@M
	neg	cx
@@M:
	mul	cx
	les	di, [(TBitmap (es:bx)).bmBits]
	mov	[BitmapStart], di
	add	ax, di
	mov	[BitmapEnd], ax

	mov	bl, 0			; half-byte counter
	cld

@@next:
	cmp	di, [BitmapEnd]
	jae	@@end			; end of destination bitmap reached

	cmp	si, [ChunkEnd]
	jae	@@outofdata		; out of data

	lodsw				; load command word
	or	al, al			; absolute mode?
	jz	SHORT @@absolute
@@coded:
	mov	cx, ax
	xor	ch, ch			; cx pixel count
	mov	al, ah
	or	bl, bl			; at half byte?
	jz	SHORT @@full
@@half:
	rol	al, 4			; swap pixels
	mov	ah, al
	and	ah, 0Fh
	or	[es:di], ah		; fill half byte
	inc	di
	xor     bl, bl
	dec	cx
@@full:
	shr	cx, 1			; byte count
	rep	stosb			; store them
	jnc	@@next

	and	ah, 0f0h
	mov	[es:di], ah
	mov	bl, 1			; was half byte
	jmp	@@next

@@absolute:
	cmp	ah, 0
	jz      SHORT @@lineend

	cmp	ah, 1
	jz	@@end

	cmp	ah, 2
	jz	SHORT @@delta

	mov	cl, ah			; cx pixel count
	xor	ch, ch
@@1:
	or	bl, bl
	jnz     SHORT @@shifthalf
@@copy:
	shr	cx, 1
	rep	movsb
	jnc	SHORT @@endabsolute

	lodsb				; handle last pixel
	and	al, 0f0h
	mov	[es:di], al
	mov	bl, 1
	jmp	SHORT @@endabsolute
@@shifthalf:
	lodsb				; get first byte
	mov	ah, al
	shr	ah, 4
	or	[es:di], ah		; fill half byte
	xor	bl, bl
	dec	cx
@@2:
	mov	ah, al
	lodsb
	shl	ax, 4
	sub	cx, 2
	jbe	SHORT @@3		; less than 2 pixels left

	mov	[es:di], ah
	inc	di
	jmp	@@2
@@3:
	jz	SHORT @@endabsolute	; no pixel left
	and	ah, 0f0h
	mov	[es:di], ah		; fill half byte
	mov	bl, 1
@@endabsolute:
	inc	si
	and	si, 0fffeh		; round up to word boundary
	jmp	@@next

@@lineend:
	mov	ax, di
	sub	ax, [BitmapStart]
	jz	SHORT @@9

	xor	dx, dx
	dec	ax
	div	[BitmapWidth]
	inc	ax			; next line
	mul	[BitmapWidth]
@@9:
	add	ax, [BitmapStart]	; ax byte at next line
	mov	bh, 0			; don't make half byte
	cmp	bl, 0
	jz	SHORT @@4

	inc	di			; skip half byte
@@4:
	mov	di, ax
	jmp	SHORT @@fillto
@@delta:
	lodsw				; read delta values
	mov	cx, ax
	shr	ax, 8
	mul	[BitmapWidth]
	add	ax, di
	xor	bh, bh
	shr	cl, 1
	jnc	SHORT @@5

	mov	bh, 1			; make half byte
@@5:
	cmp	bl, 0
	jz	SHORT @@6

	inc	di
	xor	bh, 1
	jz	SHORT @@6

	dec	ax
@@6:
	xor	ch, ch
	add	ax, cx

@@fillto:
	mov	cx, ax
	sub	cx, di
	xor	al, al
	rep	stosb
	mov	bl, bh
	or	bl, bl
	jz	@@next

	mov	[BYTE es:di], 0
	jmp     @@next

@@end:
	mov	dx, 1			; indicate: bitmap is ready
	jmp	SHORT @@0
@@outofdata:
	xor	dx, dx			; indicate: out of data
@@0:
	mov	ax, si
	sub	ax, [BitmapStart]
	pop	ds
	leave
	ret	ArgSize
ENDP

PROC	DecodeRLE8
	ARG	Bitmap: DWORD, Buffer: DWORD = ArgSize
	LOCAL	ChunkEnd: WORD, BitmapStart: WORD, BitmapEnd: WORD, \
		BitmapWidth: WORD = LocalSize

	enter	LocalSize, 0
	mov	eax, [RLEBitmapChunkSize]
	push	ds
	lds	si, [Buffer]
	add	ax, si
	mov	[ChunkEnd], ax

	les	bx, [Bitmap]
	mov	ax, [(TBitmap (es:bx)).bmWidthBytes]
	mov	[BitmapWidth], ax
	mov	cx, [(TBitmap (es:bx)).bmHeight]
	or	cx, cx
	jns	SHORT @@M
	neg	cx
@@M:
	mul	cx
	les	di, [(TBitmap (es:bx)).bmBits]
	mov	[BitmapStart], di
	add	ax, di
	mov	[BitmapEnd], ax

	cld

@@next:
	cmp	di, [BitmapEnd]
	jae	SHORT @@end		; end of destination bitmap reached

	cmp	si, [ChunkEnd]
	jae	SHORT @@outofdata	; out of data

	lodsw				; load command word
	or	al, al			; absolute mode?
	jz	SHORT @@absolute
@@coded:
	mov	cx, ax
	xor	ch, ch			; cx pixel count
	mov	al, ah
	rep	stosb			; store them
	jmp	@@next

@@absolute:
	cmp	ah, 0
	jz      SHORT @@lineend

	cmp	ah, 1
	jz	SHORT @@end

	cmp	ah, 2
	jz	SHORT @@delta

	mov	cl, ah			; cx pixel count
	xor	ch, ch
@@copy:
	rep	movsb
@@endabsolute:
	inc	si
	and	si, 0fffeh		; round up to word boundary
	jmp	@@next
@@lineend:
	mov	ax, di
	sub	ax, [BitmapStart]
	jz	SHORT @@9

	xor	dx, dx
	dec	ax
	div	[BitmapWidth]
	inc	ax			; next line
	mul	[BitmapWidth]
@@9:
	add	ax, [BitmapStart]	; ax byte at next line
	mov	di, ax
	jmp	SHORT @@fillto
@@delta:
	lodsw				; read delta values
	mov	cx, ax
	shr	ax, 8
	mul	[BitmapWidth]
	add	ax, di
@@fillto:
	mov	cx, ax
	sub	cx, di
	xor	al, al
	rep	stosb
	jmp     @@next
@@end:
	mov	dx, 1			; indicate: bitmap is ready
	jmp	SHORT @@0
@@outofdata:
	xor	dx, dx			; indicate: out of data
@@0:
	mov	ax, si
	sub	ax, [BitmapStart]
	pop	ds
	leave
	ret	ArgSize
ENDP

ENDS

END
