;----------------------------------------------------------------------------
;File name:	PCS_AV.S			Revision date:	1996.03.05
;Creator:	Ulf Ronald Andersson		Creation date:	1996.02.19
;(c)1996 by:	Ulf Ronald Andersson		All rights reserved
;----------------------------------------------------------------------------
;
huge_program		= 1	;uncomment if TEXT+DATA sections are > 32KB
keep_windows		= 1	;uncomment to keep ACC vwk in main eventloop
;;;exec_timeout		= 10	;uncomment to enable timer in main eventloop
exec_message		= 1	;uncomment for messages in main eventloop
;
;----------------------------------------------------------------------------
;
	opt	o-
;
	output	.ACC
;
	include	URAn_DOS.S
	include	URAn_JAR.S
	include	URAn_SIM.S
	include	URAn_LA.S
	include	URAn_AV.S
	include	URAn_XB.S
	include	FINDLACE.S
;
;----------------------------------------------------------------------------
;
MAX_files	= 80
MAX_flen	= 110000
;
;----------------------------------------------------------------------------
;
	SECTION	TEXT
;
	include	URAn_APP.S
;
;----------------------------------------------------------------------------
;
	ifnd	huge_program
	SECTION	DATA
	endc
;
acc_name:	dc.b	'  PCS AV-viewer'	;for ACC menu registration
		dc.b	NUL
;
;----------------------------------------------------------------------------
;
	ifnd	huge_program
	SECTION	BSS
	endc
;
message:	ds.w	8		;evnt_mesag message pipe
intin:		ds.w	30		;30 words or more for AES/VDI
intout:		ds.w	45		;45 words or more for AES/VDI
ptsin:		ds.w	30		;30 words or more for VDI
ptsout:		ds.w	12		;12 words or more for VDI output coordinates
		ds.l	256		;subroutine stack >= 100 longs
mystack:	ds.l	4		;top of subroutine stack
;
;----------------------------------------------------------------------------
;
	SECTION	TEXT
;
;----------------------------------------------------------------------------
;	Constants, Variables, and Usage of the URAn_APP.S library
;
;rz		'relative zero' for internal references
;basepage_p	-> program's base page
;tsr_size	.L size of BASEPAGE+TEXT+DATA+BSS  (only TOS/TTP may TSR)
;progtype	.L indicates program type:
;  ...			$0000.$FFFF == TOS/TTP/boot_PRG
;  ...			$0000.ap_id == APP/GTP/non_boot_PRG
;  ...			$FFFF.ap_id == ACC
;acc_flag	is the high word of 'progtype'
;tos_flag	is the low word of 'progtype'
;bootflag	.W $FFFF == PRG booted from AUTO (also sets 'tos_flag')
;menu_id	.W menu id for an ACC, otherwise null
;g_handle	.W workstation handle for ACC/APP/GTP/non_boot_PRG
;vwk_handle	.W virtual workstation handle
;contrl		12 words for AES/VDI control data
;
;wk_x_rez \
;wk_y_rez  \/ from
;wk_pix_w  /\ opnvwk
;wk_pix_h /
;
;NB: if symbol 'huge_program' is defined, above data is in TEXT section (else in BSS)
;NB: defining 'huge_program' also makes function calls use 'jsr' (instead of bsr)
;
;Required user routines:
;
;init_app	called for ACC/APP/GTP/non_boot_PRG to init application,
;		but doesn't need appl_init, graf_handle, or v_opnvwk,
;		nor does an ACC need menu_register.
;		Suitable use is for initialization of object trees.
;NB:  for ACC	menu_register is called between init_app and exec_app
;
;exec_app	called to execute the main application regardless of type,
;		but doesn't need v_clsvwk, or appl_exit, or ACC appl_mesag.
;		This call will be repeated for a reactivated ACC.
;		Non_acc programs should have exit code in d0 at RTS.
;		(See details at 'Exit codes:' below)
;
;	At entry to either of these two routines:
;
;		d6.W	== bootflag	\
;		d7.L	== progtype	 > See descriptions above.
;		a6.L	== rz		/
;
;Optional user routines:
;
;exec_timer	Called for ACC that has a defined constant 'exec_timeout',
;		whenever evnt_multi produces such a timer event.
;		The constant is placed as long at 'main_timeout', and may
;		there be dynamically adjusted by the program.
;
;exec_mesag	Called for ACC that has a defined constant 'exec_message',
;		whenever evnt_multi/evnt_mesag produces messages that are
;		not AC_OPEN  (such as VA_START).
;
;		If the constant 'keep_windows' is also set, the workstation
;		will not be closed at each return (you must obey AC_CLOSE).
;		This places a word == $FF00 at 'keep_wind_f', and if the top
;		byte is cleared the workstation closure is enabled again.
;
;NB: nonACC APP may force acc_flag to $FFFF, at first entry to exec_app.
;    It will be treated as an ACC at subsequent returns from exec_app.
;    This is very useful with AV_PROTOKOLL and under multitasking.
;    To exit program completely, clear ACC_flag again and use 'rts'.
;
;Exit codes:	At exit from exec_app, d0 has the following effects
;		when the program was not started as accessory.
;
; negative	=> Pterm(d0)			=> error code exit
; 0		=> Pterm(d0)			=> error free exit
; 0x0000ADD0	=> Ptermres(tsr_size,0)		=> error free resident exit
; 0x0000ADD1	=> Ptermres(d1,0)		=> error free resident exit
; 0x0000ADD0	=> Ptermres(d1,d2)		=> error code resident exit
;
;----------------------------------------------------------------------------
;Start of:	init_app
;----------------------------------------------------------------------------
;
init_app:
	tst	acc_flag
	bne.s	.done_sim_test
	bios	Kbshift,?
	and	#$0F,d0
	cmp	#$01,d0
	bne.s	.done_sim_test
	gemdos	Super,!
	move.l	d0,-(sp)
;
	seek_cookie	#'MiNT'
	bpl.s	.do_sim_ACC
	seek_cookie	#'MagX'
	bpl.s	.do_sim_ACC
	seek_cookie	#'Gnva'
	bpl.s	.do_sim_ACC
	bra.s	.done_sim_ACC
;
.do_sim_ACC:
	st	acc_flag
.done_sim_ACC:
	gemdos	Super,()
.done_sim_test:
	include	URAn_ARG.S
	cmp	#2,arg_cnt
	blo	.init_no_arg
	tst	acc_flag
	beq.s	.done_revision
	st	revise_type_f	
.done_revision:
	move.l	arg_ptr,a0
.loop_1:
	tst.b	(a0)+
	bne.s	.loop_1
	lea	main_path_s,a1
	move.l	a1,a4		;possible filename_start
	moveq	#127-1,d1
.loop_2:
	move.b	(a0)+,d0
	move.b	d0,(a1)+
	cmp.b	#':',d0
	beq.s	.mark_pos
	cmp.b	#'\',d0
	bne.s	.next_char
.mark_pos:
	move.l	a1,a4		;possible filename_start
.next_char:
	tst.b	d0
	dbeq	d1,.loop_2
	bne.s	.init_no_arg
	cmp.b	#'\',-2(a1)
	beq.s	.main_path_ok
	gemdos	Fsetdta,loc_dta
	move.l	d0,-(sp)
	gemdos	Fsfirst,main_path_s,!
	move.l	d0,d3
	gemdos	Fsetdta,()
	tst.l	d3
	bne.s	.add_slash
	clr.b	(a4)
	bra.s	.main_path_ok
;
.add_slash:
	lea	main_path_s,a0
.loop_3:
	tst.b	(a0)+
	bne.s	.loop_3
	cmp.b	#'\',-2(a0)
	beq.s	.main_path_ok
	move.b	#'\',-1(a0)
	clr.b	(a0)
.init_no_arg:
	clr.b	main_path_s
.main_path_ok:
exit_init_app:
	rts
;
;----------------------------------------------------------------------------
;End of:	init_app
;----------------------------------------------------------------------------
;	URAn_ARG.S defines two variables
;
;arg_cnt	== number of strings on command line
;arg_ptr	-> NUL_separated argument strings + final NUL
;
;NB:	Both of the above include a dummy program name (first string==NUL).
;----------------------------------------------------------------------------
;Start of:	exec_app
;----------------------------------------------------------------------------
;
exec_app:
	cmp	#2,arg_cnt
	blo.s	.fselect
	tst.b	main_path_s
	bne.s	.arg_path
.fselect:
	pea	prompt_s
	pea	main_name_s
	pea	main_mask_s
	pea	main_path_s
	bsr	fselect_sub
	add	#16,sp
	tst.l	d0
	bne.s	.use_path
	clr.b	main_path_s
	bra.s	exit_exec_app
;
.arg_path:
	clr	arg_cnt
.use_path:
	bsr	slideshow_sub
exit_exec_app:
	rts
;
;----------------------------------------------------------------------------
;End of:	exec_app
;----------------------------------------------------------------------------
;Start of:	exec_timer
;----------------------------------------------------------------------------
;
	ifd	exec_timeout	;cond:	ifd exec_timeout
exec_timer:
	move	state,d0
	lsl	#2,d0
	lea	state_fn_t,a0
	move.l	(a0,d0),a0
	jmp	(a0)
;
state_01:	;01 == primary response to VA_START
	AV_send	ACCWINDOPEN,!
	move	#2,state
	bra	exit_exec_timer
;
state_02:	;02 == secondary response to VA_START
	bsr	slideshow_sub
	move	#3,state
	bra	exit_exec_timer
;
state_03:	;03 == tertiary response to VA_START
	AV_send	ACCWINDCLOSED,!
	move	#0,state
	bra	exit_exec_timer
;
state_00:	;00 == passively awaiting commands
exit_exec_timer:
	rts
;
state_fn_t:
	dc.l	state_00,state_01,state_02,state_03
;
	endc			;ends:	ifd exec_timeout
;
;----------------------------------------------------------------------------
;End of:	exec_timer
;----------------------------------------------------------------------------
;Start of:	exec_mesag
;----------------------------------------------------------------------------
;
	ifd	exec_message	;cond:	ifd exec_message
exec_mesag:
	cmp	#AC_CLOSE,message
	beq	exec_mesag_AC_CLOSE
	cmp	#VA_START,message
	beq	exec_mesag_VA_START
;
	bra	exit_exec_mesag
;
exec_mesag_VA_START:
	move	message+2,AV_server_id
	move.l	message+6,a0
	move.l	a0,VA_start_cmd_p
	lea	main_path_s,a1
.loop_1:
	move.b	(a0)+,(a1)+
	bne.s	.loop_1
	AV_send	PROTOKOLL,#w_VA_START,my_name_s
	AV_send	ACCWINDOPEN,!
	bsr	slideshow_sub
	AV_send	ACCWINDCLOSED,!
;;;	move	#1,state
	bra	exit_exec_mesag
;
exec_mesag_AC_CLOSE:
	sf	keep_wind_f
exit_exec_mesag:
	rts
	endc			;ends:	ifd exec_message
;
;----------------------------------------------------------------------------
;End of:	exec_mesag
;----------------------------------------------------------------------------
;
slideshow_sub:
	find_lace
	move.l	d0,lpt_p
	GEM_aes	wind_update,#1
;
	lea	main_path_s,a0
	move.l	a0,a1
.loop:
	move.b	(a0)+,d0
	cmp.b	#'\',d0
	bne.s	.next_char
	move.l	a0,a1
.next_char:
	tst.b	d0
	bne.s	.loop
	clr.b	(a1)
;
	clr	d0
	move.b	main_path_s,d0
	beq.s	.exit
	sub	#'A',d0
	blt.s	.exit
;
	gemdos	Dsetdrv,d0
	gemdos	Dsetpath,main_path_s
	bsr	PCS_view_sub
;
.exit:
	GEM_aes	wind_update,!
	tst	acc_flag
	beq	.skip_redraw
	aes_redraw
.skip_redraw:
	rts
;
;----------------------------------------------------------------------------
;Start of:	included subroutine files
;----------------------------------------------------------------------------
;
	include	FSEL_SUB.S
;
;----------------------------------------------------------------------------
;End of:	included subroutine files
;----------------------------------------------------------------------------
;Start of:	routines from PCS_VIEW.TOS
;----------------------------------------------------------------------------
;
PCS_view_sub:
	find_lace
	move.l	d0,lpt_p
	gemdos	Super,!
	move.l	d0,system_ssp
;
	sf	entry_lace_f		;assume entry without overscan
	move.l	lpt_p,a3
	move.l	a3,d0
	beq.s	.done_lace		;skip overscan fix if LaceScan absent
	move.l	lpt_auto_sense(a3),a0
	jsr	(a0)
	move.b	d0,entry_lace_f
	beq.s	.done_lace		;skip overscan fix if LaceScan passive
	move.l	lpt_auto_switch(a3),a0
	jsr	(a0)
	move.l	lpt_auto_sense(a3),a0
	jsr	(a0)
.done_lace
;
	move.b	(hw_syn).w,syn_value
	and.b	#3,syn_value
	sf	escape_flag
	bsr	empty_key_buff
	bsr	take_screen
	bsr	take_timers
	gemdos	Dgetdrv
	move	d0,picfile_drive
	clr	files_total		;start with no files to display
	lea	filetype_list(pc),a0
	st	seek_error
.types_loop:
	move.l	(a0)+,filetype_s	;filetype_s = next filetype
	beq.s	.done_types		;exit loop if all types done
	move.l	(a0)+,filetype_viewer_p	;filetype_viewer_p -> next viewer
	bsr	seek_files
	and	d0,seek_error
	cmp	#MAX_files,files_total
	blo.s	.types_loop
.done_types:
	tst	seek_error
	bne	exit_program		;exit if no files to display
	tst	files_total
	beq	exit_program		;exit if no files to display
;
	clr	file_index
	lea	files_viewptrs,a0
	lea	files_pathnames,a1
;----------------------------------------------------------------------------
;	main slideshow loop 'slide_loop' in 'main'
slide_loop:
	move	file_index(pc),d0
	move	d0,d1
	add	d0,d0
	add	d0,d0			;d0 = index * 4
	mulu	#20,d1			;d1 = index * 20
	move.l	(a0,d0),a2		;a2 -> view routine for file
	lea	(a1,d1),a6		;a6 -> pathname to load file
	move.l	a6,load_fname_p
	movem.l	a0-a2,-(sp)		;push a0-a2
	move.l	#MAX_flen,load_fsize
	move.l	#packbase,load_buff_p
	bsr	load_picfile
	cmpi.l	#'ICE!',packbase
	bne.s	.non_ice
;here ICE! unpacking starts
	movem.l	d0-d7/a0-a6,-(sp)	;push all except sp
	move.l	load_fsize,d0
	add.l	d0,load_buff_p
	lea	(packbase).l,a0
	move.l	load_buff_p,a1
	bsr	unpack_ICE
	movem.l	(sp)+,d0-d7/a0-a6	;pull all except sp
;here ICE! unpacking ends
.non_ice:
	movem.l	(sp)+,a0-a2		;pull a0-a2
	tst.l	d0			;load error ?
	bne.s	.done_view
	movem.l	d0-d7/a0-a6,-(sp)	;push all except sp
	move	#1,vbl_count
.pre_view_sync:
	tst	vbl_count
	bgt.s	.pre_view_sync
	bsr	stop_VIEW
	bsr	empty_hw_kbdata
	bsr	empty_key_buff
	jsr	(a2)			;Call view routine for file
	move	#1,vbl_count
.post_view_sync:
	tst	vbl_count
	bgt.s	.post_view_sync
	bsr	stop_VIEW
	bsr	empty_hw_kbdata
	bsr	empty_key_buff
	movem.l	(sp)+,d0-d7/a0-a6	;pull all except sp
.done_view:
	tst.b	escape_flag
	bne	exit_program
	addq	#1,file_index
	move	file_index,d0
	cmp	files_total,d0
	blo	slide_loop
	clr	file_index
	bra	slide_loop
;
;End of main slideshow loop 'slide_loop' in 'main'
;----------------------------------------------------------------------------
;
;load_picfile:	;Called only from 'slide_loop' of 'main'
;entry:	load_fsize	== buffer size
;	load_buff_p	-> buffer
;	load_fname_p	-> files pathname
;exit:	load_fname	=  bytes loaded unless error occurred
;	d0		=  error code or zero
load_picfile:	;Called only from 'slide_loop' of 'main'
	gemdos	Fopen|_ind,load_fname_p(pc),!
	move.l	d0,d5
	tst.l	d0
	bmi.b	.load_error
	gemdos	Fread|_ind,d5,load_fsize(pc),load_buff_p(pc)
	tst.l	d0
	bpl.b	.loaded_ok
	gemdos	Fclose,d5
.load_error:
	moveq	#-1,d0
	rts
;
.loaded_ok:
	move.l	d0,load_fsize
	gemdos	Fclose,d5
	moveq	#0,d0
	rts
;
;
load_fname_p:	dc.l	0
load_buff_p:	dc.l	0
load_fsize:	dc.l	0
;
;
seek_files:	;Called only from 'main', before 'slide_loop', once per valid filetype
	movem.l	a0-a2,-(sp)
	lea	picfile_pathname(pc),a1
	move	picfile_drive,d0
	addi	#'A',d0
	move.b	d0,(a1)+
	move.b	#':',(a1)+
	move.b	#'*',(a1)+
	move.b	#'.',(a1)+
	lea	filetype_s(pc),a0
	move.b	(a0)+,(a1)+
	move.b	(a0)+,(a1)+
	move.b	(a0)+,(a1)+
	clr.b	(a1)
	gemdos	Fsetdta,loc_dta(pc)
	gemdos	Fsfirst,picfile_pathname(pc),!
	tst.l	d0
	bne.s	.done_seek		;exit with error if no file found
.seek_loop:				;loc_dta holds the name of a valid picture file
	bsr.s	copy_pathname
	cmp	#MAX_files,files_total
	bhs.s	.done_seek_ok
	gemdos	Fsnext
	tst.l	d0
	beq.s	.seek_loop
.done_seek_ok:
	clr.l	d0			;clear error flag since we found some file
.done_seek:
	movem.l	(sp)+,a0-a2
	rts
;
;
copy_pathname:	;Called only from 'seek_files' (called only from 'main')
	lea	loc_dta_fname,a0	;a0 -> found filename
	lea	picfile_pathname(pc),a1	;a1 -> search pathname
	lea	files_pathnames(pc),a2
	lea	files_viewptrs(pc),a3
	move	files_total(pc),d0	;\
	move	d0,d1			;|
	add	d1,d1			; > a3 -> files_viewptrs + ( 4 * files_total )
	add	d1,d1			;|
	adda	d1,a3			;/
	move.l	filetype_viewer_p(pc),(a3)
	mulu	#20,d0
	adda	d0,a2			; a2 -> files_pathnames + ( 20 * files_total )
	move.b	(a1)+,(a2)+		;store drive character from search path
	move.b	(a1)+,(a2)+		;store ':' from search path
	moveq	#13-1,d0		;\
.strcpy_lp:				; \
	move.b	(a0)+,(a2)+		; / store found 13 char name string (incl NUL)
	dbra	d0,.strcpy_lp		;/
	clr.b	(a2)			;store forced NUL after found name
	addq	#1,files_total		;increment files_total
	rts
;
;
picfile_drive:		ds.w	1
filetype_s:		ds.l	1
loc_dta:		ds.b	30
loc_dta_fname:		ds.b	14
files_total:		ds.w	1
picfile_pathname:	ds.b	64
files_pathnames:	ds.b	MAX_files*20
files_viewptrs:		ds.l	MAX_files
filetype_viewer_p:	ds.l	1
file_index:		ds.w	1
;
filetype_list:
		dc.l	'PC1'<<8,PC1_viewer
		dc.l	'TN?'<<8,TNx_viewer
		dc.l	'PCS'<<8,PCS_viewer
		dc.l	NUL
;
;----------------------------------------------------------------------------
;
PC1_viewer:
	move.b	syn_value(pc),(hw_syn).w
	move.l	load_buff_p,a0
	bsr	prepare_PC1
	bra	static_view
;
;----------------------------------------------------------------------------
;
TNx_viewer:
	move.b	syn_value(pc),(hw_syn).w
	move.l	load_buff_p,a0
	bsr	prepare_TNx
static_view:
	bsr	screen_static
	move	slide_time,vbl_count
.static_viewloop:
	bsr	scan_kb_cmd
	tst.b	escape_flag
	bne.s	.static_escape
	tst.b	halt_flag
	bne.s	.static_halt
	tst	vbl_count
	bgt.s	.static_viewloop
	bra.s	.static_escape
;
.static_halt:
	bsr	scan_kb_cmd
	tst.b	escape_flag
	bne.s	.static_escape
	tst.b	halt_flag
	bne.s	.static_halt
.static_escape:
	rts
;
;----------------------------------------------------------------------------
;
PCS_viewer:
	move.l	screen_bp_2,a0
	bsr	clear_32000_ia0
	move.l	screen_bp_1,a0
	bsr	clear_32000_ia0
	move.l	load_buff_p,a0
	bsr	fix_PCS_mode
	move	#1,vbl_count
.PCS_delay:
	tst	vbl_count
	bgt.s	.PCS_delay
	bsr	start_PCS
	move	slide_time,d0
	move	d0,vbl_count
.PCS_viewloop:
	cmp	vbl_count,d0
	beq.s	.PCS_viewloop
	bsr	scan_kb_cmd
	tst.b	escape_flag
	bne.s	.PCS_escape
	tst.b	halt_flag
	bne.s	.PCS_halt
	move	vbl_count,d0
	bgt.s	.PCS_viewloop
	bra.s	.PCS_escape
;
.PCS_halt:
	move	#1,vbl_count
.halt_wait:
	tst	vbl_count
	bgt.s	.halt_wait
	bsr	scan_kb_cmd
	tst.b	escape_flag
	bne.s	.PCS_escape
	tst.b	halt_flag
	bne.s	.PCS_halt
.PCS_escape:
	rts
;
;
fix_PCS_mode:	;called only by 'PCS_viewer'
	sf	interlace_flag
	move.l	screen_bp_2,L6AE6
	move.l	screen_bp_1,L6AEA
	move.l	#pal_buff_1,pal_bp_1
	move.l	#pal_buff_2,pal_bp_2
	lea	6(a0),a1
	move.l	a0,a6
	move.b	#0,files_hw_syn
	btst	#0,5(a6)
	beq.s	LC36
	move.b	#2,files_hw_syn
LC36:
	move.b	files_hw_syn,(hw_syn).w
	move.l	L6AE6,a0
	bsr.s	LC8C
	move.l	pal_bp_1,a0
	bsr	LD22
	tst.b	4(a6)
	beq.s	LC76
	st	interlace_flag
	move.l	L6AEA,a0
	bsr.s	LC8C
	move.l	pal_bp_2,a0
	bsr	LD22
	bsr	LD6E
	bsr	LD98
LC76:
	addi.l	#$20,pal_bp_1
	addi.l	#$20,pal_bp_2
	rts
;
;
LC8C:
	moveq	#0,d6
	move	#$28,d2
	move	#$C8,d3
	moveq	#5,d4
	move.b	(a1)+,d7
	lsl.w	#8,d7
	move.b	(a1)+,d7
LC9E:
	moveq	#0,d0
	subq	#1,d7
	bmi.b	LCE6
	move.b	(a1)+,d0
	bmi.b	LCE8
	beq.s	LCB2
	cmp.b	#1,d0
	beq.s	LCEC
	bra.s	LCB8
;
LCB2:
	move.b	(a1)+,d0
	lsl.w	#8,d0
	move.b	(a1)+,d0
LCB8:
	subq	#1,d0
	move.b	(a1)+,d1
LCBC:
	move.b	d1,0(a0,d6.w)
	addq	#1,d6
	andi	#1,d6
	bne.s	LCCA
	addq	#8,a0
LCCA:
	subq	#1,d2
	bne.s	LCE0
	moveq	#40,d2
	subq	#1,d3
	bne.s	LCE0
	move	#$C8,d3
	lea	-31998(a0),a0
	subq	#1,d4
	beq.s	LCE6
LCE0:
	dbra	d0,LCBC
	bra.s	LC9E
;
LCE6:
	rts
;
LCE8:
	neg.b	d0
	bra.s	LCF2
LCEC:
	move.b	(a1)+,d0
	lsl.w	#8,d0
	move.b	(a1)+,d0
LCF2:
	subq	#1,d0
LCF4:
	move.b	(a1)+,d1
	move.b	d1,0(a0,d6.w)
	addq	#1,d6
	andi	#1,d6
	bne.s	LD04
	addq	#8,a0
LD04:
	subq	#1,d2
	bne.s	LD1A
	moveq	#40,d2
	subq	#1,d3
	bne.s	LD1A
	move	#$C8,d3
	lea	-31998(a0),a0
	subq	#1,d4
	beq.s	LCE6
LD1A:
	dbra	d0,LCF4
	bra	LC9E
;
LD22:
	move.b	(a1)+,d7
	lsl.w	#8,d7
	move.b	(a1)+,d7
LD28:
	moveq	#0,d0
	subq	#1,d7
	bmi.b	LD52
	move.b	(a1)+,d0
	bmi.b	LD54
	beq.s	LD3C
	cmp.b	#1,d0
	beq.s	LD58
	bra.s	LD42
LD3C:
	move.b	(a1)+,d0
	lsl.w	#8,d0
	move.b	(a1)+,d0
LD42:
	subq	#1,d0
	move.b	(a1)+,d1
	lsl.w	#8,d1
	move.b	(a1)+,d1
LD4A:
	move	d1,(a0)+
	dbra	d0,LD4A
	bra.s	LD28
LD52:
	rts
LD54:
	neg.b	d0
	bra.s	LD5E
LD58:
	move.b	(a1)+,d0
	lsl.w	#8,d0
	move.b	(a1)+,d0
LD5E:
	subq	#1,d0
LD60:
	move.b	(a1)+,d1
	lsl.w	#8,d1
	move.b	(a1)+,d1
	move	d1,(a0)+
	dbra	d0,LD60
	bra.s	LD28
LD6E:
	btst	#0,4(a6)
	bne.s	LD96
	movem.l	d0-d7/a0-a6,-(sp)
	move.l	L6AE6,a0
	move.l	L6AEA,a1
	move	#8000-1,d0
LD8A:
	move.l	(a0)+,d1
	eor.l	d1,(a1)+
	dbra	d0,LD8A
	movem.l	(sp)+,d0-d7/a0-a6
LD96:
	rts
;
LD98:
	btst	#1,4(a6)
	bne.s	LDC0
	movem.l	d0-d7/a0-a6,-(sp)
	move.l	pal_bp_1,a0
	move.l	pal_bp_2,a1
	move	#$2560-1,d0
LDB4:
	move	(a0)+,d1
	eor	d1,(a1)+
	dbra	d0,LDB4
	movem.l	(sp)+,d0-d7/a0-a6
LDC0:
	rts
;
;
files_hw_syn:	dc.b	0
interlace_flag:	dc.b	0
;
;
;----------------------------------------------------------------------------
;	Main display VBI subroutine  (linked via vbl_list)
;
disp_vbl_sub:
	btst	#1,(hw_syn).w
	bne.s	.LDDC
	move.b	#22,hbl_count
	move.l	#disp_60_Hz_hbi,(ev_hbi).w
	bra.s	.LDEA
;
.LDDC:
	move.b	#52,hbl_count
	move.l	#disp_50_Hz_hbi,(ev_hbi).w
.LDEA:
	move	#$2100,SR		;int_mask 1
	pea	(a0)
	pea	(a1)
	move.l	pal_bp_2(pc),a0
	lea	-30(a0),a0
	lea	(hw_pal+2).w,a1
	move	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(sp)+,a1
	move.l	(sp)+,a0
.LE12:
	tst.b	hbl_count
	bne.s	.LE12
	move	#$2300,SR		;int_mask 3
	move	d0,-(sp)	;push d0
.LE1E:					;\
	btst	#0,(hw_kbstat).w	;|
	beq.s	.LE2C			; > empty hw_kbdata
	move.b	(hw_kbdata).w,d0	;|
	bra.s	.LE1E			;/
;
.LE2C:
	move	(sp)+,d0	;pull d0
	tst	vbl_count		;\
	ble.s	.LE3C			; \
	subq	#1,vbl_count		; / decrement vbl_count if > 0
.LE3C:					;/
	move.l	d0,-(sp)
	move.l	pal_bp_1,d0		;\
	tst.b	interlace_flag		;|
	beq.s	.LE56			; \ if interlace swap pal's
	move.l	pal_bp_2,pal_bp_1	; / else force them equal
.LE56:					;|
	move.l	d0,pal_bp_2		;/
	move.l	L6AE6,d0		;\
	tst.b	interlace_flag		;|
	beq.s	.LE74			; \ if interlace swap screens
	move.l	L6AEA,L6AE6		; / else force them equal
.LE74:					;|
	move.l	d0,L6AEA		;/
	lsr.w	#8,d0
	move.l	d0,(hw_vbase2-1).w
	move.l	(sp)+,d0
	rts
;
;End of Main display VBI subroutine
;----------------------------------------------------------------------------
;	50 HZ display HBI exception routine  (linked via ev_hbi)
;
disp_50_Hz_hbi:
	subq.b	#1,hbl_count
	ble.s	.LE8C
	rte
;
.LE8C:
	move	#$2700,SR		;int_mask 7
	movem.l	d0-d7/a0-a6,-(sp)
	move.l	sp,L3A42
	lea	(hw_vpos0).w,a6
	moveq	#0,d0
	moveq	#64,d7
.LEA2:
	move.b	(a6),d0
	beq.s	.LEA2
	sub	d0,d7
	lsl.w	d7,d0
	move	#$10,d0
.LEAE:
	dbra	d0,.LEAE
	nop
	move.l	pal_bp_2(pc),sp
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	rept	199			;\
	movem.l	(sp)+,d0-d7/a0-a6	; \
	movem.l	d0-d7,(hw_pal).w	; |
	movem.l	a0-a6,(hw_pal).w	; |
	move.l	(sp)+,(hw_pal+14*2).w	; |
	lea	(hw_pal).w,a0		; |
	move.l	(sp)+,(a0)+		; |
	move.l	(sp)+,(a0)+		; |
	move.l	(sp)+,(a0)+		; |
	move.l	(sp)+,(a0)+		;  \ This whole block repeats 199 times
	move.l	(sp)+,(a0)+		;  / (one block per picture line)
	move.l	(sp)+,(a0)+		; |
	move.l	(sp)+,(a0)+		; |
	move	#0,(hw_pal).w		; |
	move.l	(sp)+,(a0)+		; |
	move	#0,d0			; |
.LEEA_L3A3A	set	*		; |
	dbra	d0,.LEEA_L3A3A		; |
	nop				; /
	endr				;/
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	move.l	#0,sp
L3A42	=	*-4
	movem.l	(sp)+,d0-d7/a0-a6
	move.l	#nop_hbi,(ev_hbi).w	;link dummy routine after last line
	move.b	#35,(sp)
;----------------------------------------------------------------------------
;	'dummy' HBI exception routine  (linked via ev_hbi)
nop_hbi:
	rte
;
;End of	50 HZ and 'dummy' display HBI exception routines
;----------------------------------------------------------------------------
;	60 HZ display HBI exception routine  (linked via ev_hbi)
;
disp_60_Hz_hbi:
	subq.b	#1,hbl_count
	ble.s	L3A60
	rte
;
L3A60:
	move	#$2700,SR		;int_mask 7
	movem.l	d0-d7/a0-a6,-(sp)
	move.l	sp,L6486
	lea	(hw_vpos0).w,a6
	moveq	#0,d0
	moveq	#64,d7
L3A76:
	move.b	(a6),d0
	beq.s	L3A76
	sub	d0,d7
	lsl.w	d7,d0
	move	#$10,d0
L3A82:
	dbra	d0,L3A82
	move.l	pal_bp_2(pc),sp
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	rept	199
	movem.l	(sp)+,d0-d7/a0-a6
	movem.l	d0-d7,(hw_pal).w
	movem.l	a0-a6,(hw_pal).w
	move.l	(sp)+,(hw_pal+14*2).w
	lea	(hw_pal).w,a0
	move.l	(sp)+,(a0)+
	move.l	(sp)+,(a0)+
	move.l	(sp)+,(a0)+
	move.l	(sp)+,(a0)+
	move.l	(sp)+,(a0)+
	move.l	(sp)+,(a0)+
	move.l	(sp)+,(a0)+
	move	#0,(hw_pal).w
	move.l	(sp)+,(a0)+
	move	#0,d0
.L3ABC_L6480	set	*
	dbra	d0,.L3ABC_L6480
	endr
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	move.l	#0,sp
L6486	=	*-4
	movem.l	(sp)+,d0-d7/a0-a6
	move.l	#nop_hbi,(ev_hbi).w	;link dummy routine after last line
	move.b	#35,(sp)
	rte
;
;End of	60 HZ display HBI exception routine
;----------------------------------------------------------------------------
;
start_PCS:
	move.b	#18,(hw_kbdata).w	;mouse off
	lea	L64D4(pc),a0
	move.l	new_vbl_list+4,(a0)+
	move	#$2700,SR		;int_mask 7
	move.l	#disp_vbl_sub,new_vbl_list+4
	move	#$2300,SR		;int_mask 3
	rts
;
;----------------------------------------------------------------------------
;
stop_VIEW:
	lea	(hw_pal).w,a0
	rept	8
	clr.l	(a0)+			;Black out pallette
	endr
	lea	L64D4(pc),a0
	tst	(a0)
	beq.s	.no_act_PCS
	move	#$2700,SR		;int_mask 7
	move.l	(a0),new_vbl_list+4
	clr.l	(a0)
	move.b	#8,(hw_kbdata).w	;mouse on
.no_act_PCS:
	move	#$2700,SR		;int_mask 7
	move.l	screen_bp_1,d0		;\
	lsr.w	#8,d0			; > hw_vbase -> .l(screen_bp_1)
	move.l	d0,(hw_vbase2-1).w	;/
	move	#$2300,SR		;int_mask 3
	rts
;
;
L64D4:	dc.l	0
;
;----------------------------------------------------------------------------
;
empty_hw_kbdata:
	move	SR,-(sp)
	ori	#$0700,SR
	move.l	d7,-(sp)
.L64EA:
	btst	#0,(hw_kbstat).w
	beq.s	.L64F8
	move.b	(hw_kbdata).w,d7
	bra.s	.L64EA
.L64F8:
	move.l	(sp)+,d7
	move	(sp)+,SR
	rts
;
;----------------------------------------------------------------------------
;
screen_static:	;only called from 'static_view'
	move.l	screen_bp_2,a0
	move.l	screen_bp_1,a1
	move	#8000-1,d0
.L650C:
	move.l	(a0)+,(a1)+
	dbra	d0,.L650C
	move	#1,vbl_count
.L651A:
	tst	vbl_count
	bgt.s	.L651A
	movem.l	pal_static,d0-d7
	movem.l	d0-d7,(hw_pal).w
	rts
;
;----------------------------------------------------------------------------
;	Subroutine to prepare PC1 file for non-interlaced display
;
prepare_PC1:
	addq	#2,a0
	moveq	#16-1,d0
	lea	pal_static,a1
.L653C:
	move	(a0)+,d1
	move	d1,(a1)+
	dbra	d0,.L653C
	move.l	screen_bp_2,a1
	moveq	#0,d3
	moveq	#0,d4
	move	#200-1,d5
.L6552:
	move.b	(a0)+,d1
	ext.w	d1
	bpl.b	.L6592
	cmp.b	#128,d1
	beq.s	.L6552
	neg	d1
	move.b	(a0)+,d2
.L6562:
	move.b	d2,(a1)+
	addq	#1,d3
	cmp.b	#40,d3
	beq.s	.L657A
	btst	#0,d3
	bne.s	.L6574
	addq	#6,a1
.L6574:
	dbra	d1,.L6562
	bra.s	.L6552
;
.L657A:
	moveq	#0,d3
	addq	#1,d4
	cmp.b	#4,d4
	beq.s	.L658A
	suba	#$98,a1
	bra.s	.L6574
;
.L658A:
	moveq	#0,d4
	dbra	d5,.L6574
	bra.s	.L65C0
;
.L6592:
	move.b	(a0)+,(a1)+
	addq	#1,d3
	cmp.b	#40,d3
	beq.s	.L65AA
	btst	#0,d3
	bne.s	.L65A4
	addq	#6,a1
.L65A4:
	dbra	d1,.L6592
	bra.s	.L6552
;
.L65AA:
	moveq	#0,d3
	addq	#1,d4
	cmp.b	#4,d4
	beq.s	.L65BA
	suba	#$98,a1
	bra.s	.L65A4
.L65BA:
	moveq	#0,d4
	dbra	d5,.L65A4
.L65C0:
	rts
;
;End of	Subroutine to prepare PC1 file for non-interlaced display
;----------------------------------------------------------------------------
;	Subroutine to prepare TNx file for non-interlaced display
;
prepare_TNx:
	moveq	#8,d6
	moveq	#0,d2
	moveq	#0,d3
	moveq	#0,d4
	move.b	(a0)+,d0
	cmp.b	#2,d0
	ble.s	L65D6
	addq	#4,a0
	subq.b	#3,d0
L65D6:
	move.b	d0,(hw_rez).w
	moveq	#15,d0
	lea	pal_static(pc),a1
L65E0:
	move.b	(a0)+,d1
	lsl.w	d6,d1
	move.b	(a0)+,d1
	move	d1,(a1)+
	dbra	d0,L65E0
	move.b	(a0)+,d0
	lsl.w	d6,d0
	move.b	(a0)+,d0
	move	d0,d1
	addq	#2,a0
	move.l	a0,a1
	lea	0(a0,d1.w),a2
	move.l	screen_bp_2,a0
	move.l	a0,a3
L6604:
	moveq	#0,d0
	move.b	(a1)+,d0
	bmi.b	L6654
	beq.s	.L6614
	cmp.b	#1,d0
	beq.s	L6658
	bra.s	.L661A
.L6614:
	move.b	(a1)+,d0
	lsl.w	d6,d0
	move.b	(a1)+,d0
.L661A:
	subq	#1,d0
	move.b	(a2)+,d1
	lsl.w	d6,d1
	move.b	(a2)+,d1
.L6622:
	move	d1,(a0)
	lea	160(a0),a0
	addq	#1,d2
	cmp	#$C8,d2
	blt.b	.L664C
	moveq	#0,d2
	lea	-31992(a0),a0
	addq	#1,d3
	cmp	#$14,d3
	blt.b	.L664C
	moveq	#0,d3
	addq	#2,d4
	cmp	#6,d4
	bgt.b	L6652
	lea	0(a3,d4.w),a0
.L664C:
	dbra	d0,.L6622
	bra.s	L6604
L6652:
	rts
;
L6654:
	neg.b	d0
	bra.s	L665E
;
L6658:
	move.b	(a1)+,d0
	lsl.w	d6,d0
	move.b	(a1)+,d0
L665E:
	subq	#1,d0
.L6660:
	move.b	(a2)+,d1
	lsl.w	d6,d1
	move.b	(a2)+,d1
	move	d1,(a0)
	lea	160(a0),a0
	addq	#1,d2
	cmp	#$C8,d2
	blt.b	.L6690
	moveq	#0,d2
	lea	-31992(a0),a0
	addq	#1,d3
	cmp	#$14,d3
	blt.b	.L6690
	moveq	#0,d3
	addq	#2,d4
	cmp	#6,d4
	bgt.b	L6652
	lea	0(a3,d4.w),a0
.L6690:
	dbra	d0,.L6660
	bra	L6604
;
;End of	Subroutine to prepare TNx file for non-interlaced display
;----------------------------------------------------------------------------
;
exit_program:
	bsr	give_timers
	bsr	give_screen
	tst	entry_lace_f
	beq.s	.keep_small
	move.l	lpt_p,a3
	move.l	lpt_auto_sense(a3),a0
	jsr	(a0)
	move.l	lpt_auto_switch(a3),a0
	jsr	(a0)
	move.l	lpt_auto_sense(a3),a0
	jsr	(a0)
.keep_small:
	gemdos	Super|_ind,system_ssp
	rts
;
;This is the program exit, back to caller (or desktop)
;----------------------------------------------------------------------------
;
take_screen:	;Called at main entry only
	xbios	Physbase			;\
	move.l	d0,physbase_p			;/ physbase_p -> physbase by xbios
;;;patch	xbios	Getrez			;\
;;;patch	move	d0,rez_value		;/ rez_value = screen rez by xbios
	move.b	(hw_rez).w,d0
	and	#3,d0
	move	d0,rez_value
	move.l	#screen_buff_2,d0
	clr.b	d0
	move.l	d0,screen_bp_2		;screen_bp_2 -> screen_buff_2 page truncated
	move.l	#screen_buff_1,d0
	clr.b	d0
	move.l	d0,screen_bp_1		;screen_bp_1 -> screen_buff_1 page truncated
;;;patch	xbios	Setscreen,?,?,#0		;screen_rez = 0 (low)
	movem.l	(hw_pal).w,d0-d7	;\
	movem.l	d0-d7,pal_values	;/ pal_values = 16 words from hw_pal
	move	#$2700,SR		;int_mask 7
	move.b	(hw_ddr).w,d0
	move.b	d0,entry_ddr
	move.b	(hw_gpip).w,d1
	move.b	d1,entry_gpip
	or.b	#$80,d0
	move.b	d0,(hw_ddr).w
;;;	and	#$7F,d1
	move.b	d1,(hw_gpip).w
	move.l	(swv_vec).w,entry_swv_vec
	move.l	#view_swv_vec,(swv_vec).w
	move.l	(_vblqueue).w,a0
	move.l	a0,entry_vbl_list
	move.l	(a0),new_vbl_list
	lea	new_vbl_list(pc),a1
	move.l	a1,(_vblqueue).w
	move.b	#0,(hw_rez).w
	move.l	screen_bp_1,d0
	lsr.w	#8,d0
	move.l	d0,(hw_vbase2-1).w	;hw_vbase = screen_bp_1
	move	#$2300,SR		;int_mask 3
dsub:
	rts
;
;
view_swv_vec:
	move.b	#0,(hw_rez).w
	and.b	#$7F,(hw_gpip).w
	or.b	#$80,(hw_gpip).w
	rts
;
;
give_screen:	;called at main exit only
	movem.l	pal_values,d0-d7	;\
	movem.l	d0-d7,(hw_pal).w	;/ hw_pal = 16 words from pal_values
;;;patch	xbios	Setscreen|_ind,?,?,rez_value	;xbios screen rez = rez_value
	move	#$2700,SR		;int_mask 7
	move.b	rez_value+1(pc),(hw_rez).w
	move.b	syn_value(pc),(hw_syn).w
	move.l	physbase_p,d0			;\
	lsr.w	#8,d0				; > hw_vbase = physbase_p
	move.l	d0,(hw_vbase2-1).w		;/
	move.l	entry_vbl_list(pc),(_vblqueue).w
	move.l	entry_swv_vec(pc),(swv_vec).w
	move.b	entry_ddr,d0
	or.b	#$7F,d0
	and.b	d0,(hw_ddr).w
	move	#$2300,SR		;int_mask 3
	rts
;
;
take_timers:	;Called at main entry only
	lea	timer_values,a0
	move	USP,a1
	move.l	a1,(a0)+
	move.l	(ev_hbi).w,(a0)+
	move.l	(ev_vbi).w,(a0)+
	move.l	(iv_kb_midi).w,(a0)+
	move.l	(iv_time_a).w,(a0)+
	move.l	(iv_time_b).w,(a0)+
	move.b	(hw_iera).w,(a0)+
	move.b	(hw_ierb).w,(a0)+
	move.b	(hw_imra).w,(a0)+
	move.b	(hw_imrb).w,(a0)+
	move.b	(hw_tadr).w,(a0)+
	move.b	(hw_tbdr).w,(a0)+
	move.b	(hw_tacr).w,(a0)+
	move.b	(hw_tbcr).w,(a0)+
	move.b	(hw_vr).w,(a0)+
	move	#$2700,SR		;int_mask 7
	move.l	#cntdn_vbl_sub,new_vbl_list+4
	move	#$2300,SR		;int_mask 3
	rts
;
;
give_timers:	;called at main exit only
	move	#$2700,SR		;int_mask 7
	clr.l	new_vbl_list+4
	lea	timer_values,a0
	move.l	(a0)+,a1
	move	a1,USP
	move.l	(a0)+,(ev_hbi).w	;rest entry ev_hbi
	move.l	(a0)+,(ev_vbi).w	;rest entry ev_vbi
	move.l	(a0)+,(iv_kb_midi).w
	move.l	(a0)+,(iv_time_a).w
	move.l	(a0)+,(iv_time_b).w
	move.b	(a0)+,(hw_iera).w
	move.b	(a0)+,(hw_ierb).w
	move.b	(a0)+,(hw_imra).w
	move.b	(a0)+,(hw_imrb).w
	move.b	(a0)+,(hw_tadr).w
	move.b	(a0)+,(hw_tbdr).w
	move.b	(a0)+,(hw_tacr).w
	move.b	(a0)+,(hw_tbcr).w
	move.b	(a0)+,(hw_vr).w
	move	#$2300,SR		;int_mask 3
	rts
;
;
;----------------------------------------------------------------------------
cntdn_vbl_sub:
	tst	vbl_count
	ble.s	.L680A
	subq	#1,vbl_count
.L680A:
	rts
;
;----------------------------------------------------------------------------
;
scan_kb_cmd:
	clr.l	kb_cmd_chr
.kb_loop:
	gemdos	Cconis
	tst.l	d0
	beq.s	.L682E
	gemdos	Crawio,#255
	move.l	d0,kb_cmd_chr
	bne.s	.kb_loop
;
.L682E:
	move.l	kb_cmd_chr(pc),d0
	tst.b	d0
	beq.s	.L6856
	cmp.b	#ESC,d0
	seq	escape_flag
	cmp.b	#' ',d0
	seq	halt_flag
	cmp.b	#CR,d0
	beq.s	.short_count
.L6856:
	swap	d0
	cmp.b	#$3B,d0		;key F1 ?
	blt.b	.exit_cmd	;exit if too low
	cmp.b	#$44,d0		;key F10 ?
	bgt.b	.exit_cmd	;exit if too high
	subi.b	#$3B,d0		;d0 = X = 0..9 for F1..F10
	ext.w	d0
	lsl	#2,d0
	addq	#1,d0
	lsl	#4,d0			;d0 = X * 64 +16
	move	slide_time(pc),d1
	move	d0,slide_time
	sub	d1,d0
	add	vbl_count,d0		;adjust current timeout
	tst	d0
	bgt.s	.chg_count
.short_count:
	moveq	#1,d0
.chg_count:
	move	d0,vbl_count
.exit_cmd:
	rts
;
;
kb_cmd_chr:
	dc.l	0
;
	dc.l	0	;Unref ???
;
;----------------------------------------------------------------------------
;
empty_key_buff:
	movem.l	d0-d7/a0-a6,-(sp)
.loop:
	gemdos	Cconis
	tst.l	d0
	beq.s	.exit
	gemdos	Crawio,#255
	tst.l	d0
	bne.s	.loop
;
.exit:
	movem.l	(sp)+,d0-d7/a0-a6
	rts
;
;----------------------------------------------------------------------------
;
slide_time:
	dc.w	$E0		; new default delay = 3.5 seconds
syn_value:
	dc.w	$0
;
L68A6:	;Unref ???
	movem.l	pal_static,d0-d7
	movem.l	d0-d7,(hw_pal).w
	rts
;
;
L68B6:	;Unref ???
	move.l	screen_bp_2,d7
	move.l	screen_bp_1,screen_bp_2
	move.l	d7,screen_bp_1
	move.b	d7,d0
	lsr.w	#8,d7
	move.l	d7,(hw_vbase2-1).w
	move.b	d0,(hw_vbase0+1).w
	move	#1,vbl_count
.L68E0:
	tst	vbl_count
	bgt.s	.L68E0
	rts
;
;
clear_32000_ia0:	
	lea	32000(a0),a0
	moveq	#0,d1
	move.l	d1,d2
	move.l	d1,d3
	move.l	d1,d4
	move.l	d1,d5
	move.l	d1,d6
	move.l	d1,d7
	move.l	d1,a1
	move.l	d1,a2
	move.l	d1,a3
	move.l	d1,a4
	move.l	d1,a5
	move.l	d1,a6
	moveq	#25-1,d0
.L690A:
	rept	24
	movem.l	d1-d7/a1-a6,-(a0)
	endr
	movem.l	d1-d4/a1-a4,-(a0)
	dbra	d0,.L690A
	rts
;
;
move_32000_ia0_ia1:	;Unref ???
	move	#8000-1,d0
.move_32000_lp:
	move.l	(a0)+,(a1)+
	dbra	d0,.move_32000_lp
	rts
;
;----------------------------------------------------------------------------
;
	include	LACE_LIB.S
;
;----------------------------------------------------------------------------
;	Here starts the ICE unpacker (which is the last routine)
;
;unpack_ICE:	;Called only from 'slide_loop' of 'main'
;entry:	a0	-> header of packed data to unpack, called 'packbase' below
unpack_ICE:	;Called only from 'slide_loop' of 'main'
	movem.l	d0-d7/a0-a6,-(sp)
	bsr.s	moveb_l_ia0p_d0
	cmpi.l	#'ICE!',d0
	bne	.exit_ICE
	bsr.s	moveb_l_ia0p_d0
	lea	-8(a0,d0.l),a5		;a5 -> packbase + .l(packbase+4)
	bsr.s	moveb_l_ia0p_d0
	move.l	d0,(sp)			;.l(sp) = .l(packbase+8)  a0 -> packbase+12
	move.l	a1,a4			;a4 = a1
	move.l	a1,a6			;\
	adda.l	d0,a6			; > a3 = a6 = a1 + .l(packbase+8)
	move.l	a6,a3			;/
	move.b	-(a5),d7
	bsr	L69FA
	move.l	a3,a6
	bsr	L6A26
	bcc.s	.exit_ICE
	move	#$F9F,d7
	bsr	L6A26
	bcc.s	.ICE_loop_1
	moveq	#15,d0
	bsr	L6A30
	move	d1,d7
.ICE_loop_1:
	moveq	#4-1,d6
.ICE_loop_2:
	move	-(a3),d4
	moveq	#4-1,d5
.ICE_loop_3:
	add	d4,d4	;\
	addx	d0,d0	;|
	add	d4,d4	;|
	addx	d1,d1	; \ 4 bits are shifted out of d4 and 1 each into d0..d3
	add	d4,d4	; / this is repeated 4 times per d4 word from -(a3)
	addx	d2,d2	;|
	add	d4,d4	;|
	addx	d3,d3	;/
	dbra	d5,.ICE_loop_3
	dbra	d6,.ICE_loop_2
	movem.w	d0-d3,(a3)
	dbra	d7,.ICE_loop_1
;NB: The above 3 loops perform no actual unpacking at all, but simply rearrange
;NB: bit patterns to decode an encryption inherent in ICE.
;NB: Thus, without this encryption unpacking would be MUCH faster.
;NB: All actual unpacking is made by the subroutines called before '.ICE_loop_1'
.exit_ICE:
	movem.l	(sp)+,d0-d7/a0-a6
	rts
;
;
moveb_l_ia0p_d0:
	moveq	#3,d1
.L69F0:
	lsl.l	#8,d0
	move.b	(a0)+,d0
	dbra	d1,.L69F0
	rts
;
;
L69FA:
	bsr.s	L6A26
	bcc.s	.L6A20
	moveq	#0,d1
	bsr.s	L6A26
	bcc.s	.L6A1A
	lea	L6ABE(pc),a1
	moveq	#4,d3
.L6A0A:
	move.l	-(a1),d0
	bsr.s	L6A30
	swap	d0
	cmp	d0,d1
	dbne	d3,.L6A0A
	add.l	20(a1),d1
.L6A1A:
	move.b	-(a5),-(a6)
	dbra	d1,.L6A1A
.L6A20:
	cmp.l	a4,a6
	bgt.b	L6A42
	rts
;
;
L6A26:
	add.b	d7,d7
	bne.s	.L6A2E
	move.b	-(a5),d7
	addx.b	d7,d7
.L6A2E:
	rts
;
;
L6A30:
	moveq	#0,d1
.L6A32:
	add.b	d7,d7
	bne.s	.L6A3A
	move.b	-(a5),d7
	addx.b	d7,d7
.L6A3A:
	addx	d1,d1
	dbra	d0,.L6A32
	rts
;
L6A42:
	lea	L6AD2(pc),a1
	moveq	#3,d2
.L6A48:
	bsr.s	L6A26
	dbcc	d2,.L6A48
	moveq	#0,d4
	moveq	#0,d1
	move.b	1(a1,d2.w),d0
	ext.w	d0
	bmi.b	.L6A5C
	bsr.s	L6A30
.L6A5C:
	move.b	6(a1,d2.w),d4
	add	d1,d4
	beq.s	.L6A86
	lea	L6ADC(pc),a1
	moveq	#1,d2
.L6A6A:
	bsr.s	L6A26
	dbcc	d2,.L6A6A
	moveq	#0,d1
	move.b	1(a1,d2.w),d0
	ext.w	d0
	bsr.s	L6A30
	add	d2,d2
	add	6(a1,d2.w),d1
	bpl.b	.L6A98
	sub	d4,d1
	bra.s	.L6A98
;
.L6A86:
	moveq	#0,d1
	moveq	#5,d0
	moveq	#-1,d2
	bsr.s	L6A26
	bcc.s	.L6A94
	moveq	#8,d0
	moveq	#63,d2
.L6A94:
	bsr.s	L6A30
	add	d2,d1
.L6A98:
	lea	2(a6,d4.w),a1
	adda	d1,a1
	move.b	-(a1),-(a6)
.L6AA0:
	move.b	-(a1),-(a6)
	dbra	d4,.L6AA0
	bra	L69FA
;
;
L6AAA:	;Unref! ???  (probably needed by ICE unpacker)
	dc.w	$7FFF
	dc.w	$E
	dc.w	$FF
	dc.w	7,7
	dc.w	2,3
	dc.w	1,3
	dc.w	1
L6ABE:	dc.l	$10D,$E,7,4,1
L6AD2:
	dc.b	9,1,0,$FF,$FF,8,4,2,1,0
L6ADC:
	dc.b	$B,4,7,0,1,$1F
	dc.w	$FFFF
	dc.w	$1F
;
;----------------------------------------------------------------------------
;End of:	routines from PCS_VIEW.TOS
;----------------------------------------------------------------------------
;
	make	AV_links
	make	SIM_links
	make	JAR_links
;
;----------------------------------------------------------------------------
text_limit:	section	DATA
;----------------------------------------------------------------------------
;Enter program constant definitions below:
;
my_name_s:
	dc.b	'PCS_AV  ',NUL
prompt_s:
	dc.b	'Set slideshow path',NUL
;
;----------------------------------------------------------------------------
data_limit:	SECTION	BSS
;----------------------------------------------------------------------------
;Enter program variable definitions below:
;
;	Here started the DATA area of PCS_VIEW.TOS
;
new_vbl_list:
	ds.l	1
new_vbl_link:
	ds.l	1
	ds.l	38
;
;	Here started the BSS area of PCS_VIEW.TOS
;
L6AE6:		ds.l	1
L6AEA:		ds.l	1
pal_bp_1:	ds.l	1
pal_bp_2:	ds.l	1
timer_values:	ds.b	40
escape_flag:	ds.b	1
halt_flag:	ds.b	1
hbl_count:	ds.b	2
vbl_count:	ds.b	2
screen_bp_1:	ds.l	1
screen_bp_2:	ds.l	1
physbase_p:	ds.l	1
system_ssp:	ds.l	1
entry_ddr:	ds.b	1
entry_gpip:	ds.b	1
entry_swv_vec:	ds.l	1
entry_vbl_list:	ds.l	1
rez_value:	ds.w	1
main_path_s:	ds.b	128		;\
main_name_s:	ds.b	16		; X File (path) selector data
main_mask_s:	ds.b	16		;/
seek_error:	ds.w	1
VA_start_cmd_p:	ds.l	1		;-> cmd_line of incoming VA_START message
state:		ds.w	1		;AV protocol state
lpt_p:		ds.l	1		;-> LPT structure of LaceScan (if present)
entry_lace_f	ds.w	1
pal_values:	ds.w	16
pal_zeros:	ds.w	16		;only used as data to black out pallette
pal_static:	ds.w	16
pal_buff_1:	ds.b	19232		;pallette buffer 1
pal_buff_2:	ds.b	19232		;pallette buffer 2
		ds.b	255		;allows page truncation for screen buffers
screen_buff_1:	ds.b	32000+256	;Screen buffer 1 with page alignment margin
screen_buff_2:	ds.b	32001		;Screen buffer 2 with page alignment margin
packbase:	ds.b	MAX_flen
;
;
;----------------------------------------------------------------------------
bss_limit:	END
;----------------------------------------------------------------------------
;End of file:	PCS_AV.S
;----------------------------------------------------------------------------
