;----------------------------------------------------------------------------
; File name:	STE_EMU.S		Revision date:	1994.02.19
; Created by:	U.R. Andersson		Creation date:	1990.12.08
; Inspired by:	Mick West's MONO_EMU
;----------------------------------------------------------------------------
; Remarks:
;
; This program makes an ST accept STE colour codes,
; by patching the XBIOS routines, and installs a VBLANK handler
; which causes the extended colour set to be displayed.
; The following XBIOS routines are patched:
;
;   SETPALLETE, SETCOLOR.
;
; Installation should be done at boot, from auto folder.
; It can also be done from desktop.
;
;----------------------------------------------------------------------------
;
	output	.TOS
;
	include	URAn_DOS.S
	include	URAn_XB.S
	include URAn_LA.S
;
;----------------------------------------------------------------------------
;
	section	DATA
;
;----------------------------------------------------------------------------
;
framescan = 2	;range 1..8
;
inimixtb0:	;RGB levels for each STE code in frame 0
;
	dc.w	$000,$111,$222,$333,$444,$555,$666,$777     ;Code 0..7
	dc.w	$101,$121,$323,$343,$545,$565,$767,$777     ;Code 8..F
;
inimixtb1:	;RGB levels for each STE code in frame 1
;
	dc.w	$000,$111,$222,$333,$444,$555,$666,$777     ;Code 0..7
	dc.w	$010,$212,$232,$434,$454,$656,$676,$777     ;Code 8..F
;
izlevel_t:	dc.b	0,1,2,3,4,5,6,7
SteCpy_t:	ds.w	16	; copy of StePal_t to monitor pokes
CpyPal_t:	ds.w	16	; copy of hardware PAL to monitor pokes
dummytb1:	ds.w	16	;protects from ext dest ref's below StePal_t
StePal_t:	ds.w	16	; pallette for STE RGB
dummytb2:	ds.w	16	;protects from ext dest ref's above StePal_t
;
;----------------------------------------------------------------------------
;
	section	BSS
;
;----------------------------------------------------------------------------
;
palptr:		ds.l	1	;-> Hardware pallette (on ST $FF8240)
setcol_rv:	ds.l	3	;d0/a0/at at/for exit from Setcolor
setpal_rv:	ds.l	3	;d0/a0/a1 at/for exit from Setpallete
emuframe:	ds.w	1	;current scan frame index
;
EmuMix_t:	ds.w	$1000*framescan	;Tables of ST RGB  words for STE RGB
;
tsr_limit:	;this is the end of program RAM after initialization
;
stackbot:
		ds.w	$100
stacktop:
;
;----------------------------------------------------------------------------
;
	section	TEXT
;
;----------------------------------------------------------------------------
;
start:
	bra	init_emu
;
;----------------------------------------------------------------------------
;	new XBIOS routine
;
	XB_define	nu_xbios,'ePAL'
;
	btst	#5,(sp)
	beq.s	.user_mode
.super_mode:
	tst	(_longframe).w
	sne	d0
	and	#2,d0
	lea	6(sp,d0),a0
	bra.s	.a0_args
;
.user_mode:
	move.l	USP,a0
.a0_args:
	move	(a0),d0		; Get xbios instruction code
	cmp	#6,d0		; Setpallete ?
	blo.s	norm_xbios	; use old routine if too low
	cmp	#7,d0		; Setcolor ?
	bhi.s	norm_xbios	; use old routine if too high
	bne.s	setpalfix	; go for Setpallete if not Setcolor
setcolfix:
	move.l	a6,-(sp)
	move	2(a0),d1		;d1 = color number
	and	#$0F,d1
	lsl	#1,d1			;d1 = offset for pallette table
	lea	EmuMix_t(pc),a1		;a1 -> frame 0 RGB table
	clr.l	d0
	move	emuframe(pc),d0
	ror	#3,d0			;simulates  'rol     #13,d0'
	add.l	d0,a1			;a1 -> RGB table of current frame
	lea	StePal_t(pc),a6		;a6 -> StePal_t
	move	(a6,d1),setcol_rv+2	;return d0 = old RGB mix
	move	4(a0),d0		;d0 = STE RGB mix
	movea.l	palptr(pc),a0		;a0 -> hardware pal (not flagged !)
	bmi.s	SETCOLF3		;branch if d0 < 0
setpokecol:
	and	#$fff,d0
	move	d0,(a6,d1)			;store STE RGB mix in StePal_t
	move	d0,SteCpy_t-StePal_t(a6,d1)	;also in table to monitor pokes
	lsl	#1,d0
	move	(a1,d0),d0			;d0 = ST RGB mix
	move	d0,(a0,d1)			;store mix for current pallette
	move	d0,CpyPal_t-StePal_t(a6,d1)	;also in table, to monitor pokes
SETCOLF2:
	movem.l	setcol_rv(pc),d0/a0/a1
	move.l	(sp)+,a6
	rte
;
SETCOLF3:
	move	(a6,d1),d0
	cmp	SteCpy_t-StePal_t(a6,d1),d0
	bne.s	setpokecol
	move	(a0,d1),d0
	and	#$777,d0
	cmp	CpyPal_t-StePal_t(a6,d1),d0
	bne.s	setpokecol
	bra.s	SETCOLF2
;
;
norm_xbios:
	XB_gonext_d	nu_xbios
;
setpalfix:
	movem.l	d1/a2/a6,-(sp)
	move.l	2(a0),a1	;a1 -> new (user) STE pallette
	lea	StePal_t(pc),a0	;a0 -> active STE pallette
	lea	EmuMix_t(pc),a2	;a2 -> RGB mix table
	clr.l	d1
	move	emuframe(pc),d1
	ror	#3,d1		;simulates  'rol     #13,d1'
	add.l	d1,a2
	move.l	palptr,a6	;a6 -> hardware ST pallette
	moveq	#16-1,d1
setpal_loop:
	move	(a1)+,d0	;STE RGB from user pallette
	and	#$fff,d0
	move	d0,(a0)+	;store STE RGB in "StePal_t"
	move	d0,SteCpy_t-StePal_t-2(a0)	;stored to monitor pokes
	lsl	#1,d0		;d0 = offset for ST RGB mix
	move	(a2,d0),d0	;d0 = ST RGB mix
	move	d0,(a6)+	;store RGB mix for current frame in hardware
	move	d0,CpyPal_t-StePal_t-2(a0)	;store in CpyPal_t to monitor pokes
	dbra	d1,setpal_loop
	movem.l	setpal_rv,d0/a0/a1
	movem.l	(sp)+,d1/a2/a6
	rte
;
;
;----------------------------------------------------------------------------
;	new VBLANK routine
;
	XB_define	nu_vbl,'ePAL'
	movem.l	d0-d1/a0/a3/a4,-(sp)	; Save all registers
	move.l	palptr(pc),a0
	lea	StePal_t(pc),a3
	lea	EmuMix_t(pc),a4
	clr.l	d1
	move	emuframe(pc),d1
	addq	#1,d1
	cmp	#framescan,d1
	blo.s	frame_ok
	clr	d1
frame_ok:
	move	d1,emuframe
	ror	#3,d1			;simulates  'rol     #13,d1'
	add.l	d1,a4
	moveq	#16-1,d1
EMUPAL_LP:
	move	(a3),d0				;d0 = STE RGB from StePal_t
	cmp	SteCpy_t-StePal_t(a3),d0
	bne.s	setpokevbl
	move	(a0),d0				;d0 = RGB mix from hardware pallette
	and	#$777,d0
	cmp	CpyPal_t-StePal_t(a3),d0	;Same as was stored previously ?
	beq.s	EMUPAL_OK			;if so, just go make frame swap
SETPOKEVBL:
	and	#$fff,d0
	move	d0,(a3)				;else, store new STE RGB mix in StePal_t
	move	d0,SteCpy_t-StePal_t(a3)	;also in table to monitor pokes
EMUPAL_OK:
	move	(a3)+,d0			;d0 = STE RGB mix from StePal_t
	lsl	#1,d0				;d0 = offset for emulation RGB mix
	move	(a4,d0),d0			;d0 = ST RGB mix
	move	d0,(a0)+			;store "new" in hardware to activate color
	move	d0,CpyPal_t-StePal_t-2(a3)	;store in CpyPal_t to monitor pokes
	dbra	d1,EMUPAL_LP
	movem.l	(sp)+,d0-d1/a0/a3/a4		; Restore all registers
	XB_gonext_d	nu_vbl
;
;----------------------------------------------------------------------------
;
init_emu:
	move.l	a0,d5
	move.l	4(sp),a5		;a5 -> Program basepage
	lea	stacktop,sp
	lea	$100(a5),a6
	add.l	bp_textlen(a5),a6
	add.l	bp_datalen(a5),a6
	add.l	bp_bss_len(a5),a6	;a6 -> End of initial program RAM
	move.l	a6,d0
	sub.l	a5,d0
	gemdos	Mshrink,!,(A5),d0
	gemdos	Cconws,installed_s(pc)
	gemdos	Crawcin
	clr	emuframe
	moveq	#framescan-1,d4		;start d4 at max frame number
izframe_loop:				;loop start to init all frame tables
	lea	inimixtb0(pc),a1
	move	d4,d0
	mulu	#16*2,d0
	add.l	d0,a1			;  a1 -> base of init table d4
	lea	EmuMix_t(pc),a2
	move	d4,d0
	mulu	#$1000*2,d0
	add.l	d0,a2			;  a2 -> base of frame table d4
	move	#$FFF,d3		;  start d3 at max RGB mix
EmuMix_loop:				;  loop start to init frame table d4
	clr.l	d2
	move	d3,d2
	ror.l	#8,d2			;    d2 = Red index
	asl	#1,d2
	move	(a1,d2),d0
	and	#$F00,d0		;    d0 = Red level
	rol.l	#4,d2
	and	#15,d2			;    d2 = Green index
	asl	#1,d2
	move	(a1,d2),d1
	and	#$0F0,d1		;    d1 = Green level
	or	d1,d0			;    d0 = Red.Green mix
	rol.l	#4,d2
	and	#15,d2			;    d2 = Blue index
	asl	#1,d2
	move	(a1,d2),d1
	and	#$00F,d1		;    d1 = Blue level
	or	d1,d0			;    d0 = Red.Green.Blue mix
	move	d3,d2			;    d2 = RGB index
	asl	#1,d2
	move	d0,(a2,d2)		;    store RGB mix in table of this frame
	dbra	d3,EmuMix_loop		;  loop back for each possible RGB mix
	lea	16*2(a1),a1		;  a1 -> mixture rule table of next frame
	add	#$1000,a2		;  a2 -> RGB mix table of next frame
	dbra	d4,izframe_loop		;loop back for each frame table
;
	xbios	Setcolor,#0,?
	movem.l	d0/a0/a1,setcol_rv
	move.l	a0,palptr		;-> hardware pallette ( norm $FFFF8240 )
	lea	StePal_t(pc),a0
	move.l	a0,setcol_rv+4
;
	gemdos	Super,!
	move.l	d0,-(sp)
;
	lea	EmuMix_t(pc),a2		;a2 -> RGB mix table of frame 0
	move.l	palptr(pc),a3		;a3 -> hardware pallette
	movem.l	a5-a6,-(sp)
	lea	CpyPal_t(pc),a4
	lea	SteCpy_t(pc),a5
	lea	StePal_t(pc),a6
	moveq	#16-1,d3
iz_pal_loop:			;loop start to init RGB codes of pallette
	move	d3,d4
	asl	#1,d4
	clr	d0
	clr.l	d1
	move	(a3,d4),d1		;d1 = RGB from hardware
	ror.l	#8,d1
	moveq	#3-1,d2
iz_lev_loop:			;loop start for each component of an RGB code
	asl	#4,d0
	and	#7,d1		;mask for ST level
	move.b	izlevel_t-StePal_t(a6,d1),d1
	or	d1,d0
	rol.l	#4,d1
	dbra	d2,iz_lev_loop
	move	d0,(a6,d4)	;store STE RGB mix in StePal_t
	move	d0,(a5,d4)	;store also in SteCpy_t to monitor pokes
	asl	#1,d0		;d0 = ST RGB mix table offset
	move	(a2,d0),d0	;d0 = ST RGB mix
	move	d0,(a3,d4)	;store RGB mix for frame 0 in hardware
	move	d0,(a4,d4)	;store also in CpyPal_t to monitor pokes
	dbra	d3,iz_pal_loop	;loop back to init entire pallette
	movem.l	(sp)+,a5-a6
;
	gemdos	Super,()
;
	xbios	Setpallete,CpyPal_t(pc)
	movem.l d0/a0/a1,setpal_rv
;
	XB_install	nu_xbios(pc),(ev_xbios).w
	XB_install	nu_vbl(pc),(ev_vbi).w
	_a_init
	move		#4096,la_wk_palcolours(a0)
;
	move.l	a6,d0
	sub.l	a5,d0
	gemdos	Ptermres,d0,!
;
;----------------------------------------------------------------------------
;
installed_s:
	dc.b	27,'E'
	dc.b	'The STE Emulator V1.2',CR,LF
	dc.b	'Gives normal ST 4096 colours, like STE',CR,LF
	dc.b	'(c)Copyright 1990: Ulf Ronald Andersson',CR,LF
	dc.b	'All rights reserved, but rights granted',CR,LF
	dc.b	'for non-commercial use and distribution',CR,LF
	dc.b	CR,LF
	dc.b	'This is shareware..., you try it FREE.',CR,LF
	dc.b	'But to keep using it, you should pay.',CR,LF
	dc.b	'(Just send me what you consider fair)',CR,LF
	dc.b	CR,LF
	dc.b	'Send Money, Requests, Problems, etc to:',CR,LF
	dc.b	CR,LF
	dc.b	'       U.R. Andersson,',CR,LF
	dc.b	'        Lokes vaeg 6,',CR,LF
	dc.b	'     S-145 70  Norsborg,',CR,LF
	dc.b	'           Sweden',CR,LF
	dc.b	CR,LF
	dc.b	'Press a key to continue...',CR,LF
	dc.b	NUL
	even
;
;----------------------------------------------------------------------------
;
	END	;of program source
;
;----------------------------------------------------------------------------
; End of file:	STE_EMU.S
;----------------------------------------------------------------------------
