; /-----------------------------------------------------------------------/
; file:		uuencode.s
; function:	Encode something
; opcode:		
; part of:	Infitra
;
; comment:	Experimental
; author:		E Kuik
; /-----------------------------------------------------------------------/

.include "xlib.i"
.include "infitra.i"

uuelwidth	= 45
;uuelwidth	= 54
lout	= 100	; output x lines at once


.globl UUEncode
UUEncode:	lea	Upath,a0
	tst.b	(a0)
	bne	ndefp
	Copy_str	#Def_path,#Upath
	Merge_str	#Upath,#defmask
ndefp:	Xrsc_gaddr #r_frstr,#Select_binfile,alrt_id,a1
	Xfsel_inp Upath,Name,Psource,(a1),d0
	if_false	d0,Ext_UUE_abort	; No selection
	bra	UUencode

.globl Int_UUEncode
Int_UUEncode:
	move.l	a1,-(sp)
	move.l	a0,-(sp)
	move.l	(sp)+,a2
	Copy_str	a2,#Pdest
	move.l	(sp)+,a2
	Copy_str	a2,#Psource
	bsr	auto_encode
	Return	d0

.globl Ext_UUEncode
Ext_UUEncode:
	move.l	a0,a2
	Copy_str	a2,#Psource
UUencode:	lea	Psource,a0
	Fsfirst	#Psource,#0
	tst.l	d0
	bne	Ext_UUE_abort
	Copy_str	#Psource,#Pdest
	End_str	#Pdest,a0
.bkscan:	move.b	-(a0),d0
	beq	Ext_UUE_abort
	cmp.b	#".",d0
	bne	.bkscan
	move.b	#"u",1(a0)
	move.b	#"u",2(a0)
	move.b	#"e",3(a0)
	move.b	#0,4(a0)
; let user confirm the uue file
	Copy_str	#Pdest,#destpath
	End_str	#destpath,a0
.bksscan:	move.b	-(a0),d0
	beq	Ext_UUE_abort
	cmp.b	#"/",d0
	beq	slfound
	cmp.b	#"\",d0
	bne	.bksscan
slfound:	move.l	a0,-(sp)
	move.l	(sp),a3
	lea	1(a3),a3
	Copy_str	a3,#destname
	move.l	(sp)+,a0
	clr.b	1(a0)
	Merge_str	#destpath,#uuemask
re_select:
	Xrsc_gaddr #r_frstr,#Select_uuename,alrt_id,a1
	Xfsel_inp destpath,destname,Pdest,(a1),d0
	if_false	d0,Ext_UUE_abort	; No selection
auto_encode:
	Fsfirst	#Pdest,#0
	tst.l	d0
	bne	Fnexcist
	Alert	alrt_id,#Msg_Ferror3,#1,d0
	cmp.w	#3,d0
	beq	Ext_UUE_abort
	cmp.w	#2,d0
	beq	re_select
	Fdelete	#Pdest
	tst.w	d0
	beq	Fnexcist
	Alert	alrt_id,#Msg_Ferror4,#1,d0
	cmp.w	#1,d0
	beq	re_select
	bra	Ext_UUE_abort
Fnexcist:
	Fsfirst	#Psource,#0
	Fgetdta
	move.l	d0,a4
; Demo limitation
.ifne Infitra_demo
	cmp.l	#64*1024,26(a4)
	bgt	Ext_UUE_abort
.endif
	Fcreate	#$20,#Pdest
	move.w	d0,d7
	bmi	Fc_err
	Fopen	#0,#Psource
	move.w	d0,d6
	bmi	File_error

	End_str	#Simple_boundary,d0
	sub.l	#Simple_boundary,d0
	Fwrite	#Simple_boundary,d0,d7
	tst.l	d0
	bmi	Xfile_error
	End_str	#Copyright,d0
	sub.l	#Copyright,d0
	Fwrite	#Copyright,d0,d7
	tst.l	d0
	bmi	Xfile_error
; now init the encoding
	End_str	#uue_table,d0
	sub.l	#uue_table,d0
	Fwrite	#uue_table,d0,d7
	tst.l	d0
	bmi	Xfile_error
	End_str	#Psource,a0
.bksscan:	move.b	-(a0),d0
	beq	Xfile_error
	cmp.b	#"/",d0
	beq	slsfound
	cmp.b	#"\",d0
	bne	.bksscan
slsfound:	lea	1(a0),a3
	Copy_str	a3,#uue_file
	Merge_str	#uue_begin,#linefeed
	End_str	#uue_begin,d0
	sub.l	#uue_begin,d0
	Fwrite	#uue_begin,d0,d7
	tst.l	d0
	bmi	Xfile_error
; load the source file
	move.l	26(a4),d5		; source file size
	add.l	#16+3,d5
	Xmalloc	#mx_prefttram,d5,d4
	beq	Xmem_error
	move.l	d4,a5
	Fread	a5,26(a4),d6
	tst.l	d0
	bmi	Xread_error
; now start encoding
	cmp.l	26(a4),d0
	bne	Xread_error
	clr.b	0(a5,d0.l)
	clr.b	1(a5,d0.l)
	clr.b	2(a5,d0.l)
	move.l	d0,d5		; counter
	Get_mnutext #MSG_uuencode1,a2
	lea	msg1,a0
	move.l	a2,(a0)
	Get_mnutext #MSG_uuencode2,a2
	lea	msg2,a0
	move.l	a2,(a0)
	lea	count,a0
	move.l	#0,(a0)
	lea	uuelend,a2
	move.b	#"z",(a2)
	move.l	a5,a0		; source buff
	lea	lcount,a3		; line counter
nxtlgroup:
	move.w	#lout,(a3)
; set display info
	move.l	a0,-(sp)
	Copy_str	msg1,#msg
	End_str	#msg,a0
	move.l	26(a4),d0
	sub.l	d5,d0
	lsr.l	#8,d0
	lsr.l	#2,d0
	moveq	#10,d1
	jsr	ltoa
	Merge_str	#msg,msg2
	Change_mnutext #msg
	move.l	(sp)+,a0
	lea	Lbuff,a1
nxtline:	move.l	#uuelwidth,d3	; chars on a line
	cmp.l	d3,d5
	bgt	deflen
	move.l	d5,d3
deflen:	bsr	Line_encode
	sub.l	#uuelwidth,d5
	beq	lready
	bmi	lready
	sub.w	#1,(a3)
	bne	nxtline
	move.l	a0,-(sp)
	End_str	#Lbuff,d4
	sub.l	#Lbuff,d4
	Fwrite	#Lbuff,d4,d7
	move.l	(sp)+,a0
	tst.l	d0
	bmi	Xread_error
	cmp.l	d0,d4
	bne	Xread_error
	bra	nxtlgroup
lready:	End_str	#Lbuff,d4
	sub.l	#Lbuff,d4
	Fwrite	#Lbuff,d4,d7
	tst.l	d0
	bmi	Xread_error
	cmp.l	d0,d4
	bne	Xread_error
	Def_mnutext
; and finish it
	Mfree	a5

	lea	uue_end,a0
	lea	uuelend,a2
	move.b	(a2),1(a0)
	End_str	#uue_end,d0
	sub.l	#uue_end,d0
	Fwrite	#uue_end,d0,d7
	tst.l	d0
	bmi	Xfile_error
; and let user now wher encoding stops
	End_str	#Simple_boundary,d0
	sub.l	#Simple_boundary,d0
	Fwrite	#Simple_boundary,d0,d7
	tst.l	d0
	bmi	Xfile_error
	Fclose	d6
	Fclose	d7
	Return	#true

Xmem_error:
	Alert	alrt_id,#Sysmemerr,#1,d0
	Fclose	d6
	Fclose	d7
	Fdelete	#Pdest
	Return	#false
Xread_error:
	Mfree	a5
Xfile_error:
	Fclose	d6
File_error:
	Fclose	d7
	Fdelete	#Pdest
Fc_err:	Alert	alrt_id,#Msg_Ferror5,#1,d0
Ext_UUE_abort:
	Return	#false

Line_encode:
	move.l	d3,d2
	add.l	#$20,d2
	move.b	d2,(a1)+

; encode in groups of 3 byte to 4 encoded bytes
Encode:	moveq	#0,d0		; dest reg
	moveq	#0,d1		; temp reg
; encoded byte 1
	move.b	(a0),d0
	rol.l	#6,d0		; use upper 6 bit
	move.b	#0,d0
; encoded byte 2
	move.b	(a0)+,d1
	and.b	#3,d1		; use lower 2 bit
	lsl.b	#4,d1		; 4 bit to left
	or.b	d1,d0
	move.b	(a0),d1		; use upper 4 bit
	rol.b	#4,d1
	and.b	#$0f,d1
	or.b	d1,d0
; encoded byte 3
	rol.l	#8,d0		; create space
	move.b	(a0)+,d1
	and.b	#$0f,d1
	lsl.b	#2,d1
	or.b	d1,d0
	move.b	(a0),d1
	rol.b	#2,d1
	and.b	#3,d1
	or.b	d1,d0
; encoded byte 4
	rol.l	#8,d0		; create space
	move.b	(a0)+,d0
	and.b	#$3f,d0
	add.l	#$20202020,d0
; and store in destination buffer
.rept 4
	rol.l	#8,d0
	move.b	d0,(a1)+
.endm
	sub.w	#3,d3
	beq	lineend
	bpl	Encode
lineend:	lea	uuelend,a2
	move.b	(a2),(a1)+
	sub.b	#1,(a2)
	cmp.b	#"a",(a2)
	bge	endchar
	move.b	#"z",(a2)
endchar:	move.b	#13,(a1)+
	move.b	#10,(a1)+
	move.b	#0,(a1)
	rts

.data
uuelend:	dc.b	"z",0
uuemask:	dc.b	"*.uue",0
defmask:	dc.b	"\*.*",0

.even
Copyright:	dc.b	"File encoded by Infitra "
		Infitra_version
		dc.b	".",13,10,13,10,0
.even
Simple_boundary:	dc.b	13,10
.rept (uuelwidth/3*4)+2
		dc.b	"-"
.endm
		dc.b	13,10,0

.even
uue_table:	dc.b	"table",13,10
chr = $20
.rept 32
	dc.b	chr
	chr = chr + 1
.endm
	dc.b	13,10

.rept 32
	dc.b	chr
	chr = chr + 1
.endm
	dc.b	13,10,0

.even
uue_begin:	dc.b	"begin 644 "
uue_file:		ds.b	64

.even
uue_end:		dc.b	"  ",13,10
		dc.b	"end",13,10,0

linefeed:		dc.b	13,10,0

.bss
count:	ds.l	1
lcount:	ds.w	1
msg1:	ds.l	1
msg2:	ds.l	1
msg:	ds.b	64
Upath:	ds.b	pathsize
Name:	ds.b	32
Psource:	ds.b	pathsize+14
destpath:	ds.b	pathsize
destname:	ds.b	32
Pdest:	ds.b	pathsize+14
Lbuff:	ds.w	((uuelwidth/3*4)+5)*lout
