;-----------------------------------------------------------------------------
;File name:	TST_PACK.S			Revision date:	1993.08.05
;Creator:	Ulf Ronald Andersson		Creation date:	1993.08.05
;(c)1993 by:	Ulf Ronald Andersson		All rights reserved
;-----------------------------------------------------------------------------
;
	output	.APP
;
	include	URAn_APP.S
;
;-----------------------------------------------------------------------------
		data
;
acc_name:	dc.b	'  Test Packer',0
		even
;
;-----------------------------------------------------------------------------
		bss
;
mystack_data:	ds.l	$100
mystack:	ds.w	1
message:	ds.b	16
intin:		ds.w	30
intout:		ds.w	45
ptsin:		ds.w	30
ptsout:		ds.w	12
;
;-----------------------------------------------------------------------------
;		Constants
;
str_bits	=	5
str_size	=	1<<str_bits
max_bits	=	10
max_size	=	1<<max_bits
buf_size	=	max_size
;
;-----------------------------------------------------------------------------
		SECTION TEXT
;
init_app:
	tst	d7
	bmi.s	.TOS_init
	nop
.TOS_init:
	rts
;
;
exec_app:
	tst	d7
	bpl.s	GEM_app
TOS_app:
	clr.l	d0
	rts
;
;
GEM_app:
	clr.l	d0
	rts
;
;
;-----------------------------------------------------------------------------
;
tst_init:
	movem.l	d3-d7/a2-a5,-(sp)
	move.l	#tvar_end-tvar_base-1,d0
	move.l	d0,d1
	swap	d1
	lea	tvar_base,a0
.clear_var_loop:
	clr.b	(a0)+
	dbra	d0,.clear_var_loop
	dbra	d1,.clear_var_loop
;
	movem.l	(sp)+,d3-d7/a2-a5
	rts
;
;-----------------------------------------------------------------------------
;
up_raw_read:
	jmp	$C0DEC0DE
;
;-----------------------------------------------------------------------------
;
pk_raw_write:
	jmp	$C0DEC0DE
;
;-----------------------------------------------------------------------------
;
up_init:
	clr	up_buff_ct
	clr	up_bits
	clr	up_bits_ct
	move	#2,up_refbits
	move	#4,up_refsize
	clr	up_ring_ix
	clr.l	up_ring_ct
	clr	up_ring_out_ct
	clr	up_delta
	rts
;
;-----------------------------------------------------------------------------
;
pk_init:
	clr	pk_buff_ct
	clr	pk_bits
	clr	pk_bits_ct
	move	#2,pk_refbits
	move	#4,pk_refsize
	clr	pk_ring_ix
	clr.l	pk_ring_ct
	clr	pk_string_ct
	clr	pk_delta
	rts
;
;-----------------------------------------------------------------------------
;
up_read:		;d0=byte count, a0->dest.buffer
	move.l	a0,up_read_p
	move.l	d0,up_read_ct
	clr.l	up_read_err_f
	clr.l	up_read_retv
.up_read_loop:
	move.l	up_read_ct,d0
	beq	.exit
	clr.l	d1
	move	#str_size,d1
	move	pk_string_ct,d1
	beq.s	.get_data
	cmp.l	d0,d1
	beq.s	.all_out
	bgt.s	.part_out
	bsr.s	.all_out
.get_data:
	bsr	up_decode
	tst.l	d0
	bpl.s	.up_read_loop
	move.l	d0,up_read_err_f
	bra.s	.exit
;
.part_out:
	move.l	d0,d1	
.all_out:				;d1 = byte count of output data
	move	d3,-(sp)
	move	up_delta,d3
	move.l	up_read_p,a1	;a1 = get pointer to new data dest
	add.l	d1,up_read_p	;set pointer to new data end
	add.l	d1,up_read_retv	;increase accumulated data size
	sub.l	d1,up_read_ct	;decrease request size by data size
	sub	d1,up_ring_out_ct	;decrease buffered size by data size
	move	up_ring_ix,d0
	sub	d1,d0			;d0 = ring index to new data start
	bge.s	.one_group		;go move in one group if index positive
;   Here negative index means we have to move data in two groups unless -d0 = d1
	move	d0,d2
	add	#max_size,d0		;d0 = ring index to new data start
	neg	d2
;   So we move two groups using d0.d2, followed by 0.d1-d2 unless d1=d2
	sub	d2,d1		;NB: if d1 now is zero, we later skip a loop
	lea	up_ring,a0
	add	d0,a0
	subq	#1,d2		;prep d2 for dbra
.out_loop_1:
	move.b	(a0)+,(a1)+
	and	up_delta_f,d3
	eor.b	d3,-(a1)
	move.b	(a1)+,d3
	dbra	d2,.out_loop_1
	clr	d0
	tst	d1
	ble.s	.exit
.one_group:
	lea	up_ring,a0
	add	d0,a0
	subq	#1,d1		;prep d1 for dbra
.out_loop_2:
	move.b	(a0)+,(a1)+
	and	up_delta_f,d3
	eor.b	d3,-(a1)
	move.b	(a1)+,d3
	dbra	d1,.out_loop_2
	move	d3,up_delta
	move	(sp)+,d3
.exit:
	move.l	up_read_err_f,d0
	bmi.s	.exit_rts
	move.l	up_read_retv,d0
.exit_rts:
	rts
;
;-----------------------------------------------------------------------------
;
pk_write:
	move.l	a0,pk_write_p
	move.l	d0,pk_write_ct
	clr.l	pk_write_err_f
	clr.l	pk_write_retv
.pk_write_loop:
	move.l	pk_write_ct,d0
	beq	.exit
	clr.l	d1
	move	pk_string_ct,d1
	beq.s	.get_data
	cmp.l	d0,d1
	beq.s	.all_out
	bgt.s	.part_out
	bsr.s	.all_out
.get_data:
	bsr	pk_encode
	tst.l	d0
	bpl.s	.pk_write_loop
	move.l	d0,pk_write_err_f
	bra.s	.exit
;
.part_out:
	move.l	d0,d1	
.all_out:				;d1 = byte count of output data
	move	d3,-(sp)
	move	pk_delta,d3
	move.l	pk_write_p,a1		;a1 = get pointer to new data dest
	add.l	d1,pk_write_p		;set pointer to new data end
	add.l	d1,pk_write_retv	;increase accumulated data size
	sub.l	d1,pk_write_ct		;decrease request size by data size
	sub	d1,pk_string_ct		;decrease buffered size by data size
	move	pk_ring_ix,d0
	sub	d1,d0			;d0 = ring index to new data start
	bge.s	.one_group		;go move in one group if index positive
;   Here negative index means we have to move data in two groups unless -d0 = d1
	move	d0,d2
	add	#max_size,d0		;d0 = ring index to new data start
	neg	d2
;   So we move two groups using d0.d2, followed by 0.d1-d2 unless d1=d2
	sub	d2,d1		;NB: if d1 now is zero, we later skip a loop
	lea	pk_ring,a0
	add	d0,a0
	subq	#1,d2		;prep d2 for dbra
.out_loop_1:
	move.b	(a0)+,(a1)+
	and	pk_delta_f,d3
	eor.b	d3,-(a1)
	move.b	(a1)+,d3
	dbra	d2,.out_loop_1
	clr	d0
	tst	d1
	ble.s	.exit
.one_group:
	lea	pk_ring,a0
	add	d0,a0
	subq	#1,d1		;prep d1 for dbra
.out_loop_2:
	move.b	(a0)+,(a1)+
	and	pk_delta_f,d3
	eor.b	d3,-(a1)
	move.b	(a1)+,d3
	dbra	d1,.out_loop_2
	move	d3,pk_delta
	move	(sp)+,d3
.exit:
	move.l	pk_write_err_f,d0
	bmi.s	.exit_rts
	move.l	pk_write_retv,d0
.exit_rts:
	rts
;
;-----------------------------------------------------------------------------
;
up_decode:
	movem.l	d3-d7/a5,-(sp)
	clr.l	d7
	move	up_bits,d7
	move	up_bits_ct,d6
	move	up_ring_ix,d5	;d5 =  circle index  = dest. start index
	lea	up_ring,a5	;a5 -> circle buffer
	move.l	up_ring_ct,d0
	cmp.l	up_refsize,d0
	bls.s	.decode_loop
	addq	#1,up_refbits
	lsl	up_refsize+2
	cmp.l	#max_size,d0
	blo.s	.decode_loop
	st	up_refsize	;avoid rescaling when circle closed
.decode_loop:
	subq	#str_bits+1,d6
	bge.s	.got_code
	jsr	up_raw_read_byte
	tst.l	d0
	bmi	.exit
	lsl	#8,d7
	move.b	d0,d7
	addq	#8,d6
.got_code:
	ror.l	d6,d7
	clr.l	d3
	move	d7,d3
	clr	d7
	rol.l	d6,d7
	bclr	#5,d3		;d3=block length,  testing codeflag
	bne.s	.got_code_block
	tst	d3
	bne.s	.got_text_block
;;;patch special codes here
	bra.s	.decode_loop
;
.got_text_block:
	add.l	d3,up_ring_ct
	add	d3,up_ring_out_ct
	subq	#1,d3
.text_loop:
	subq	#8,d6
	bge.s	.got_text_byte
	jsr	up_raw_read_byte
	tst.l	d0
	bmi	.exit
	lsl	#8,d7
	move.b	d0,d7
	addq	#8,d6
.got_text_byte:
	ror.l	d6,d7
	move.b	d7,(a5,d5)
	clr	d7
	rol.l	d6,d7
	addq	#1,d5
	cmp	#max_size,d5
	blo.s	.text_ix_ok
	clr	d5
.text_ix_ok:
	dbra	d3,.text_loop
	clr.l	d0
	bra.s	.exit
;
.got_code_block:
	cmp	up_refbits,d6
	bge.s	.got_code_pos
.get_code_pos:
	jsr	up_raw_read_byte
	tst.l	d0
	bmi.s	.exit
	lsl.l	#8,d7
	move.b	d0,d7
	addq	#8,d6
	cmp	up_refbits,d6
	blo.s	.get_code_pos
.got_code_pos:
	sub	up_refbits,d6
	ror.l	d6,d7
	move	d7,d4		;d4 = block offset from circle index or start
	clr	d7
	rol.l	d6,d7
;
	cmp.l	#max_size,up_ring_ct
	blo.s	.keep_pos_d4
	add	d5,d4
	cmp	#max_size,d4
	blo.s	.keep_pos_d4
	sub	#max_size,d4
.keep_pos_d4:
;
;   Here  d3 = block length  with  d4 = block pos  and  d5 = circle index
;
	add.l	d3,up_ring_ct
	add	d3,up_ring_out_ct
	subq	#1,d3
.code_loop:
	move.b	(a5,d4),(a5,d5)
	addq	#1,d4
	cmp	#max_size,d4
	blo.s	.block_ix_ok
	clr	d4
.block_ix_ok:
	addq	#1,d5
	cmp	#max_size,d5
	blo.s	.code_ix_ok
	clr	d5
.code_ix_ok:
	dbra	d0,.code_loop
;
.exit:
	move	d7,up_bits
	move	d6,up_bits_ct
	move	d5,up_ring_ix
	movem.l	(sp)+,d3-d7/a5
	rts
;
;-----------------------------------------------------------------------------
;
pk_encode:
	rts
;
;-----------------------------------------------------------------------------
;
up_raw_read_byte:
	tst	up_buff_ct
	bne.s	.got_buff
	lea	up_buff,a0
	move.l	#buf_size,d0
	jsr	up_raw_read
	tst.l	d0
	bmi.s	.error_1
	beq.s	.clr_buff
	cmp.l	#$100,d0
	bls.s	.set_buff
	moveq	#-64,d0		;range error
.error_1:
	rts
;
.clr_buff:
	move	#buf_size/4-1,d0
	lea	up_buff,a0
.clr_loop:
	clr.l	(a0)+
	dbra	d0,.clr_loop
	move	#buf_size,d0
.set_buff:
	move	d0,up_buff_ct
	clr	up_buff_ix
.got_buff:
	lea	up_buff,a0
	add	up_buff_ix,a0
	addq	#1,up_buff_ix
	subq	#1,up_buff_ct
	move.b	(a0),d0
	rts
;
;-----------------------------------------------------------------------------
	SECTION	BSS
;
tvar_base:
;
up_read_p:	ds.l	1
up_read_ct:	ds.l	1
up_read_err_f:	ds.l	1
up_read_retv:	ds.l	1
;
up_buff:	ds.b	buf_size	;buffers raw packed bytes for unpacking
up_buff_ix:	ds.w	1
up_buff_ct:	ds.w	1
;
up_bits:	ds.w	1	;buffers raw packed bits for unpacking
up_bits_ct:	ds.w	1
up_refbits:	ds.w	1
up_refsize:	ds.w	1
;
up_ring:	ds.b	max_size	;circular buffer for unpacked data
up_ring_ix:	ds.w	1	;index to io reference point in circle
up_ring_ct:	ds.l	1	;counts bytes passed into circle
up_ring_out_ct:	ds.w	1	;counts bytes remaining to output in ring
;
up_delta:	ds.w	1
up_delta_f:	ds.w	1
;
pk_write_p:	ds.l	1
pk_write_ct:	ds.l	1
pk_write_err_f:	ds.l	1
pk_write_retv:	ds.l	1
;
pk_buff:	ds.b	buf_size	;buffers raw packed bytes
pk_buff_ix:	ds.w	1
pk_buff_ct:	ds.w	1
;
pk_bits:	ds.w	1	;buffers raw packed bits
pk_bits_ct:	ds.w	1
pk_refbits:	ds.w	1
pk_refsize:	ds.w	1
;
pk_ring:	ds.b	max_size	;circular buffer for referenced data
pk_ring_ix:	ds.w	1	;index to io reference point in circle
pk_ring_ct:	ds.l	1	;counts bytes passed into circle
;
pk_string:	ds.b	str_size
pk_string_ct
;
pk_delta:	ds.w	1
pk_delta_f:	ds.w	1
;
tvar_end:
;
;
;-----------------------------------------------------------------------------
	END	;of file:	TST_PACK.S
