
;This is the assembler source for the 2View function ReadIntoBitmap()
;
;Parameters:
;  a0.l - The destination bitmap's PLANEPTR structure
;  a1.l - The source buffer
;  a2.l - The pointer to the IFFParse structure
;
;  d0.l - The length of the source buffer
;  d1.l - The number of bytes per bitmap row
;  d2.w - The number of rows in the bitmap
;  d3.b - The number of bitplanes in the bitmap
;  d4.b - 0 if the source isn't compressed, 1 if it is
;  d5.b - 1 if there's masking, 0 if not
;
;Returns:
;  Nothing
;
;Bugs:
;  Doesn't check ReadChunkBytes() return value


	    xref _LVOCopyMem
	    xref _LVOReadChunkBytes
	    xref _DOSBase
	    xref _IFFParseBase
	    xref _SysBase
	    xref _trashBuf

	    xref _storage

	    xdef _ReadIntoBitmapAsm

	    SECTION "program",code

_ReadIntoBitmapAsm:
	    nop
	    nop
	    nop

	    move.l   4(a7),planePtr
	    move.l   8(a7),srcStart   ;Store start of buffer
	    move.l   12(a7),iff        ;Store the IFFParse struct pointer

	    move.l   16(a7),(sourceBufSize)
	    move.l   20(a7),bytesInRow
	    move.l   24(a7),d0         ;Masking
	    move.w   d0,Height
	    move.l   28(a7),d0
	    lsl.b    #2,d0
	    move.b   d0,Depth
	    move.l   32(a7),d0
	    move.b   d0,comp
	    move.l   36(a7),d0

	    movem.l  a2/a4-a6/d2-d4/d7,-(a7)

	    movea.l  srcStart,a2       ;Create the current source buf ptr
	    adda.l   (sourceBufSize),a2
	    movea.l  a2,a5	       ;Create the end-of-source ptr

	    moveq.l  #0,d2
	    clr.l    byteOffset
	    move.b   Depth,d3
	    tst.b    d0 	       ;Check masking
	    beq      storeMask
	    subq.b   #4,d3	       ;Store the mask plane number

storeMask:  move.b   d3,maskPlaneNum

	    clr.w    curRow	       ;Clear the current row variable

	    tst.b    comp	       ;Test the compression flag
	    beq      uncompressed      ;If 0 no compression

nextRow:    moveq.l  #0,d4	       ;Start of bitplane loop

nextPlane:
	    cmp.b    maskPlaneNum,d4   ;If it isn't the mask plane...
	    bne      getBitplane       ;Get the destination bitmap pointer
	    movea.l  _trashBuf,a4      ;Else, get a pointer to a bit bucket
	    bra      getBytes

getBitplane:
	    movea.l  planePtr,a0
	    movea.l  0(a0,d4),a4
	    adda.l   byteOffset,a4
	    move.l   a4,d7
	    add.l    bytesInRow,d7     ;Create the end-of-row pointer

getBytes:
	    cmpa.l   a2,a5
	    bne      checkCompType

	    bsr      refillSrcBuffer
	    bmi      error

checkCompType:
	    moveq.l  #0,d2
	    move.b   (a2)+,d2          ;Get the current byte
	    cmp.b    #128,d2
	    beq      getBytes	       ;Check for a NOP
	    cmp.b    #0,d2	       ;Check to see if the byte specifies
	    blt      fillMem	       ;a fill...

	    addq.b   #1,d2	       ;We need to copy d2+1 bytes
	    move.l   a5,d3	       ;Check to see if the source buffer
	    sub.l    a2,d3	       ;contains all the bytes we need to
	    cmp.l    d2,d3	       ;copy
	    bpl      copyAll	       ;If so, copy them

	    ;Otherwise, copy the number of bytes available
	    movea.l  a2,a0
	    movea.l  a4,a1
	    move.l   d3,d0
	    movea.l  _SysBase,a6
	    jsr      _LVOCopyMem(a6)

	    ;Add the number of bytes copied to the destination pointer
	    adda.l   d3,a4

	    sub.b    d3,d2	       ;Determine how many bytes are left
				       ;to copy

	    bsr      refillSrcBuffer
	    bmi      error

;Copy a given number of bytes from the source to destination
copyAll:
	    movea.l  a2,a0	       ;Setup for CopyMem()
	    movea.l  a4,a1
	    move.l   d2,d0
	    movea.l  _SysBase,a6
	    jsr      _LVOCopyMem(a6)

	    adda.l   d2,a4	       ;Update destination pointer
	    adda.l   d2,a2	       ;Update source pointer

	    bra      nextCompByte

fillMem:    neg.b    d2
	    cmpa.l   a5,a2	    ;See if source buffer is empty
	    bne      getFillByte

	    bsr      refillSrcBuffer
	    bmi      error

getFillByte:
	    move.b   (a2)+,d0       ;Get the fill byte

doFill:
	    move.b   d0,(a4)+       ;Do the fill
	    dbra     d2,doFill

nextCompByte:
	    cmp.l    a4,d7	    ;Check to see if we've written the
	    bne      getBytes	    ;entire row
	    bra      checkLoop	    ;If so, get the next row

checkLoop:
	    ;Check to see if we're done with all the planes in this row
	    addq.b   #4,d4	    ;Increment the plane counter
	    cmp.b    Depth,d4	    ;Compare to the # of planes
	    bne      nextPlane	    ;If not equal, get next plane in row

setupNextRow:
	    move.l   byteOffset,d0  ;Update byte-offset value
	    add.l    bytesInRow,d0
	    move.l   d0,byteOffset

	    addq     #1,curRow	    ;Increment the row counter
	    move.w   curRow,d0	    ;Check to see if we've run through
	    cmp.w    Height,d0	    ;all the rows
	    bne      nextRow	   ;If not, get the next row
	    bra      done


;Transfer a row (uncompressed)
uncompressed:
nextURow:   moveq.l  #0,d4	       ;Start of bitplane loop

nextUPlane:
	    cmp.b    maskPlaneNum,d4   ;If it isn't the mask plane...
	    bne      getUBitplane      ;Get the destination bitmap pointer
	    adda.l   bytesInRow,a2     ;Else, skip past the mask plane
	    bra      setupNextRow      ;And go on to the next row

getUBitplane:
	    movea.l  planePtr,a0
	    movea.l  0(a0,d4),a4
	    adda.l   byteOffset,a4
	    move.l   a4,d7
	    add.l    bytesInRow,d7     ;Create the end-of-row pointer

getUBytes:
	    cmpa.l   a2,a5
	    bge      moveBytes

	    bsr      refillSrcBuffer
	    bmi      error

moveBytes:
	    move.l   a5,d2	    ;Check to see if all the bytes we need
	    sub.l    a2,d2	    ;are in the source buffer
	    cmp.l    bytesInRow,d2
	    bge      noCompXfer

	    move.l   d2,d0	    ;Setup registers
	    movea.l  a2,a0
	    movea.l  a4,a1
	    movea.l  _SysBase,a6
	    jsr      _LVOCopyMem(a6)

	    adda.l   d2,a4	    ;Update destination pointer
	    move.l   bytesInRow,d0
	    sub.l    d2,d0
	    move.l   d0,d2

	    bsr      refillSrcBuffer
	    bmi      error
	    bra      xfer_nc	    ;Transfer the rest

noCompXfer:
	    ;Setup to transfer all the bytes in the row
	    move.l   bytesInRow,d2  ;row

xfer_nc:    movea.l  a2,a0	    ;Transfer the given number of bytes
	    movea.l  a4,a1
	    move.l   d2,d0
	    movea.l  _SysBase,a6
	    jsr      _LVOCopyMem(a6)

	    adda.l   d2,a2	    ;Update the src pointer

	    ;Check to see if we're done with all the planes in this row
	    addq.b   #4,d4	    ;Increment the plane counter
	    cmp.b    Depth,d4	    ;Compare to the # of planes
	    bne      nextUPlane     ;If not equal, get next plane in row

setupNextURow:
	    move.l   byteOffset,d0  ;Update byte-offset value
	    add.l    bytesInRow,d0
	    move.l   d0,byteOffset

	    addq     #1,curRow	    ;Increment the row counter
	    move.w   curRow,d0	    ;Check to see if we've run through
	    cmp.w    Height,d0	    ;all the rows
	    bne      nextURow	    ;If not, get the next row

done:
	    moveq.l  #0,d0
	    bra      return

error:
	    moveq.l  #0,d0

return:
	    ;Restore registers
	    movem.l  (a7)+,a2/a4-a6/d2-d4/d7

	    rts 		    ;And we're done


refillSrcBuffer:
	    movea.l  iff,a0
	    movea.l  srcStart,a1
	    movea.l  a1,a2
	    move.l   sourceBufSize,d0
	    movea.l  _IFFParseBase,a6
	    jsr      _LVOReadChunkBytes(a6)
	    movea.l  a2,a5
	    adda.l   d0,a5
	    tst.l    d0
	    rts

	    SECTION  "data",data

	    CNOP     0,4

planePtr:   dc.l     0
srcStart:   dc.l     0
bytesInRow: dc.l     0
byteOffset: dc.l     0
iff:	    dc.l     0
sourceBufSize:
	    dc.l     0

Height:     dc.l     0
curRow:     dc.w     0

plane:	    dc.b     0
maskPlaneNum:
	    dc.b     0
Depth:	    dc.b     0

comp:	    dc.b     0

	    END


