;	*-------+---------------------------------------*
;	|Name	| PARIN					|
;	|Version| 0.13	Comment:Debugging opti		|
;	+-------+---------------------------------------+
;	|	PC->Amiga par receiver			|
;	+-----------------------------------------------+
;	|	  Copyright (C) 1993 MACROCOSM		|
;	*-----------------------------------------------*

;0.13:fixed rpmode bug
;0.12:total remake, chksum etc. testing.. OBS! exit via double 00,ff!
;0.11:optimizing parrec(), sends chksum
;if OpenLib/CloseLib is used, set LibBits!
;Bits 0-7=Dos,Int,Gfx,Con,Icon,MathF,MathT,MathI
;Presume that all macros destroy D0-D1/A0-A1, and preserves all other regs.
;Macros that use supplied work-registers preserve ALL registers.
;When calling a macro, A5 MUST BE INIT-ADR+32768 AND A6 MUST BE $DFF002!
;Most Macros CONTAIN GLOBAL LABELS, so use local only in-between Macro calls.
;Labels to define if relevant macros are used:
;Params (#Max longs)
;CurrHdl (current filehandle storage long)
;Buf (blk.b 81,0) for conversion & input routines


Spd	=3
BSize	=49152
LibBits=%00000101
INCLUDE "CO:Symbols.S"
INCLUDE "CO:Makaron.S"

START:
	INIT
	OPENLIBS
	ALLOC #BSize+128,_Any
	move.l d0,BAddr-R(a5)
	beq.w BADERR

	OPENF d7,#FName,#_NEW		;ram:q.dms
	move.l d7,Fhdl
	beq ERR

ML:	move.l BAddr(PC),a0		;@not nec
	move.l #BSize,d0		;@not nec
	bsr ParRec			;ret #bytes read in d0
	move.l d0,d6
	beq.s DONE
	move.l fhdl(PC),d7
	WRITEF d7,BAddr(PC),d6
;	cmp.l #Bsize,d6
;	blo.s DONE			;read until EOF
	btst #6,$bfe001
	bne.s ML			;..or until LMB

DONE:	move.l fhdl(PC),d7
	CLOSEF d7

ERR:	FREE BAddr(PC),#BSize+128
BADERR:	CLOSELIBS
	EXIT
	RTS
Fhdl:	dc.l 0
;;**********************************************************************
ParRec:	;receive par data.a0=bufaddr,d0.l=bufsize.Ret #read bytes in d0.l
	MOVEM.L D1-A6,-(SP)

	MOVEM.L D0-A6,-(SP)
	move.l 4.w,a6
	jsr EDisable(a6)		;no ints
	MOVEM.L (SP)+,D0-A6

	LEA $BFE101,A5
	LEA $DFF000,A6
	move.w 2(a6),-(SP)
	move.w #$0200,$96(a6)		;low dma off $017f=bpl,blt,spr,dsk,aud dma off

	;a2-a3 free from here on

	;---init--------------
.i:	LEA $180(A6),A6			;OBS!OBS! only in this loop!
	moveq #0,d3			;const (esc code & clear-const)
	move.b #$80,d4			;const (block ctrl code)
	moveq #0,d0			;so upper 24 bits always 0!(move.w)
	moveq #0,d2			;so upper 24 bits always 0!(move.w)
	clr.l RLen			;@opti.report length 0 if EOF
	clr.l RChk
	clr.l RChk+4
;---------------------------------------
	;---start readin'--------------
	move.b d3,$200(a5)			;PRB (Parallel D0..7)=INputs!
	move.b (a5),d0			;d0=par D

.w0:	bsr WaitNew			;wait for new byte, ret in d0 
	bne.s .w0			;wait for 0
	bsr WaitNew			;read ctrl code (d0)
.RPmode:cmp.b #$fa,d0			;modechange=$c0-$ff ;@$c0!
	blo.s .w0			;if not modechange,wait some more


.CHG:	move.b d0,d1			;safetycopy for fastcheck
	addq.b #1,d1			;$ff:dest=limbo (EOF)
	beq.w .e

	addq.b #1,d1			;$fe:dest=Buf
	bne.s .nofe
	move.l BAddr(PC),a0
	move.l a0,a1			;buf lower bound
	add.l #BSize,a1			;buf upper bound
	bsr ReadPar			;fill buf	
	move.l d5,RChk			;@opti.Actual ChkSum
	move.l a1,d1
	sub.l a0,d1
	move.l d1,RLen			;@opti. Actual Read Length
	move.b RPmode(PC),d1		;RPexit with MODE read/buf full?
	bne.s .RPmode			;if mode, then skip ctrlread
	bra.s .w0			;otherwise wait for ctrl
;@???(send len), rec. chksum, (send chksum), if not same, src WILL resend
.nofe:
	addq.b #1,d1			;$fd:dest=Len
	bne.s .nofd
	lea Len(PC),a0			;"buf" lower bound
	clr.l (a0)			;make sure word & byte lens work too
	lea 4(a0),a1			;@opti a1,0reg,maxlen=4(!) OBS! BIGENDIAN!
	bsr ReadPar			;fill Len (a0=last+1)
	lea -4(a1),a0			;a0=start,a1=stop
	bsr RevBytes			;now, Len is LITTLE-ENDIAN!
	move.b RPmode(PC),d1		;RPexit with MODE read/buf full?
	bne.s .RPmode			;if mode, then skip ctrlread
	bra.s .w0			;otherwise wait for ctrl;@opti^^^!
.nofd:
	addq.b #1,d1			;$fd:dest=Chk. TRIGGERS BUFWRITE!
	bne.s .nofc
	lea Chk(PC),a0			;"buf" lower bound
	clr.l (a0)			;make sure word & byte chks work too
	clr.l 4(a0)			;@opti a1,zeroreg
	lea 8(a0),a1			;@maxlen=8(!) OBS! BIGENDIAN!
	bsr ReadPar			;fill Chk
	lea -8(a1),a0			;a0=start,a1=stop
	bsr RevBytes			;now, Chk is LITTLE-ENDIAN!OBS OFFS4.L!
;moment of truth!
	lea RLen(PC),a0
	move.l Len(PC),d1		;COMPARE XFERRED & ACTUAL LEN & CHK!
	cmp.l (a0)+,d1
	bne.s .err
	move.l Chk(PC),d1
	cmp.l (a0)+,d1
	bne.s .err
	move.l Chk+4(PC),d1
	cmp.l (a0)+,d1
	bne.s .err
;EVERYTHING'S ALL RIGHT!
	move.b RPmode(PC),d1		;RPexit with MODE read/buf full?
	bne.w .RPmode			;if mode, then skip ctrlread
	bra.w .w0			;otherwise wait for ctrl;@opti^^^!
.err:	

.nofc:
	;$fb,$fa here!
.wm1:	move.w #$fff,$dff180		;indicate error if undefd code used
	move.w #$000,$dff180
	btst #6,$bfe001			;LMB
	bne.s .wm1
.h1:	bra.s .h1			;halt
	;---done--------------
;---------------------------------------
.e:
	move.l Rlen(PC),d0

	LEA $DFF000,A6		;***a6 restored!
	move.w (SP)+,d1
	bset #15,d1
	move.w #$7fff,$96(a6)
	move.w d1,$96(a6)

	MOVEM.L D0-A6,-(SP)
	move.l 4.w,a6
	jsr EEnable(a6)		;ints on
	MOVEM.L (SP)+,D0-A6

	MOVEM.L (SP)+,D1-A6
	RTS

;;**************************************
RevBytes:		;rev. bytes until ptrs meet.a0=start,a1=stop. uses d1
.l:	move.b (a0),d1
	move.b -(a1),(a0)+
	move.b d1,(a1)
	cmp.l a1,a0
	blt.s .l
	RTS
;;**************************************
ReadPar:				;read par to [a0..a1] until modechange
	clr.b RPmode			;@opti
	moveq #0,d5			;CHKSUM:0
	;---dynamic readloop--------------
.l:	move.b d0,d2			;save last databyte if 0
	bsr WaitNew			;read byte
	beq.s .ctrl			;0=ctrl escapecode!

.data:	move.b d0,(a0)+			;1-$ff=data!
	add.l d0,d5			;add to chksum!
.cont:	cmp.l a1,a0
	bmi.s .l			;buffull?
	bra.s .e			;then stop!

	;---ctrl codes--------------
.ctrl:					;DON't save d0=0 as last databyte
	bsr WaitNew			;read ctrl code (d0)
	bmi.s .spec			;$80-$ff=special

	move.w d0,(a6)			;@temp. change color
	move.w d0,d7
	subq.w #1,d7			;compens. for dbra
.rpt:	move.b d2,(a0)+			;last DATA byte
	add.l d2,d5			;add to chksum!;@opti'd
	dbra d7,.rpt
.cont2:	cmp.l a1,a0
	bmi.s .l			;buffull?
	bra.s .e			;then stop!

.spec:	cmp.b d4,d0			;d4=$80=data $00(temp)
	bne.s .MODE
	move.b d3,(a0)+			;d3=const $00
;	add.l d0,d5			;add to chksum!;@opti'd
.cont3:	cmp.l a1,a0
	bmi.s .l			;buffull?
	bra.w .e			;then stop!
	;---switch datadest!--------------
.e:
	bra.s .x			;buffer filled to the rim,exit,no mode
	;@beq above.otherwise too small buffer!!

.wm2:	move.w #$fff,$dff180		;indicate TOO SMALL BUFFER!
	move.w #$000,$dff180
	btst #10,$dff016		;RMB
	bne.s .wm2
.h2:	bra.s .h2			;halt

.MODE:	move.b #1,RPmode		;@opti
.x:	move.b d0,RPd0
	RTS				;d0=mode ($fa-$ff),d5=chk,a0=last+1
;---------------------------------------
RPmode:	dc.b 0
RPd0:	dc.b 0
;;**************************************
WaitNew:	;Wait for new parbyte. d0=old parbyte.ret:d0=new,tested!
	move.b d0,d1
.wdiff:	move.b (a5),d0			;read par D
	cmp.b d0,d1
	beq.s .wdiff			;wait until different

;.diff:	move.b (a5),d2			;read par D
;	cmp.b d0,d1
;	beq.s .wdiff			;wait until different

					;REPEAT UNTIL BEEN SAME FOR A WHILE
	REPT Spd			;@rplc with dynamic wait?or param?
	cmp.b (a5),d0
	bne.s .wdiff			;nope-changed too fast, =NOISE,re-wait
	ENDR
	;---real byte read!--------------
;	and.w #$00ff,d0
;	move.w d0,$dff180		;@just test!
	tst.b d0
	RTS
;;**********************************************************************
BAddr:	dc.l 0
Len:	dc.l 0
	blk.b 128,0		;extra so no check-per-byte
Chk:	dc.l 0,0		;upto 8 bytes chksum!
	blk.b 128,0		;extra so no check-per-byte
;---------------------------------------
RLen:	dc.l 0			;don't move vv!
RChk:	dc.l 0,0		;upto 8 bytes chksum!
;---------------------------------------

FName:	dc.b "RAM:Q.dms",0
