
      INCLUDE "EXEC/TYPES.I"
      INCLUDE "GRAPHICS/GFXBASE.I"
      INCLUDE "GRAPHICS/GFX.I"
      INCLUDE "GRAPHICS/VIEW.I"
      INCLUDE "GRAPHICS/RASTPORT.I"


    XREF     _AbsExecBase             ;library references
    XREF     _LVOExit
	XREF	 _LVOFreeMem
    XREF     _LVOAllocMem
	XREF	 _LVODelay
    XREF     _LVOOpen
	XREF	 _LVORead
    XREF     _LVOClose
    
    XREF     dosbase                  ;first defined in pix.a                       
       
    XDEF     readfile                 ;called by pix.a
  
 CSECT text,code

readfile:                  ;reads iff picture file
    move.l  d0,filename
    move.l  d1,BMscene
    move.l  d2,colourlist
	jsr	    openfile       
    tst.l   d0             ;exits if file is invalid
    bne     finished
more:
	move.l	bytesread,d0   ;reads all chunks
	cmp.l	totalbytes,d0
	bge	    closefile
	jsr	    readchunk
    bra     more
closefile:
    move.l fHandle,d1
    move.l dosbase,a6
    jsr    _LVOClose(a6)
finished:
	rts

wait:                      ;Delay routine used in debugging
    move.l  dosbase,a6
    move.l  #5,d1
    jsr     _LVODelay(a6)
    rts

openfile:                    ;opens file
	move.l	#1005,d2
	move.l	filename,d1
    move.l  dosbase,a6
	jsr	    _LVOOpen(a6)
	movem.l	d0,fHandle
	tst.l	fHandle
	beq     finished
	move.l	#8,d3           ;reads first 8 bytes
	move.l	#mybuf,d2
	move.l	fHandle,d1
	jsr	    _LVORead(a6)
	movem.l	d0,rLen
	move.l	d0,bytesread     ;stores file length
	move.l  filelength,d0
    move.l  d0,totalbytes
	move.l	#4,d3
	move.l	#mybuf,d2
	move.l	fHandle,d1
    move.l  dosbase,a6
	jsr	    _LVORead(a6)
	add.l	d0,bytesread
	move.l	#mybuf,a0
	move.l	#ilbm,a1          ;checks for ILBM or ACBM file
	jsr	    strcmp
	tst.l	d0
	bne	    acbmtype
	rts
acbmtype:
	move.l	#mybuf,a0
	move.l	#acbm,a1
	jsr	strcmp
	rts

readchunk:                     ;reads chunk header
	move.l	#8,d3
	move.l	#mybuf,d2
	move.l	fHandle,d1
    move.l  dosbase,a6
	jsr	    _LVORead(a6)        ;adds length to total
    move.l  mybuf+4,d1
	move.l	d1,icLen
	add.l	#8,bytesread
	add.l	d1,bytesread
	move.l	#mybuf,a1           ;is it a BMHD chunk?
	move.l	#bmhd,a0
	jsr	    strcmp
	tst.l	d0
	bne	    notbmhd
	jsr	    readbitmapheader
	rts
notbmhd:                        ;is it a CMAP chunk?
	move.l	#mybuf,a1
	move.l	#cmap,a0
	jsr	    strcmp
	tst.l	d0
	bne	    notcmap
	jsr	    readcmap
	rts
notcmap:                          ;is it a BODY chunk?
	move.l	#mybuf,a1
	move.l	#body,a0
	jsr	    strcmp
	tst.l	d0
	bne	    notbody
	jsr	    readbody
	rts
notbody:                          ;is it an ABIT chunk?
	move.l	#mybuf,a1
	move.l	#abit,a0
	jsr	    strcmp
	tst.l	d0
	bne	    notabit
	jsr	    readabit
	clr.l	d0
	rts                
notabit:                          ;none of these,read and ignore.
	move.l	icLen,d3              ;extra chunk types could be 
	move.l	#mybuf,d2             ;processed here
	move.l	fHandle,d1
    move.l  dosbase,a6
	jsr	    _LVORead(a6)
	rts

readbitmapheader:                ;process BMHD info
	move.l	icLen,d3
	move.l	#mybuf,d2
	move.l	fHandle,d1
    move.l  dosbase,a6
	jsr	_LVORead(a6)             ;read rest of chunk
	clr.l	d0
	move.w	mybuf,d1
	move.w	d1,scrWidth          ;store screen width in pixels
	clr.l	d0
	move.w	mybuf+2,d1
	move.w	d1,scrHeight         ;store screen height
	clr.w	d0
	move.b	mybuf+8,d0
	move.w	d0,iDepth            ;store number of planes
	move.b	mybuf+10,iCompr      ;store compression flag
	clr.l	d0
	move.w	mybuf+16,d1
	move.w	d1,iWidth            ;store picture width in pixels
	clr.l	d0
	move.w	mybuf+18,d1          ;store picture height
	move.w	d1,iHeight
	move.w	iWidth,d0 
	ext.l	d0
	asr.l	#3,d0
	move.w	d0,iRowBytes         ;calculate bytes per row for picture
	move.w	scrWidth,d0
	ext.l	d0
	asr.l	#3,d0
	move.w	d0,scrRowBytes       ;calculate bytes per row for screen
	move.w	iDepth,d0            ;calculate number of colours
	ext.l	d0
    move.w  #1,d1
    asl.w   d0,d1
    move.w  d1,nColors
	rts

readcmap:                        ;CMAP info into colourlist
	move.l	icLen,d3
	move.l	#mybuf,d2 
	move.l  fHandle,d1
    move.l  dosbase,a6
	jsr	    _LVORead(a6)          ;read data
	move.w	nColors,d4
    andi.l	#255,d4
    sub.l   #1,d4
    move.l   colourlist,a1
    move.l   #mybuf,a0
nextcolour:                       ;for each colour
	move.b	(a0)+,d0              ;first byte -red componant R0
    ext.w    d0
    andi.w   #255,d0
	move.w	d0,red
	move.b	(a0)+,d0              ;second byte -green componant G0
    ext.w    d0
    andi.w   #255,d0             
    move.w  d0,gre
	move.b	(a0)+,d0              ;third byte -blue componant B0
    ext.w    d0
    andi.w    #255,d0
	move.w	d0,blu
	asr.w	#4,d0                 ;B0 / 16 to give 000B
	move.w	gre,d1                ;G0 to 00G0
	add.w	d1,d0                 ;add green to blue 00GB
	move.w	red,d1                ;red to 00R0
	asl.w	#4,d1                 ;00R0 x 16 to give 0R00
	add.w	d1,d0                 ;add red to blue/green 0RGB
	move.w	d0,(a1)+              ;store result in colourlist
	dbra	d4,nextcolour
    rts

readabit:                         ;read picture data from ACBM file
	move.w	iDepth,d6
	ext.l	d6
    clr.l   d5
    move.l  BMscene,a0
    lea     bm_Planes(a0),a3      
nextplane:                       ;for each bitplane
	cmp.l	d6,d5
	bge	    finished
	move.w	iHeight,d1
	move.w	scrRowBytes,d3        ;calculate number of bytes
	mulu    d1,d3
	move.l	(a3)+,d2
	move.l	fHandle,d1
    move.l  dosbase,a6
	jsr	    _LVORead(a6)           ;read the data
	add.l	#1,d5
	bra	    nextplane

readbody:                          ;read body of ILBM file
	move.l	#65539,d1
	move.l	icLen,d0
    move.l  _AbsExecBase,a6
	jsr	_LVOAllocMem(a6)           ;allocate buffer for all picture data
	movem.l	d0,tempbuffer
	move.l	icLen,d3
	move.l	tempbuffer,d2
	move.l	fHandle,d1
    move.l  dosbase,a6
	jsr	_LVORead(a6)                ;read all data
	move.b	iCompr,d0               ;is data compressed?
	tst.l	d0
	bne	   fibcomp                  
	jsr	   plainread                ;read interleaved planes
    bra     freemem
fibcomp:
	jsr	    decode                  ;decode interleaved and compressed data 
freemem:
	move.l	icLen,d0                ;free the data buffer
	move.l	tempbuffer,a1
    move.l  _AbsExecBase,a6
	jsr	    _LVOFreeMem(a6)
    rts

decode:
	move.l	tempbuffer,a3           ;beginning of data buffer
	clr.w   d5                      ;rows
nextrow3:                           ;for each row
    move.l   BMscene,a0             ;address of start of pbitplane
    lea     bm_Planes(a0),a5
	cmp.w	iHeight,d5              ;check for last row
	bge	    finished
    clr.w   d6                      ;planes
nextplane3:                         ;for each plane
    move.l  (a5),a2
	cmp.w	iDepth,d6
	bge	     endrow3                ;check for last plane
	move.w	scrRowBytes,d4          ;calculate offset from row start
	mulu    d5,d4
    add.l   d4,a2
	move.w	iRowBytes,d0            ;store bytes per row
	ext.l	d0
    clr.l   d7                      ;byte count 
nextcol3:                           ;for each column
    cmp.l   d0,d7                   ;check for end of plane
    bge     endplane3
    move.b  (a3)+,d3                ;read next byte
    move.b   d3,d2                  ;store its value 'x'
    and.l    #255,d2
    move.l   d2,d4
    btst     #7,d2                  ;is x more than 128?
    bne      code128
nextbytesdiff:                      ;the next x bytes differ from each other
    move.b    (a3)+,(a2)+           ;read next x bytes on to bit plane
    dbra      d4,nextbytesdiff
    add.l     #1,d7
    add.l     d2,d7                 ;update byte count
    bra       nextcol3              ;process next column
code128:                            ;the next x bytes are the same 
    move.l     #256,d4
    sub.l     d2,d4 
    move.b   (a3)+,d1               ;read value of next byte 'y'
nextbytesame:
    move.b    d1,(a2)+              ;copy 'y' to next x bytes on bitplane
    dbra      d4,nextbytesame
    add.l     #257,d7
    sub.l     d2,d7                 ;update byte count
    bra       nextcol3              ;process next column
endplane3:
    add.l    #4,a5                  ;address of start of next plane
	add.w	#1,d6                   ;add to plane count
	bra	    nextplane3
endrow3:
	add.w	#1,d5                   ;add to row count
	bra	    nextrow3
    rts

plainread:                          ;read uncompressed picture data
	move.l	tempbuffer,a3           ;beginning of data buffer
	clr.w   d5                      ;rows
nextrow:                            ;for each row 
    move.l   BMscene,a0
    lea     bm_Planes(a0),a5        ;address of start of plane       
	cmp.w	iHeight,d5              ;check for last row
	bge	    finished
    clr.w   d6                      ;planes
nextplane2:                         ;for each plane
    move.l  (a5),a2
	cmp.w	iDepth,d6
	bge	     endrow                 ;check for end of plane
	move.w	scrRowBytes,d4          ;calculate offset from first row
	mulu    d5,d4
    add.l   d4,a2                   ;add to bit plane address
	move.w	iRowBytes,d0
	ext.l	d0
    sub.l   #1,d0
nextcol:                            ;for each column
	move.b  (a3)+,(a2)+             ;copy from buffer to bitplane
	dbra     d0,nextcol
endplane:
    add.l    #4,a5                  ;address of start of next plane
	add.w	#1,d6                   ;add to number of planes
	bra	    nextplane2
endrow                          
	add.w	#1,d5                   ;add to number of rows
	bra	    nextrow
     rts

strcmp:                 ;compare two characte strings
	move.b	(a0)+,d0
    tst.b   d0
    beq     eq
	cmp.b	(a1)+,d0
	bne	    noteq
	bra     strcmp
eq:  
    clr.l  d0
noteq:
    rts

	CSECT DATA	
filename:
   ds.l  1
BMscene:
   ds.l  1
colourlist:
   ds.l  1
bytesread:	
   dc.l  0
totalbytes:	
   DS.l  1
icLen:	
   DS.l  1
iHeight:	
   DS.W	1
iWidth:	
   DS.W	1
scrWidth:	
   DS.W	1
scrHeight:	
   DS.W	1
iDepth:	
   DS.W	1
nColors:	
   DS.W	1
iRowBytes:	
   DS.W	1
scrRowBytes:	
   DS.W	1
iCompr:	
   DS.B	1
   ds.w 0
mybuf:	
   DS.B	4
filelength:
   ds.b 116
rLen:	
   DS.l 1
tempbuffer:	
   DS.l 1
fHandle:	
   DS.l  1
red:	
   DS.W	1
gre:	
   DS.W	1
blu:	
   DS.W	1

abit:	
    DC.B	"ABIT",0
	DS.W	0
acbm:
    dc.b    "ACBM",0
    ds.w    0
body:
    dc.b    "BODY",0
    ds.w    0
cmap:
    dc.b    "CMAP",0
    ds.w    0
bmhd:
    dc.b    "BMHD",0
    ds.w    0
ilbm:
    dc.b    "ILBM",0
	ds.w	0
	END 
