; ===========================================================================
; ---------------------------------------------------------------------------
; Sonic Hacking Contest
; ---------------------------------------------------------------------------
EASTEREGG	=	0
; --- These equates are in the "_Assemble.bat" batch file ---
;LITE		=	0
;GAME		=	0	; 0 = any | 1 = Sonic 1 & 2 | 2 = Sonic 3&K
; ---------------------------------------------------------------------------
VSH_Scroll	= $0000
VSH_MonDyn	= $0020							; monitor dynamic art address
VSH_MonArt	= VSH_MonDyn+$F20					; F20 is maximum size of dynamic art
VSH_LogoArt	= VSH_MonArt+$5A0					; 5A0 is size of smallest monitor frame (the last one to show)
VSH_LogoPlane	= VSH_LogoArt+$6500					; 6500 is size of logo art uncompressed
VSH_PlaneB	= $C200
VSH_FilmArtA	= (VSH_MonArt+$8A80)					; 1420
VSH_FilmArtB	= (((VSH_PlaneB-VSH_FilmArtA)/2)&-$20)+VSH_FilmArtA	; 1420
VSH_68kRAM	= $D000
VSH_Sprite	= $FC00
VSH_PlaneA	= VSH_Sprite+$280
VSH_NumberArt	= VSH_Sprite-$F00					; $F00 is the size of the art when uncompressed
VSH_Window	= $A000							; this window area WILL be available once the logo is fully in
; ---------------------------------------------------------------------------
THOROUGHFRAME	= $1D	; (bitmap frame 013), this is the one and only frame that renders odd pixels properly, but it's slower code...
; ---------------------------------------------------------------------------
jsrl	macro	Address, Reg
		move.l	#Address-(*+6),\2
		jsr	*(pc,\2.l)
	endm

jmpl	macro	Address, Reg
		move.l	#Address-(*+6),\2
		jmp	*(pc,\2.l)
	endm

leal	macro	Address, Reg
		move.l	#Address-(*+6),\2
		lea	*(pc,\2.l),\2
	endm

rseven	macro
		rs.b	__rs&1		; automatic even without needing to turn on +oae...
	endm

; ---------------------------------------------------------------------------
; Equates
; ---------------------------------------------------------------------------

	; --- Film data ---

		rsset	0

_Delay:		rs.b	1
_Static:	rs.b	1
_StatFilm:	rs.b	1
		rseven
_Frame:		rs.b	1
_FilmID:	rs.b	1
_FilmList:	rs.l	1
_Palette:	rs.l	1
_PlaneB:	rs.l	3

_FilmData:	rs.b	0

	; --- Film render ---

		rsset	0

_FilmParent:	rs.w	1		; Points to _FilmData
_ArtBuff:	rs.w	1		; 68k RAM address where the film buffer is meant to be
_Scale:		rs.b	1		; scale frame to render (if FF, then it's drawn to the plane and doesn't need sprite rendering)
_Mirror:	rs.b	1		; mirror the sprites or not
_VRAM:		rs.w	1		; absolute VRAM relative to the frame's VRAM buffer
_VRAMRAW:	rs.w	1		; relative VRAM to 0
_Pal:		rs.w	1		; palette line the film is on
_PosX:		rs.l	1		; X position of the monitor
_PosY:		rs.l	1		; Y position of the monitor
_DestX:		rs.w	1		; X destination of the monitor
_DestY:		rs.w	1		; Y destination of the monitor

_FilmRend:	rs.b	0

	; --- Main RAM ---

		rsset	$FFFF8000
R_RAM:		rs.b	0

R_Buffer:	rs.b	1				; double buffer odd/even flag
R_Intro:	rs.b	1				; if the intro sequence has finished (FF = Yes | 00+ = No (and film order sequence ID/animation)
R_Skip:		rs.b	1				; skip counter for skipping the screen
R_PalFadeMAST:	rs.b	1				; master palette fading
R_PalPrevMAST:	rs.b	1				; previous master palette fading
R_PalFade1:	rs.b	1				; palette fading out counter
R_PalPrev1:	rs.b	1				; previous fade position
R_PalFade2:	rs.b	1				; '' same as above
R_PalPrev2:	rs.b	1				; ''
R_PalFade3:	rs.b	1				; '' same as above
R_PalPrev3:	rs.b	1				; ''
R_PalFade4:	rs.b	1				; '' same as above
R_PalPrev4:	rs.b	1				; ''
R_PalFadeMon:	rs.b	1				; '' same but for monitor colours on palette line 4
R_PalPrevMon:	rs.b	1				; ''
R_YearNumber:	rs.b	1				; last two digits byte (specifying the year), if FF then numbers are finishing
R_FilmNumber1:	rs.b	1				; film ID so the right text can be displayed
R_FilmNumber2:	rs.b	1				; film ID so the right text can be displayed
R_FilmCurrent1:	rs.b	1
R_FilmCurrent2:	rs.b	1
R_UpdateText:	rs.b	1				; if the text should update
R_YearCur:	rs.b	1				; current year displaying 1st
R_YearCur2:	rs.b	1				; current year displaying 2nd
R_YearSlot:	rs.b	1				; odd/even
R_ClearNumbers:	rs.b	1				; flag to specify if the number art should be cleared from the plane
R_LoadLogo:	rs.b	1				; if logo art has been requested to load
R_LogoOrder:	rs.b	1				; counter/order for films to fade
R_LogoFlag:	rs.b	1				; logo palette loading flag
R_PalNumber:	rs.b	1				; if we're on the last palette fading for numbers
	if EASTEREGG=1
R_S1NXLFTW:	rs.b	1				; if Sonic 1 next level should win all trophies
	endc
		rseven
R_FlickerTimer:	rs.w	1				; flickering timer (for full logo)
R_Random:	rs.l	1				; random number storage

R_ShuffleList:	rs.b	$100

R_FilmArt:	rs.b	0
R_FilmArt_1:	rs.b	$280
R_FilmArt_2:	rs.b	$280
R_FilmArt_3:	rs.b	$280
R_FilmArt_4:	rs.b	$280

R_FilmRend:	rs.b	0
R_FilmRend_1:	rs.b	_FilmRend
R_FilmRend_2:	rs.b	_FilmRend
R_FilmRend_3:	rs.b	_FilmRend
R_FilmRend_4:	rs.b	_FilmRend

R_FilmRend_5:	rs.b	_FilmRend
R_FilmRend_6:	rs.b	_FilmRend
R_FilmRend_7:	rs.b	_FilmRend
R_FilmRend_8:	rs.b	_FilmRend

R_FilmRend_9:	rs.b	_FilmRend
R_FilmRend_10:	rs.b	_FilmRend
R_FilmRend_11:	rs.b	_FilmRend
R_FilmRend_12:	rs.b	_FilmRend

R_Film:		rs.b	0
R_Film_1:	rs.b	_FilmData
R_Film_2:	rs.b	_FilmData
R_Film_3:	rs.b	_FilmData
R_Film_4:	rs.b	_FilmData

R_LZVRAM:	rs.l	4		; because VSRAM is being a prick...

R_Palette:	rs.w	$40
R_PalMain:	rs.w	$40

		rs.b	(4-__rs)&3	; align to next long-word
R_RAM_End:	rs.b	0

R_RAM_Size = (R_RAM_End-R_RAM)

	if R_RAM_Size>$1000
		inform 2,"RAM reserved is $%h (Cannot be above $1000 not enough VRAM)", R_RAM_Size
	endif

		rsreset
; ---------------------------------------------------------------------------

		bra.s	.NoDebug

	; --- Debug code ---
	; This floods CRAM with green and loops, so that
	; a savestate can be made and the VDP registers can
	; be ripped
	; ------------------

		move.w	#$2700,sr					; disable interrupts
		lea	($C00000).l,a5					; load VDP data port
		lea	$04(a5),a6					; load VDP control port
		move.w	(a6),ccr					; load status
		bvs.s	*-$02						; if the VDP DMA busy flag was set (bit 1), branch to wait til finished...
		move.l	#$C0000000,(a6)					; set VDP to CRAM write mode
		move.l	#$00A000A0,d1					; set to write GREEN to the screeen
		moveq	#($80/$04)-1,d0					; size of palette to flood

	.DebugColours:
		move.l	d1,(a5)						; setup all colours in palette to green
		dbf	d0,.DebugColours				; repeat for all colours

		bra.w	*						; trap/loop

; ---------------------------------------------------------------------------
; The screen itself
; ---------------------------------------------------------------------------

	.NoDebug:
		move.w	sr,-(sp)					; store register data
		move.w	#$2700,sr					; disable interrupts

;		move.w	#$0100,($A11100).l				; request Z80 to stop
;		moveq	#$01,d0						; prepare to recheck the bit we set
;
;	.WaitZ80:
;		and.b	($A11100).l,d0					; has the Z80 cleared the stop bit? (has it stopped)
;		bne.s	.WaitZ80					; if not, branch

	; --- Setup and clear ---

		lea	($C00000).l,a5					; load VDP data port
		lea	$04(a5),a6					; load VDP control port

		move.w	(a6),ccr					; load status
		bvs.s	*-$02						; if the VDP DMA busy flag was set (bit 1), branch to wait til finished...

		move.w	#$8000|%00000100,(a6)				; $80	; 00LH 01CD - Leftover SMS bar (0N|1Y) | H-Interrupt (0N|1Y) | H,V Counter (0N|1Y) | Disable video signal (0N|1Y)
		move.w	#$8100|%00010100,(a6)				; $81	; SDVM P100 - SMS mode (0N|1Y) | Display (0N|1Y) | V-Interrupt (0N|1Y) | DMA (0N|1Y) | V-resolution (0-1C|1-1E)
		move.w	#$8200|(((VSH_PlaneA&$E000)>>$0A)&$FF),(a6)	; $82	; 00FE DCBA - Scroll Plane A Map Table VRam address
		move.w	#$8300|(((VSH_Window)>>$0A)&$FF),(a6)		; $83	; 00FE DCB0 / 00FE DC00 (20 H-resol) - Window Plane A Map Table VRam address
		move.w	#$8400|(((VSH_PlaneB&$E000)>>$0D)&$FF),(a6)	; $84	; 0000 0FED - Scroll Plane B Map Table VRam address
		move.w	#$8500|(((VSH_Sprite)>>$09)&$FF),(a6)		; $85	; 0FED CBA9 / 0FED CBA0 (20 H-resol) - Sprite Plane Map Table VRam address
		move.w	#$8600|%00000000,(a6)				; $86	; 0000 0000 - Unknown/Unused Register
		move.w	#$8700|$00,(a6)					; $87	; 00PP CCCC - Backdrop Colour: Palette Line | Colour ID
		move.w	#$8800|%00000000,(a6)				; $88	; 0000 0000 - Unknown/Unused Register
		move.w	#$8900|%00000000,(a6)				; $89	; 0000 0000 - Unknown/Unused Register
		move.w	#$8A00|$DF,(a6)					; $8A	; 7654 3210 - H-Interrupt Register
		move.w	#$8B00|%00000000,(a6)				; $8B	; 0000 EVHH - External Interrupt (0N|1Y) | V-Scroll (0-Full|1-2Celled) | H-Scroll: (00-Full|10-Celled|11-Sliced)
		move.w	#$8C00|%10000001,(a6)				; $8C	; APHE SNNB - H-resol (0N|1Y) | Pixel int (0N|1Y) | H-sync (0N|1Y) | Extern-pix (0N|1Y) | S/H (0N|1Y) | Interlace (00N|01Y|11-Split) | H-resol (0-20|1-28)
		move.w	#$8D00|(((VSH_Scroll)>>$0A)&$FF),(a6)		; $8D	; 00FE DCBA - Horizontal Scroll Table VRam address
		move.w	#$8E00|%00000000,(a6)				; $8E	; 0000 0000 - Unknown/Unused Register
		move.w	#$8F00|$02,(a6)					; $8F	; 7654 3210 - Auto Increament
		move.w	#$9000|%00010001,(a6)				; $90	; 00VV 00HH - Plane Y Size (00-20|01-40|11-80) | Plane X size (00-20|01-40|11-80)
		move.w	#$9100|$00,(a6)					; $91	; 7654 3210 - Window Horizontal Position
		move.w	#$9200|$00,(a6)					; $92	; 7654 3210 - Window Vertical Position

		jsrl	ClearVDP,d0					; clear CRAM, VSRAM, and VRAM

	; --- Making some 68k RAM space ---

		move.l	#$94009300|(((R_RAM_Size/2)&$FF00)<<8)|((R_RAM_Size/2)&$FF),(a6)	; DMA size $800
		move.l	#$96009500|(((R_RAM/2)&$FF00)<<8)|((R_RAM/2)&$FF),(a6)			; DMA source $FF0000
		move.l	#$97004000|((R_RAM/2)&$7F0000)|(VSH_68kRAM&$3FFF),(a6)			; DMA destination
		move.w	#((VSH_68kRAM>>$E)&3)|$80,-(sp)						; '' (must be done from 68k RAM)
		move.w	(sp)+,(a6)								; ''

		lea	(R_RAM).w,a1					; load RAM space to use
		moveq	#$00,d0						; clear d0
		move.w	#(R_RAM_Size/4)-1,d1				; size of RAM to clear

	.Clear68kRAM:
		move.l	d0,(a1)+					; clear RAM
		dbf	d1,.Clear68kRAM					; repeat til RAM is clear

	; --- Setting up ---

		move.l	#$40000010,(a6)					; set V-scroll positions based on plane position
		move.w	#(VSH_PlaneA&$1F80)>>4,(a5)			; ''
		move.w	#(VSH_PlaneB&$1F80)>>4,(a5)			; ''

	if LITE=0

	; --- FULL version of setup ---

		suba.l	a1,a1						; clear PLC list
		jsr	SetupPLC(pc)					; ''

		move.w	#VSH_MonArt,d0					; art is A440 bytes, wanna fit it snuggly before C200v
		leal	MonArt001_016,a0				; load last half of monitor art
		jsrl	LZVRAM,a1					; decompress and dump

		move.w	#VSH_NumberArt,d0				; art is F00 byte
		leal	ArtNumbers,a0					; load number art
		jsrl	LZVRAM,a1					; decompress and dump

		lea	LogoPalette(pc),a0				; load number palette
		lea	(R_Palette+$42).w,a1				; load buffer area
		lea	(R_Palette+$62).w,a2				; load buffer area
		moveq	#((LogoPalette_End-LogoPalette)/2)-1,d1		; size of palette

	.LoadNumPal:
		move.w	(a0),(a1)+					; copy number palette
		move.w	(a0)+,(a2)+					; ''
		dbf	d1,.LoadNumPal					; repeat til done

		; Loading film/monitor data

		lea	(R_FilmRend).w,a0				; load film render objects
		lea	.FilmRend_Setup(pc),a1				; load setup list
		move.w	(a1)+,d0					; load 68k art buffer address
		beq.w	.FinishFilmRend					; if finished, branch

	.LoadFilmRend:
		move.w	d0,_ArtBuff(a0)					; save 68k art buffer address (where art is being transferred from)
		move.w	(a1)+,_FilmParent(a0)				; save art film address (as parent)
		move.w	(a1)+,_PosX(a0)					; save X position
		move.w	(a1)+,_DestX(a0)				; save X destination
		move.w	(a1)+,d0					; load Y position
		move.w	d0,_PosY(a0)					; save Y position
		move.w	d0,_DestY(a0)					; save Y destination
		move.w	(a1)+,_Pal(a0)					; save palette line ID
		move.w	(a1)+,d0					; save starting scale
		move.b	d0,_Scale(a0)					; ''
		lea	_FilmRend(a0),a0				; advance to next slot
		move.w	(a1)+,d0					; load 68k art buffer address
		bne.s	.LoadFilmRend					; if not finished, continue reading list

		st.b	(R_FilmRend_2+_Mirror).w			; set second monitor as mirrored (since it's in the intro)
		bra.w	.FinishFilmRend					; finished~

	; --- Initial monitor/film start up positions, palette line, etc ---

	.FilmRend_Setup:
		dc.w	R_FilmArt_1&$FFFF,	R_Film_1&$FFFF		; _ArtBuff.	_FilmParent
		dc.w	$0080+(320+32),		$0080+62		; _PosX,	_DestX
		dc.w	$0080+60,		$0000			; _PosY/_DestY,	_Pal
		dc.w	$0000						; starting frame

		dc.w	R_FilmArt_2&$FFFF,	R_Film_2&$FFFF		; _ArtBuff.	_FilmParent
		dc.w	$0080+(0-32)-8,		$0080+(328-62)		; _PosX,	_DestX
		dc.w	$0080+(224-60),		$2000			; _PosY/_DestY,	_Pal
		dc.w	$0000						; starting frame

		dc.w	R_FilmArt_3&$FFFF,	R_Film_3&$FFFF		; _ArtBuff.	_FilmParent
		dc.w	$0080+(320+32)+$10,	$0080+52+(72*2)		; _PosX,	_DestX
		dc.w	$0080+57+(56*0),	$4000			; _PosY/_DestY,	_Pal
		dc.w	$0001						; starting frame

		dc.w	R_FilmArt_4&$FFFF,	R_Film_4&$FFFF		; _ArtBuff.	_FilmParent
		dc.w	$0080+(320+32)+$20,	$0080+52+(72*3)		; _PosX,	_DestX
		dc.w	$0080+57+(56*0),	$6000			; _PosY/_DestY,	_Pal
		dc.w	$0002						; starting frame


		dc.w	R_FilmArt_2&$FFFF,	R_Film_2&$FFFF		; _ArtBuff.	_FilmParent
		dc.w	$0080+(320+32),		$0080+52+(72*0)		; _PosX,	_DestX
		dc.w	$0080+57+(56*1),	$2000			; _PosY/_DestY,	_Pal
		dc.w	$0000						; starting frame

		dc.w	R_FilmArt_4&$FFFF,	R_Film_4&$FFFF		; _ArtBuff.	_FilmParent
		dc.w	$0080+(320+32)+8,	$0080+52+(72*1)		; _PosX,	_DestX
		dc.w	$0080+57+(56*1),	$6000			; _PosY/_DestY,	_Pal
		dc.w	$0000						; starting frame

		dc.w	R_FilmArt_1&$FFFF,	R_Film_1&$FFFF		; _ArtBuff.	_FilmParent
		dc.w	$0080+(320+32)+$10,	$0080+52+(72*2)		; _PosX,	_DestX
		dc.w	$0080+57+(56*1),	$0000			; _PosY/_DestY,	_Pal
		dc.w	$0001						; starting frame

		dc.w	R_FilmArt_3&$FFFF,	R_Film_3&$FFFF		; _ArtBuff.	_FilmParent
		dc.w	$0080+(320+32)+$20,	$0080+52+(72*3)		; _PosX,	_DestX
		dc.w	$0080+57+(56*1),	$4000			; _PosY/_DestY,	_Pal
		dc.w	$0002						; starting frame


		dc.w	R_FilmArt_3&$FFFF,	R_Film_3&$FFFF		; _ArtBuff.	_FilmParent
		dc.w	$0080+(320+32),		$0080+52+(72*0)		; _PosX,	_DestX
		dc.w	$0080+57+(56*2),	$4000			; _PosY/_DestY,	_Pal
		dc.w	$0000						; starting frame

		dc.w	R_FilmArt_1&$FFFF,	R_Film_1&$FFFF		; _ArtBuff.	_FilmParent
		dc.w	$0080+(320+32)+8,	$0080+52+(72*1)		; _PosX,	_DestX
		dc.w	$0080+57+(56*2),	$0000			; _PosY/_DestY,	_Pal
		dc.w	$0000						; starting frame

		dc.w	R_FilmArt_4&$FFFF,	R_Film_4&$FFFF		; _ArtBuff.	_FilmParent
		dc.w	$0080+(320+32)+$10,	$0080+52+(72*2)		; _PosX,	_DestX
		dc.w	$0080+57+(56*2),	$6000			; _PosY/_DestY,	_Pal
		dc.w	$0001						; starting frame

		dc.w	R_FilmArt_2&$FFFF,	R_Film_2&$FFFF		; _ArtBuff.	_FilmParent
		dc.w	$0080+(320+32)+$20,	$0080+52+(72*3)		; _PosX,	_DestX
		dc.w	$0080+57+(56*2),	$2000			; _PosY/_DestY,	_Pal
		dc.w	$0002						; starting frame

		dc.w	$0000

	.FinishFilmRend:

		; initial delay times before the monitors start showing

		move.b	#26,(R_Film_1+_Delay).w		; DO NOT GO LOWER THAN 26! (Font art loads into dynamic monitor's VRAM)
		move.b	#26+15,(R_Film_2+_Delay).w
		move.b	#7,(R_Film_3+_Delay).w
		move.b	#23,(R_Film_4+_Delay).w
	else

	; --- LITE version of setup ---

		leal	LogoPLC,a1					; load logo art
		jsr	SetupPLC(pc)					; ''
		move.b	#$08,(R_LogoFlag).w

	; -----------------------------

	endc

		move.w	#$8100|%01010100,(a6)				; $81	; SDVM P100 - SMS mode (0N|1Y) | Display (0N|1Y) | V-Interrupt (0N|1Y) | DMA (0N|1Y) | V-resolution (0-1C|1-1E)

	.WaitVBlank:
		move.w	(a6),ccr					; load status
		bmi.s	.WaitVBlank					; if the VDP is in V-blank from a previous frame, branch and wait
	.Wait:	move.w	(a6),ccr					; load status
		bpl.s	.Wait						; if the VDP has not triggered V-blank yet, branch and wait

		move.b	#$01,(R_Skip).w					; set skip counter, 01, then 00, then FF

	if EASTEREGG=1
		jsr	ReadControls(pc)
		move.b	d7,d0
		andi.w	#%11100010,d0
		cmpi.w	#%11100010,d0
		bne.s	.Skip
		st.b	(R_S1NXLFTW).w
		move.w	#$2000,d0
		lea	(R_FilmRend+_FilmRend+_Pal).w,a1
		moveq	#11-1,d1

	.NextS1NXL:
		move.w	d0,(a1)
		lea	_FilmRend(a1),a1
		dbf	d1,.NextS1NXL

	.Skip:
	endc

; ---------------------------------------------------------------------------
; Main loop
; ---------------------------------------------------------------------------

	if LITE=0

MainLoop_Films:

	; --- Between B and A (for frame A) ---

		bsr.w	SendPalette					; transfer the palettes (if any)
		bsr.w	LoadFilm_3_4					; decompress second two films

		bsr.w	VBlankA						; wait for V-blank A frame and run V-blank routine
		bsr.s	CheckSkip					; check if the screen has been skipped by any player
		bmi.s	.Exit						; if so, branch and finish the screen

	; --- Between A and B (for frame B) ---

		bsr.w	SendPalette					; transfer the palettes (if any)

		bsr.w	ControlMonitors					; allow the monitors to move
		bsr.w	LoadFilm_1_2					; decompress first two films
		bsr.w	ControlYear					; control the year being displayed and palette fading for it

		bsr.w	VBlankB						; wait for V-blank B frame and run V-blank routine
		bsr.s	CheckSkip					; check if the screen has been skipped by any player
		bmi.s	.Exit						; if so, branch and finish the screen

		cmpi.b	#$02,(R_LogoFlag).w				; is the logo more or less loaded on-screen?
		blo.s	MainLoop_Films					; if not, branch
	endc

; ---------------------------------------------------------------------------
; Second loop (the logo loop)
; ---------------------------------------------------------------------------

	.Loop:
		bsr.w	SendPalette					; transfer the palettes (if any)

		bsr.w	VBlankA						; wait for V-blank A frame and run V-blank routine
		bsr.s	CheckSkip					; check if the screen has been skipped by any player
		bmi.s	.Exit						; if not, loop back
	; I kinda like the palette fading delay, so delay another frame =3
		bsr.w	VBlankA						; wait for V-blank A frame and run V-blank routine
		bsr.s	CheckSkip					; check if the screen has been skipped by any player
		bpl.s	.Loop						; if not, loop back

	.Exit:
		jmpl	Finish,d0					; finish the screen

	; --- Skip check ---

CheckSkip:
		tst.l	d7						; has player 1 start button been pressed?
		bmi.s	.Skip						; if so, branch
		tst.w	d7						; has player 2 start button been pressed?
		bpl.s	.NoSkip						; if not, branch

	.Skip:
		tst.b	(R_LogoFlag).w					; is the logo already fading into the sequence?
		bgt.s	.YesSkip					; if so, perform hard skip
		subq.b	#$01,(R_Skip).w					; reduce skip counter
		smi.b	(R_Skip).w					; if it's dropped to FF or lower, keep as FF, otherwise 00
	bra.s	.NoSkip
	;	tst.b	(R_Intro).w					; are we still in the intro sequence?
	;	bmi.s	.NoSkip						; if not, branch

	.YesSkip:
		st.b	(R_Skip).w					; force to skip entire screen

	.NoSkip:
		tst.b	(R_Skip).w					; are we skipping the entire screen now? (FF)
		bpl.s	.NoFade						; if not, branch
		addq.b	#$01,(R_PalFadeMAST).w				; increase fade out amount
		moveq	#$10,d0						; check if it's finished fading
		sub.b	(R_PalFadeMAST).w,d0				; '' (return checks with bmi, so...)

	.NoFade:
		rts							; return

; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to control how the year numbers display
; ---------------------------------------------------------------------------

	if LITE=0

ControlYear:
		tst.b	(R_ClearNumbers).w				; are numbers displaying?
		bne.w	.Finish						; if not, branch

	.Change:
		lea	(R_YearCur).w,a1				; load first year's slot
		tst.b	(R_YearSlot).w					; 
		bmi.s	.First
		lea	(R_YearCur2).w,a1

	.First:
		move.b	(R_YearNumber).w,d0				; load current year number
		cmp.b	(a1),d0						; has the year number changed?
		beq.s	.FadeIn						; if not, branch
		st.b	(R_UpdateText).w				; set text to update

	bset.b	#$06,(R_PalNumber).w				; set font as loaded
	bne.s	.NoFont						; if font has already loaded, branch
	leal	ArtFont,a0					; load compressed font address
	move.w	#VSH_MonDyn,d0					; set to dump where the dynamic monitor art would be
	jsr	LZVRAM(pc)					; decompress to VRAM
	move.b	(R_YearNumber).w,d0				; reload current year number

	.NoFont:
		move.b	(R_PalFade3).w,d1				; load palette fading
		addq.b	#$02,d1						; increase fading
		cmpi.b	#$08,d1						; are we finished?
		bls.s	.FadeOut					; if not, branch
		subq.b	#$04,d1						; undo increase
		tst.b	d0
		bpl.s	.FadeOut_Save					; if not finished, branch
		addq.b	#$04,d1						; continue fading
		cmpi.b	#$0C,d1						; are we finished?
		bls.s	.FadeOut					; if not, branch
		move.b	d1,(R_PalFade3).w				; update palette fading
		move.b	d1,(R_PalFade4).w				; ''
		ori.b	#$01,(R_ClearNumbers).w				; set to clear the numbers
		rts							; return

	.FadeIn:
		moveq	#-2,d1						; fade palette in
		add.b	(R_PalFade3).w,d1				; ''
		bcc.s	.NoChange					; if finished, branch

	.FadeOut:
		move.b	d1,(R_PalFade3).w				; update palette fading
		rts							; return

	.FadeOut_Save:
		move.b	(R_FilmNumber1).w,(R_FilmCurrent1).w		; copy film ID's to be updated
		move.b	(R_FilmNumber2).w,(R_FilmCurrent2).w		; ''
		move.b	d0,(a1)						; update current year
		move.b	d1,(R_PalFade3).w				; update palette fading
		rts							; return

	.Finish:

	.NoChange:
		rts							; return

	endc

; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to control how the monitors move on-screen
; ---------------------------------------------------------------------------

	if LITE=0

ControlMonitors:
		cmpi.b	#$02,(R_LogoFlag).w				; is the logo basically more or less loading in?
		bhs.w	.NoMonitors					; if so DO NOT RUN OR CONTROL ANY MONITORS

		lea	(R_FilmRend_1).w,a0				; load film rendering objects
		moveq	#12-1,d6					; set number of objects to check

	.NextFilm:
		move.w	_DestX(a0),d0					; load X position
		sub.w	_PosX(a0),d0					; get distance
		asr.w	#$03,d0						; reduce for speed
		add.w	d0,_PosX(a0)					; advance to destination
		move.w	_DestY(a0),d0					; load X position
		sub.w	_PosY(a0),d0					; get distance
		asr.w	#$03,d0						; reduce for speed
		add.w	d0,_PosY(a0)					; advance to destination

		moveq	#$00,d0						; load scale amount
		move.b	_Scale(a0),d0					; ''
		tst.b	(R_Intro).w					; are we still in the intro sequence?
		bmi.s	.NoIntro					; if not, branch

	; --- intro ---

		cmpi.b	#THOROUGHFRAME,d0				; have we reached mid-point?
		bge.s	.IntroFrame					; if so, branch
		addq.b	#$01,_Scale(a0)					; increase scale

	.IntroFrame:
	;	cmpi.b	#((MonMap_End-MonMap)/2)-16,d0			; have we reached the static frames yet?  (are dynamic frames free to be used by another monitor?)
	;	blo.s	.NoMonitors					; if not, branch
		lea	_FilmRend(a0),a0				; repeat for second monitor (for intro)
		dbf	d6,.NextIntro					; repeat for only 2 films (see below)
		rts

	.NextIntro:
		moveq	#$01-1,d6					; ensure the dbf only runs one more time above for second monitor (for intro)
		bra.s	.NextFilm					; loop

	.NoMonitors:
		rts

	; --- Flying Monitors In ---

	.NoIntro:
		st.b	(R_YearNumber).w				; set numbers as finished
		cmpi.b	#((MonMap_End-MonMap)/2)-1,d0			; have we reached the last frame of scaling?
		beq.w	.DrawOnPlane					; if so, branch
		addq.b	#$01,d0						; increase scale
		bcs.w	.NoDraw						; if it was FF, branch (already drawn to plane)
		move.b	d0,_Scale(a0)					; ''
		cmpi.b	#((MonMap_End-MonMap)/2)-16,d0			; have we reached the static frames yet?  (are dynamic frames free to be used by another monitor?)
		blo.w	.Finish						; if not, branch
		cmpi.w	#12-1,d6					; are we on the first slot?
		beq.s	.Finish						; if so, branch (DO NOT ALLOW 2ND START TO CONTINUE UNTIL FIRST HAS 100% FINISHED, BECAUSE 2ND ISN'T STARTING FROM BEGINNING)

	.Continue:
		tst.w	d6						; is this the last frame?
		beq.s	.Finish						; if so, branch
		lea	_FilmRend(a0),a0				; load next film
		move.w	_DestX(a0),d0					; load X position
		sub.w	_PosX(a0),d0					; get distance
		asr.w	#$03,d0						; reduce for speed
		add.w	d0,_PosX(a0)					; advance to destination
		move.w	_DestY(a0),d0					; load X position
		sub.w	_PosY(a0),d0					; get distance
		asr.w	#$03,d0						; reduce for speed
		add.w	d0,_PosY(a0)					; advance to destination
		addq.b	#$01,_Scale(a0)					; increase scale
		; no need to check if it's reached anything yet, it won't
		; until last film has finished in some way

	.Finish:
		rts							; return

	.NoDraw:
		lea	_FilmRend(a0),a0				; advance to next film
		dbf	d6,.NextFilm					; repeat until a film that's moving/rendering is found

		; All monitors have finished flying in at this point

		bset.b	#$00,(R_LoadLogo).w				; set logo PLC art as now loading
		bne.s	.Finish						; if it's already been requested before, branch
		leal	LogoPLC,a1					; load logo art
		jmp	SetupPLC(pc)					; ''

	; --- Drawing mappings onto the plane ---

	.DrawOnPlane:
		move.w	_DestX(a0),d0					; is the monitor still moving on X?
		sub.w	_PosX(a0),d0					; ''
		bne.s	.Continue					; if so, branch
		move.w	_DestY(a0),d0					; is the monitor still moving on Y?
		sub.w	_PosY(a0),d0					; ''
		bne.s	.Continue					; if so, branch

		st.b	_Scale(a0)					; set as drawn to plane now

		; the first 4 frames have their own art rendering, but the
		; last 8 don't, they're using one of the first 4, so we
		; need to look for that VRAM unforuntately...

		cmpi.b	#(12-4)-1,d6					; have we reached one of the 8 non-permanent frames?
		bhi.s	.NoFirst4					; if not, branch (only render the first four frames if they're on plane)
		lea	(R_FilmRend-_FilmRend).w,a1			; load beginning of film rendering
		move.w	_Pal(a0),d0					; load palette line

	.FindVRAM:
		lea	_FilmRend(a1),a1				; advance to next slot
		cmp.w	_Pal(a1),d0					; have we found the original?
		bne.s	.FindVRAM					; if not, keep searching
		move.w	_VRAMRAW(a1),_VRAMRAW(a0)			; set it to match

	.NoFirst4:

		; -------------------------------------------

		move.l	#$40000000,d0					; prepare VDP write mode
		move.w	_PosX(a0),d0					; load X position
		subi.w	#$0090,d0					; adjust
		lsr.w	#$02,d0						; convert for VDP address
		andi.w	#$007E,d0					; ''
		move.w	_PosY(a0),d1					; load Y position
		subi.w	#$00A8,d1					; adjust
		lsl.w	#$04,d1						; convert for VDP address
		andi.w	#$1F80,d1					; ''
		add.w	d1,d0						; fuse with X
		move.l	d0,d1						; make a copy (one for monitors, one for films)

		; For film (on FG plane)
		addi.w	#(VSH_PlaneA&$E000),d0				; advance to correct VRAM address
		rol.l	#$02,d0						; align for VDP port
		ror.w	#$02,d0						; ''
		swap	d0						; ''

		; For monitors (on BG plane)
		addi.w	#$00FE,d1					; move left and down for monitors (on BG plane)
		addi.w	#VSH_PlaneB,d1					; advance to correct VRAM address
		rol.l	#$02,d1						; align for VDP port
		ror.w	#$02,d1						; ''
		swap	d1						; ''

		movea.w	_FilmParent(a0),a1				; load film slot
		tst.l	_PlaneB(a1)					; is the first plane B slot taken?
		beq.s	.FoundPlaneSlot					; if not, branch
		addq.w	#$04,a1						; advance to second slot
		tst.l	_PlaneB(a1)					; has it been taken?
		beq.s	.FoundPlaneSlot					; if not taken, branch
		addq.w	#$04,a1						; advance to third slot

	.FoundPlaneSlot:
		move.l	d1,d2						; adjust towards the static tiles
		addi.l	#$00820000,d2					; ''
		move.l	d2,_PlaneB(a1)					; store plane B address for later

	; --- Doing FG film first ---

		move.w	#$8F80,(a6)					; set auto-increment mode to skip a column

		move.w	_VRAMRAW(a0),d2					; load relative VRAM address
		addi.w	#(VSH_FilmArtA>>5)&$7FF,d2			; advance to buffer A film art
		moveq	#$05-1,d3					; set X size
		moveq	#$04-1,d4					; set Y size
		bsr.s	.DrawMaps					; draw film mappings

		addi.l	#$0B760000,d0					; advance to buffer B part of plane

		move.w	_VRAMRAW(a0),d2					; load relative VRAM address
		addi.w	#(VSH_FilmArtB>>5)&$7FF,d2			; advance to buffer A film art
		moveq	#$05-1,d3					; set X size
		moveq	#$04-1,d4					; set Y size
		bsr.s	.DrawMaps					; draw film mappings

	; --- Doing the BG monitor ---

		move.l	d1,d0						; load VDP address for monitor BG plane
		lea	.MonPlane(pc),a1				; load monitor plane list
		move.w	#$6000|((VSH_MonArt>>5)&$7FF),d2		; pattern index start
		bra.s	.Loop						; jump into the loop

	.DrawPiece:
		move.w	(a1)+,d4					; load Y size
		bsr.s	.DrawMaps					; draw film mappings

	.Loop:
		move.w	(a1)+,d3					; load X size
		bgt.s	.DrawPiece					; if it's an actual size, branch
		beq.s	.NoMore						; if finished, branch
		move.w	d3,(a6)						; set auto-increment mode
		moveq	#$00,d1						; load address advance
		move.w	(a1)+,d1					; ''
		swap	d1						; ''
		add.l	d1,d0						; advance address
		bra.s	.Loop						; repeat

	; --- Drawing mappings in sprite format

	.DrawMaps:
		move.l	d0,(a6)						; set VDP write mode address
		addi.l	#$00020000,d0					; advance to next column
		move.w	d4,d5						; load Y count

	.NextY:
		move.w	d2,(a5)						; save tile
		addq.w	#$01,d2						; increase ID for next tile
		dbf	d5,.NextY					; repeat for all rows
		dbf	d3,.DrawMaps					; repeat for all columns

	.NoMore:
		rts							; return

	.MonPlane:
		dc.w	4-1, 4-1			; X, Y
		dc.w	3-1, 4-1			; X, Y
		dc.w	$8F80, ($0200-$0E)		; reg, address add
		dc.w	4-1, 2-1			; X, Y
		dc.w	3-1, 2-1			; X, Y
		dc.w	$8F02, ($0100-$0A)		; reg, address add
		dc.w	3-1, 1-1			; X, Y
		dc.w	$0000				; reg, end of list

	endc

; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to decompress and load film data
; ---------------------------------------------------------------------------
; There's barely enough time to decompress all four films in a single frame
; (between Vblank A and B), since it just barely brushes lagging because
; of the monitor rendering too, I've split them into two films per frame.
; ---------------------------------------------------------------------------

	if LITE=0

	; --- First two films ---

LoadFilm_1_2:
		cmpi.b	#$02,(R_LogoFlag).w				; is the logo basically more or less loading in?
		bhs.w	.NoFilm						; if so DO NOT LOAD FILM

		lea	(R_Film_1).w,a2					; load film RAM
		lea	(R_FilmArt_1).w,a1				; load art address to decompress to
		leal	FilmList_AnyCols,a3				; set to use list which have monitor colours
		leal	Film_AnySlot,a4					; load shuffle available slots
		bsr.w	LoadFilm					; load the film correctly

	;	tst.b	(R_Intro).w					; the intro should only render one film in sequence (NOT RANDOMLY)
	;	bpl.s	.OneFilm					; so we skip the other three until later
	;	tst.b	(R_Skip).w					; force first skip as done
	;	smi.b	(R_Skip).w					; ''

		lea	(R_Film_2).w,a2					; load film RAM
		lea	(R_FilmArt_2).w,a1				; load art address to decompress to
		leal	FilmList_AnyCols,a3				; set to use list which have monitor colours
		leal	Film_AnySlot,a4					; load shuffle available slots
		bra.s	LoadFilm					; load the film correctly

	; --- Second two films ---

	.OneFilm:
		tst.b	(R_Skip).w					; has the player requested to skip?
		beq.w	FinishIntro					; if so, branch

	.NoFilm:
		rts							; return (no decompression)

LoadFilm_3_4:
		cmpi.b	#$02,(R_LogoFlag).w				; is the logo basically more or less loading in?
		bhs.w	.NoFilm						; if so DO NOT LOAD FILM

		tst.b	(R_Intro).w					; is the screen during the intro?
		bpl.s	.NoFilm						; if so, branch (only first film is active)
		lea	(R_Film_3).w,a2					; load film RAM
		lea	(R_FilmArt_3).w,a1				; load art address to decompress to
		leal	FilmList_AnyCols,a3				; set to use list which have monitor colours
		leal	Film_AnySlot,a4					; load shuffle available slots
		bsr.s	LoadFilm					; load the film correctly
		lea	(R_Film_4).w,a2					; load film RAM
		lea	(R_FilmArt_4).w,a1				; load art address to decompress to
		leal	FilmList_AnyCols,a3				; set to use list which have monitor colours
		leal	Film_MonOnly,a4					; load shuffle available slots
		bsr.s	LoadFilm					; load the film correctly

	.NoFilm:
		rts

; ---------------------------------------------------------------------------
; Loading of film
; ---------------------------------------------------------------------------

LoadFilm:
		subq.b	#$01,_Delay(a2)					; decrease delay timer
		bcs.s	.Ready						; if finished, branch
	; STATIC ANIMATION
		tst.b	_StatFilm(a2)					; have the game films started running yet?
		bne.s	.NoLoad						; if so, branch (only do animated static at the beginning)
		move.l	_FilmList(a2),d0				; load art list/address
		bne.w	.Continue					; if there is a list, branch
		leal	Film_1936,a3					; load static animation
		bra.w	.SetFrame					; set the static animation to run

	.NoLoad:
	; ----------------
		rts							; return

	.Ready:
	; STATIC ANIMATION
		tst.b	_StatFilm(a2)					; have the game films had the chance to load yet?
		bne.s	.NoFreshStart					; if so already, branch
		st.b	_StatFilm(a2)					; set as running game films now (no more static film)
		clr.l	_FilmList(a2)					; clear the film list (BRAND NEW SLATE/FILM TO LOAD!)

	.NoFreshStart:
	; ----------------
		sf.b	_Delay(a2)					; keep at 0
		move.l	_FilmList(a2),d0				; load art list/address
		bne.s	.Continue					; if there is a list, branch
		bra.s	.NewList					; continue into loop

	.NextList:
		move.b	#$03,_Delay(a2)					; set static delay

	.NewList:
		lea	(a3),a0						; copy list address
		moveq	#-1,d2						; clear list size

	.FindSize:
		addq.w	#$01,d2						; increase list size
		tst.l	(a0)+						; have we reached the end of the list yet?
		bpl.s	.FindSize					; if not, branch
		moveq	#$00,d0						; clear d0
		move.b	(R_Intro).w,d0					; load film render frame
		moveq	#$01,d1
		add.b	d0,d1
		not.b	(R_YearSlot).w					; swap the slot
		bpl.s	.Text2						; if this is the first slot, branch
		move.b	d1,(R_FilmNumber1).w				; saving film number (for text 1)
		bra.s	.Text1						; resume

	.Text2:
		move.b	d1,(R_FilmNumber2).w				; saving film number (for text 2)

	.Text1:
		move.b	d0,(R_YearNumber).w				; just in-case the render frame is FF, force year number to be FF
		bmi.s	.Random						; if negative, branch as it's meant to be random now
		leal	FilmYears,a0					; load year number
		move.b	(a0,d0.w),(R_YearNumber).w			; ''
		addq.b	#$01,(R_Intro).w				; increase frame ID
		cmp.b	d0,d2						; has it reached the end?
		bgt.s	.Render						; if not, branch

	.Skip:
		bsr.s	FinishIntro

	.Random:
		bsr.w	ShuffledFrame					; get a random number

	.Render:
	if EASTEREGG=1
	tst.b	(R_S1NXLFTW).w
	beq.s	.NoS1NXL
	moveq	#12,d0

	.NoS1NXL:
	endc
		move.b	d0,_FilmID(a2)					; store film ID
		add.w	d0,d0						; multiply by size of long-word
		add.w	d0,d0						; ''
		adda.l	(a3,d0.w),a3					; advance to correct film data

	.SetFrame:
		move.l	a3,_Palette(a2)					; store palette address
		lea	$20-2(a3),a3					; advance to film list
		move.l	a3,_FilmList(a2)				; set film list address
		move.l	a3,d0						; prepare address
		sf.b	_Frame(a2)					; reset frame ID

	.Continue:
		movea.l	d0,a0						; set address of list

		moveq	#$00,d0						; clear d0
		move.b	_Frame(a2),d0					; load frame ID
		addq.b	#$04,_Frame(a2)					; increase frame ID
		move.l	(a0,d0.w),d0					; load frame address
		bmi.w	.NextList					; if this is the end of the list, branch to find a new list
		adda.l	d0,a0						; advance to the actual art entry
		jmpl	KosSpeDec,a3					; decompress the art

FinishIntro:
		st.b	(R_Intro).w					; set to random now
		move.w	#$0080+52+(72*0),(R_FilmRend_1+_DestX).w	; set new monitor destination
		move.w	#$0080+57,(R_FilmRend_1+_DestY).w		; ''
		move.w	#$0080+52+(72*1),(R_FilmRend_2+_DestX).w	; set new monitor destination
		move.w	#$0080+57,(R_FilmRend_2+_DestY).w		; ''
		rts							; return

; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to collect the next frame randomly in a "shuffled" way
; This will ensure that the same frame isn't shown again until all frames
; have been shown within their respective constituencies.
; --- input -----------------------------------------------------------------
; a4.l = list of 00 and FF bytes to represent which slots the film can use (the second slot can only use certain films)
; d2.w = size of film list (should be 18)
; --- output ----------------------------------------------------------------
; d0.w = frame ID to use
; ---------------------------------------------------------------------------

ShuffledFrame:
		lea	(R_ShuffleList).w,a0				; load shuffle list
		bsr.w	RandomNumber					; get a random slot
		moveq	#$00,d0						; get only lower word (so DIVU is guarenteed)
		move.w	d1,d0						; ''
		divu.w	d2,d0						; keep within the list size
		swap	d0						; ''
		move.w	d0,d1						; store where we're starting
		moveq	#$00,d3						; clear upper bytes of d3

	.NextSlot:
		move.b	(a4,d0.w),d3					; check if the this film is allowed to use it
		or.b	(a0,d0.w),d3					; ...and check if it's taken
		beq.s	.FoundSlot					; if allowed and is not taken, branch
		addq.b	#$01,d0						; advance to next slot
		cmp.w	d2,d0						; have we reached the end of the list?
		bcs.s	.NoWrap						; if not, branch
		moveq	#$00,d0						; loop around from beginning again

	.NoWrap:
		cmp.w	d0,d1						; have we reached back where we started?
		bne.s	.NextSlot					; if not, branch

	.NextReset:
		tst.b	(a4,d0.w)					; is this film allowed to be used?
		bne.s	.Unavailable					; if not, branch
		tst.b	(a0,d0.w)					; is this film "in-used"?
		bmi.s	.Unavailable					; if so, cannot make it available...
		sf.b	(a0,d0.w)					; set it as free (it /was/ "used", but it's not "in-use" right now)
		move.b	d0,d3						; store free slot to use

	.Unavailable:
		addq.b	#$01,d0						; advance to next slot
		cmp.w	d2,d0						; have we reached the end of the list?
		bcs.s	.NoWrapReset					; if not, branch
		moveq	#$00,d0						; loop around from beginning again

	.NoWrapReset:
		cmp.w	d0,d1						; have we reached back where we started?
		bne.s	.NextReset					; if not, branch
		move.b	d3,d0						; load free slot we now found

	.FoundSlot:
		move.b	_FilmID(a2),d3					; set current film ID as "used" but not "in-use"
		move.b	#$01,(a0,d3.w)					; ''
		st.b	(a0,d0.w)					; set it as "in-use"
		rts							; return

	endc

; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to generate a random number (basically Sonic 1's...)
; ---------------------------------------------------------------------------

RandomNumber:
		move.l	(R_Random).w,d1
		bne.s	.NoSeed
		move.l	#$2A6D365A,d1

	.NoSeed:
		move.l	d1,d0
		asl.l	#2,d1
		add.l	d0,d1
		asl.l	#3,d1
		add.l	d0,d1
		move.w	d1,d0
		swap	d1
		add.w	d1,d0
		move.w	d0,d1
		swap	d1
		move.l	d1,(R_Random).w
		rts

; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to wait for (and run) V-blank - Part A (monitors/sprites)
; ---------------------------------------------------------------------------

VBlankA:
		move.w	(a6),ccr					; load status
		bmi.s	VBlankA						; if the VDP is in V-blank from a previous frame, branch and wait
	.Wait:	move.w	(a6),ccr					; load status
		bpl.s	.Wait						; if the VDP has not triggered V-blank yet, branch and wait

	; --- V-blank subroutine ---

	if LITE=0
		tst.b	(R_ClearNumbers).w				; are the numbers required to be cleared?
		beq.s	.ShowingNumbers					; if not, branch
		bmi.s	.PlaneCleared					; if the plane has already been cleared, branch
		move.l	#$8F019780,(a6)					; set increment mode and DMA mode
		move.l	#$940F9300,(a6)					; set DMA size ($F00)
		move.l	#$96009500,(a6)					; set DMA source (null for fill)
		move.l	#$40000080|(((VSH_NumberArt&$3FFF)<<$10)|((VSH_NumberArt>>$E)&3)),(a6) ; set DMA destination
		move.w	#$0000,(a5)					; set DMA fill value
		nop							; delay, give VDP time to set DMA status
		nop							; '' (probably not needed)
		move.w	(a6),ccr					; load status
		bvs.s	*-$02						; if the VDP DMA busy flag was set (bit 1), branch to wait til finished...
		move.w	#$8F02,(a6)					; set VDP increment mode back to normal
		ori.b	#$80,(R_ClearNumbers).w				; set plane as cleared

	.PlaneCleared:
		cmpi.b	#$02,(R_LogoFlag).w				; is the logo basically more or less loading in?
		bhs.w	.NoBuffer					; if so DO NOT DOUBLE BUFFER CHANGE VSCROLL (KEEP IT FIXED AT 0!)
		move.l	#$40000010,(a6)					; set VSRAM write mode
		move.w	#(VSH_PlaneA&$1F80)>>4,d0			; load plane position in VRAM
		tst.b	(R_Buffer).w					; swap buffer
		sne.b	d1						; set scroll to be where buffer A or B map tiles are depending on buffer flag
		andi.w	#$00B8,d1					; ''
		add.w	d1,d0						; ''
		move.w	d0,(a5)						; save to VSRAM

	.NoBuffer:

	.ShowingNumbers:
		jsr	MonitorArt(pc)					; render uncompressed monitor art
		jsr	MonitorSprites(pc)				; load monitor and film sprites

	endc

		jsr	MonitorPlaneB(pc)				; handle the static flicker for monitors that are on the plane, and logo control

		; Transfer palette to CRAM (done here to avoid colour dots on bottom boarder)

	;.WaitCRAM:
	;	move.w	$08(a5),d0
	;	subi.w	#$E000,d0
	;	cmpi.w	#$0800,d0
	;	blo.s	.WaitCRAM

		move.l	#$94009340,(a6)
		move.l	#$96009500|(((R_PalMain/2)&$FF00)<<8)|((R_PalMain/2)&$FF),(a6)
		move.l	#$9700C000|((R_PalMain/2)&$7F0000),(a6)
		move.w	#$0080,-(sp)
		move.w	(sp)+,(a6)

	if LITE=0

		jsr	FontText(pc)					; display the text under the year numbers

	endc

	; --- Standard stuff ---

		jsr	ProcessPLC(pc)					; process PLC entries
	if LITE=0
		jmp	ReadControls(pc)				; read controls
	endc

; ---------------------------------------------------------------------------
; Subroutine to wait for (and run) V-blank - Part B (the film textures)
; ---------------------------------------------------------------------------

	if LITE=0

VBlankB:
		move.w	(a6),ccr					; load status
		bmi.s	VBlankB						; if the VDP is in V-blank from a previous frame, branch and wait
	.Wait:	move.w	(a6),ccr					; load status
		bpl.s	.Wait						; if the VDP has not triggered V-blank yet, branch and wait

	; --- V-blank subroutine ---

		bsr.w	SendFilm					; render the film textures into VRAM with correct perspective (already decompressed into RAM)

	; --- Standard stuff ---

		jsr	ProcessPLC(pc)					; process PLC entries
	;	jmp	ReadControls(pc)				; read controls

	endc

; ---------------------------------------------------------------------------
; Subroutine to load control buttons
; ---------------------------------------------------------------------------
; d7.l = 1P1H2P2H
; ---------------------------------------------------------------------------

ReadControls:
		lea	($A10003).l,a0					; load control port A data address
		bsr.w	.ReadButtons					; read player 1 port
		addq.w	#$02,a0						; advance to player 2

	.ReadButtons:
		move.b	#%00000000,(a0)					; set TH to low
		swap	d7						; get player buttons
		moveq	#%00110000,d0					; get START and A button bits
		and.b	(a0),d0						; ''
		move.b	#%01000000,(a0)					; set TH to high
		add.b	d0,d0						; send START and A to MSB
		add.b	d0,d0						; ''
		moveq	#%00111111,d1					; get B, C, and D-pad button bits
		and.b	(a0),d1						; ''
		or.b	d1,d0						; fuse buttons together
		not.b	d0						; reverse button states (for XOR below)
		eor.b	d0,d7						; ''
		and.b	d0,d7						; get only the pressed buttons
		lsl.w	#$08,d7						; send pressed out the way
		move.b	d0,d7						; store held buttons
		rts							; return

; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to setup the palette ready for sending
; ---------------------------------------------------------------------------

SendPalette:
	if LITE=0
		bsr.w	GetPalettes					; load palettes (if any)
	endc
		move.b	(R_PalFadeMAST).w,d3				; load master palette fading
		cmp.b	(R_PalPrevMAST).w,d3				; has it changed?
		sne.b	d0						; set/clear if it has/hasn't
		bne.s	.NoMaster
		move.b	d3,(R_PalPrevMAST).w				; update previous

	.NoMaster:
		or.b	d0,d1						; save with updated flag
		lea	(R_Palette).w,a0				; load palette buffer
		lea	(R_PalMain).w,a1				; load main palette buffer
		move.b	(R_PalFade1).w,d0				; load current palette fading
		cmp.b	(R_PalPrev1).w,d0				; has the fading changed?
		bne.s	.Update1					; if so, branch
		tst.b	d1						; have any of the palettes updated?
		beq.s	.NoUpdate1					; if not, branch

	.Update1:
		move.b	d0,(R_PalPrev1).w				; update previous storage
		moveq	#$10-1,d6					; set number of colours to process
		bsr.s	.FadeLines					; fade the lines

	.NoUpdate1:

		lea	(R_Palette+$20).w,a0				; load palette buffer
		lea	(R_PalMain+$20).w,a1				; load main palette buffer
		move.b	(R_PalFade2).w,d0				; load current palette fading
		cmp.b	(R_PalPrev2).w,d0				; has the fading changed?
		bne.s	.Update2					; if so, branch
		tst.b	d1						; have any of the palettes updated?
		beq.s	.NoUpdate2					; if not, branch

	.Update2:
		move.b	d0,(R_PalPrev2).w				; update previous storage
		moveq	#$10-1,d6					; set number of colours to process
		bsr.s	.FadeLines					; fade the lines

	.NoUpdate2:

		lea	(R_Palette+$40).w,a0				; load palette buffer
		lea	(R_PalMain+$40).w,a1				; load main palette buffer
		move.b	(R_PalFade3).w,d0				; load current palette fading
		cmp.b	(R_PalPrev3).w,d0				; has the fading changed?
		bne.s	.Update3					; if so, branch
		tst.b	d1						; have any of the palettes updated?
		beq.s	.NoUpdate3					; if not, branch

	.Update3:
		move.b	d0,(R_PalPrev3).w				; update previous storage
		moveq	#$10-1,d6					; set number of colours to process
		bsr.s	.FadeLines					; fade the lines

	.NoUpdate3:

		lea	(R_Palette+$6E).w,a0				; load palette buffer
		lea	(R_PalMain+$6E).w,a1				; load main palette buffer
		move.b	(R_PalFade4).w,d0				; load current palette fading
		cmp.b	(R_PalPrev4).w,d0				; has the fading changed?
		bne.s	.Update4					; if so, branch
		tst.b	d1						; have any of the palettes updated?
		beq.s	.NoUpdate4					; if not, branch

	.Update4:
		move.b	d0,(R_PalPrev4).w				; update previous storage
		moveq	#$09-1,d6					; set number of colours to process
		bsr.s	.FadeLines					; fade the lines

	.NoUpdate4:
		lea	(R_Palette+$60).w,a0				; load palette buffer
		lea	(R_PalMain+$60).w,a1				; load main palette buffer
		move.b	(R_PalFadeMon).w,d0				; load current palette fading
		cmp.b	(R_PalPrevMon).w,d0				; has the fading changed?
		bne.s	.UpdateMon					; if so, branch
		tst.b	d1						; have any of the palettes updated?
		beq.s	.NoUpdateMon					; if not, branch

	.UpdateMon:
		move.b	d0,(R_PalPrevMon).w				; update previous storage
		moveq	#$07-1,d6					; set number of colours to process

	.FadeLines:
		add.b	d3,d0
		moveq	#$10,d5						; load palette fading amount
		sub.b	d0,d5						; ''
		bpl.s	.LineOK						; if it's not gone past darkest, branch
		moveq	#$00,d5						; keep at darkest

	.LineOK:
		moveq	#$00,d0						; clear upper byte
		cmpi.b	#$10,d5						; has it surpassed maximum?
		bls.s	.FadeLines2					; if not, branch
		moveq	#$10,d5						; keep at lighest

	.FadeLines2:

	.NextColour:
		move.b	(a0)+,d0					; load blue
		mulu.w	d5,d0						; convert palette
		lsr.w	#$04,d0						; ''
		move.b	d0,(a1)+					; save blue
		move.b	(a0)+,d0					; load green and red
		moveq	#$FFFFFFE0,d2					; load green
		and.w	d0,d2						; ''
		mulu.w	d5,d2						; convert green
		lsr.w	#$04,d2						; ''
		andi.w	#$00E0,d2					; ''
		andi.w	#$000E,d0					; convert red
		mulu.w	d5,d0						; ''
		lsr.w	#$04,d0						; ''
		or.b	d2,d0						; fuse red and green together
		move.b	d0,(a1)+					; save red and greeen
		dbf	d6,.NextColour					; repeat for all colours

	.NoUpdateMon:
		rts							; return

; ---------------------------------------------------------------------------
; Loading the palettes
; ---------------------------------------------------------------------------

	if LITE=0

GetPalettes:
		cmpi.b	#$02,(R_LogoFlag).w				; is the logo basically more or less loading in?
		bhs.w	.NoPalette					; if so DO NOT GET PALETTES FROM FILM

		tst.b	(R_LogoOrder).w					; is the first film already swapped to SHC logo?
		bne.s	.SkipLine1					; if so, don't load film palette for this line

		lea	(R_Palette+$02).w,a1				; load palette buffer
		lea	(R_Film_1+_Palette).w,a0			; palette address
		bsr.s	.DoPal						; transfer line 1

	.SkipLine1:
		lea	(R_Palette+$22).w,a1				; load palette buffer
		lea	(R_Film_2+_Palette).w,a0			; palette address
		bsr.s	.DoPal						; transfer line 2

		tst.b	(R_ClearNumbers).w				; have the numbers been cleared?
		beq.s	.NoPalette					; if not, ignore lines 2 and 4 (using them for numbers)

		lea	(R_Palette+$42).w,a1				; load palette buffer
		lea	(R_Film_3+_Palette).w,a0			; palette address
		bsr.s	.DoPal						; transfer line 3

		lea	(R_Palette+$6E).w,a1				; load palette buffer
		lea	(R_Film_4+_Palette).w,a0			; palette address
									; transfer line 4

	.DoPal_Small:
		move.l	(a0),d0						; load palette address
		beq.s	.NoPalette					; if no palette was requested, branch
		st.b	d1						; mark as an update has occurred
		clr.l	(a0)						; clear palette
		movea.l	d0,a0						; set address
		lea	$0C(a0),a0					; advance to main colours (skip monitor colours)
		move.w	(a0)+,(a1)+					; copy palette line
		move.l	(a0)+,(a1)+					; ''
		move.l	(a0)+,(a1)+					; ''
		move.l	(a0)+,(a1)+					; ''
		move.l	(a0)+,(a1)+					; ''

	.NoPalette:
		rts							; return

	.DoPal:
		move.l	(a0),d0						; load palette address
		beq.s	.NoPalette					; if no palette was requested, branch
		st.b	d1						; mark as an update has occurred
		clr.l	(a0)						; clear palette
		movea.l	d0,a0						; set address
		move.w	(a0)+,(a1)+					; copy palette line
		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)+					; ''
		rts							; return

	endc

; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to render the film in the right shape
; ---------------------------------------------------------------------------

	if LITE=0

SendFilm:
		cmpi.b	#$02,(R_LogoFlag).w				; is the logo basically more or less loading in?
		bhs.w	.NoFilm						; if so DO NOT SEND FILM ART

		move.w	#(VSH_FilmArtA>>5)&$7FF,d5			; prepare pattern index address for buffer A
		move.l	#$40000000|(((VSH_FilmArtA&$3FFF)<<$10)|((VSH_FilmArtA>>$E)&3)),d4 ; prepare buffer A VRAM
		not.b	(R_Buffer).w					; swap buffer
		beq.s	.BufferA					; if we're writing to buffer A now, branch
		move.w	#(VSH_FilmArtB>>5)&$7FF,d5			; prepare pattern index address for buffer B
		move.l	#$40000000|(((VSH_FilmArtB&$3FFF)<<$10)|((VSH_FilmArtB>>$E)&3)),d4 ; prepare buffer B VRAM instead

	.BufferA:
		lea	(R_FilmRend).w,a1				; load render object
		moveq	#12-1,d6					; number of render object slots available
		move.l	#$00FFFFFF,d1					; prepare registers for rendering
		moveq	#$00,d2						; ''

	.NextObject:
		moveq	#$00,d0						; clear d0
		move.b	_Scale(a1),d0					; load scale ID
		bpl.s	.Valid						; if it's not FF (drawn to the plane), branch
		move.b	#((MonMap_End-MonMap)/2)-1,d0			; set as being on last frame instead
		cmpi.b	#(12-4)-1,d6					; have we reached one of the 8 non-permanent frames?
		bls.s	.NullSprite					; if so, branch (only render the first four frames if they're on plane)

	.Valid:
		subi.w	#((MonMap_End-MonMap)-((MapFilm_End-MapFilm)/2))/2,d0 ; is it displaying a frame that renders nothing?
		bcs.s	.NullSprite					; if so, branch
		add.w	d0,d0						; multiply by size of long-word
		add.w	d0,d0						; ''
		leal	RenderFilm,a2					; load film rendering routines
		adda.l	(a2,d0.w),a2					; advance to correct render routine
		move.l	d4,d0						; convert VDP long-word to pattern index
		swap	d0						; ''
		lsl.w	#$02,d0						; ''
		lsr.l	#$02,d0						; ''
		lsr.w	#$05,d0						; ''
		or.w	_Pal(a1),d0					; add palette ID to it
		move.w	d0,_VRAM(a1)					; save VRAM for sprite rendering next frame
		sub.w	d5,d0						; get relative to 0 address
		move.w	d0,_VRAMRAW(a1)					; store raw address for map rendering
		movea.w	_ArtBuff(a1),a0					; set art buffer address where the film is
		move.l	d4,(a6)						; set VDP write mode
		jsr	(a2)						; run rendering routines

	.NullSprite:
		lea	_FilmRend(a1),a1				; advance to next render object
		dbf	d6,.NextObject					; repeat for all object slots

	.NoFilm:
		rts							; return

	endc

; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to transfer uncompressed monitor art to VRAM
; ---------------------------------------------------------------------------

	if LITE=0

MonitorArt:
		cmpi.b	#$02,(R_LogoFlag).w				; is the logo basically more or less loading in?
		bhs.w	.NoMonArt					; if so DO NOT RENDER MONITOR ART

		lea	(R_FilmRend).w,a1				; load render object
		moveq	#12-1,d2					; number of render object slots available

	; --- TEMP FONT ART OVERWRITING PREVENTION ---
		tst.b	(R_PalNumber).w					; since the font fits inside the dynamic monitor area, I do NOT want the 3rd monitor and onwards to render during the intro section
		bmi.s	.NoIntro					; so branch if we're NOT in the intro...
		moveq	#2-1,d2						; ...otherwise only allow the first two monitors to render, and once they're done, we can use their VRAM space for font art temporarily.

	.NoIntro:
	; --------------------------------------------

	.NextObject:
		moveq	#$00,d0						; clear d0
		move.b	_Scale(a1),d0					; load scale ID
		bmi.s	.NextSlot					; if this object has rendered to plane, branch
		add.w	d0,d0						; advance to size of long-word
		add.w	d0,d0						; ''
		leal	MonArt,a0					; load monitor art address
		move.l	$04(a0,d0.w),d1					; load end address
		bgt.s	.DrawArt					; if the slot is not empty, branch

	.NextSlot:
		lea	_FilmRend(a1),a1				; advance to next render object
		dbf	d2,.NextObject					; repeat for all object slots
		rts							; return

	.DrawArt:
		move.l	#$94009300,-(sp)				; prepare DMA registers
		move.l	#$96009500,-(sp)				; ''
		move.w	#$9700,-(sp)					; ''
		move.l	(a0,d0.w),d0					; load start address
		add.l	a0,d0						; advance to absolute address
		add.l	a0,d1						; ''
		move.l	d0,d2						; get source divided by size of word
		lsr.l	#$01,d2						; ''
		movep.l	d2,-$01(sp)					; save with DMA source registers
		move.l	(sp)+,(a6)					; set DMA source
		move.w	(sp)+,(a6)					; ''
		moveq	#$3E,d2						; prepare boundary size
		swap	d2						; ''
		move.l	d1,d3						; get end address boundary
		and.l	d2,d3						; ''
		and.l	d0,d2						; get start address boundary
		cmp.l	d2,d3						; check if they're the same boundary
		move.w	sr,-(sp)	; want to avoid using more regs	; store conditions
		move.l	#$40200000|VSH_MonDyn,d2			; DMA destination bits
		move.w	(sp)+,sr	; want to avoid using more regs	; restore conditions
		beq.s	.Single						; if so, branch
		move.l	d3,d4		; ended up using another register anyways....  pfft fuck it... ; store next window's address for later
		sub.l	d3,d1						; get size of second part
		sub.l	d0,d3						; get size of first part
		move.l	d2,d0						; load DMA destination
		add.w	d3,d2						; advance destination for NEXT part
		lsr.w	#$01,d3						; divide size for DMA
		movep.w	d3,$01(sp)					; save with DMA size registers
		move.l	(sp),(a6)					; set DMA size
		rol.l	#$02,d0						; align DMA destination for VDP port
		ror.w	#$02,d0						; ''
		move.w	d0,(a6)						; set first DMA destination
		swap	d0						; set final DMA destination (must be from 68k RAM)
		move.w	d0,-(sp)					; ''
		move.w	(sp)+,(a6)					; ''
		moveq	#$00,d0						; clear d0

		; Update 97 only (DMA will only update 95 and 96 hence
		; why it won't cross a window of 20000).

		swap	d4						; get the upper byte address
		lsr.b	#$01,d4						; ''
		move.w	#$9700,-(sp)					; reassert 97 again (ugh...)
		move.b	d4,$01(sp)					; ''
		move.w	(sp)+,(a6)					; ''

	.Single:
		sub.l	d0,d1						; get size of art
		lsr.w	#$01,d1						; divide size for DMA
		movep.w	d1,$01(sp)					; save with DMA size registers
		move.l	(sp)+,(a6)					; set DMA size
		rol.l	#$02,d2						; align DMA destination for VDP port
		ror.w	#$02,d2						; ''
		move.w	d2,(a6)						; set first DMA destination
		swap	d2						; set final DMA destination (must be from 68k RAM)
		move.w	d2,-(sp)					; ''
		move.w	(sp)+,(a6)					; ''

	.NoMonArt:
		rts							; return

	endc

; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to render monitor sprites as they're animating graphics
; ---------------------------------------------------------------------------

	if LITE=0

MonitorSprites:
		cmpi.b	#$02,(R_LogoFlag).w				; is the logo basically more or less loading in?
		bhs.w	.NoSprites					; if so DO NOT RENDER SPRITES

		move.l	#$40000000|(((VSH_Sprite&$3FFF)<<$10)|((VSH_Sprite>>$E)&3)),(a6) ; set VDP to sprite table buffer
		moveq	#$00,d2						; reset link ID

	; --- Monitor and film ---

		lea	(R_FilmRend).w,a1				; load render object
		moveq	#12-1,d4					; number of render object slots available
		moveq	#$02-1,d5					; number of monitors/film sprites to display at once

	.NextObject:
		moveq	#$00,d0						; load scale
		move.b	_Scale(a1),d0					; ''
		bmi.s	.SkipObject					; if it's now rendered on a plane instead, branch
		add.w	d0,d0						; multiply by size of word
		lea	MonMap(pc),a3					; load monitor mappings
		adda.w	(a3,d0.w),a3					; advance to correct sprite list
		lea	NullSprite(pc),a2				; load null sprite for no film
		move.w	_FilmParent(a1),a4				; load parent film
	; STATIC ANIMATION
		tst.b	_StatFilm(a4)					; is this is the initial static film?
		beq.s	.Film						; if so, branch
	; ----------------
		tst.b	_Delay(a4)					; has static delay been set?
		bne.s	.NoFilm						; if so, skip rendering the film (shows static)

	.Film:
		subi.w	#((MonMap_End-MonMap)-((MapFilm_End-MapFilm)/2)),d0 ; minus starting frames which have no film
		bcs.s	.NoFilm						; if there's no film to display, branch
		add.w	d0,d0						; multiply to size of long-word
		leal	MapFilm,a2					; load monitor mappings
		adda.l	(a2,d0.w),a2					; advance to correct sprite list

	.NoFilm:
		swap	d2						; preserve link ID
		move.w	_PosY(a1),d2					; load Y position
		swap	d2						; realign
		move.l	_PosX(a1),d1					; load X position
		move.w	_VRAM(a1),d1					; load main index

		lea	(a2),a0						; load film sprites first
		bsr.w	DrawSprites					; ''
		move.w	#$6000|(VSH_MonDyn/$20),d1			; load dynamic monitor art address (if the sprite is using static, it doesn't matter, all is handled)
		lea	(a3),a0						; load monitor sprite mappings
		bsr.w	DrawSprites					; draw the monitor
		dbf	d5,.SkipObject					; repeat for two monitors
		bra.s	.CheckNumber					; continue

	.SkipObject:
		lea	_FilmRend(a1),a1				; advance to next render object
		dbf	d4,.NextObject					; repeat for all object slots

	; --- Year numbers ---

	.CheckNumber:
		tst.b	(R_ClearNumbers).w				; are numbers displaying?
		bne.w	.NoNumbers					; if not, branch

		move.w	#$4000,d6
		tst.b	(R_YearSlot).w
		bmi.s	.NoSwapPalette
		move.w	#$4000+$2000,d6

	.NoSwapPalette:
		addi.w	#(VSH_NumberArt>>5),d6				; add pattern index address

		move.w	#$2000,d0					; start from the year 2000
		move.b	(R_YearCur).w,d0				; load current year
		beq.s	.NoYear1st					; if no year has been set, branch
		swap	d2						; store link ID
		move.w	#$0080+14,d2					; set Y position
		swap	d2						; set up
		ext.w	d2						; clear shape
		ori.w	#$0E00,d2					; force shape to number sprite shape
		move.w	#$0080+152,d1					; set starting X position
		bsr.s	.DrawNumbers					; draw the year

	.NoYear1st:
		tst.b	(R_YearNumber).w
		bmi.s	.LastYear
		eori.w	#$2000,d6					; swap palette line

	.LastYear:
		move.w	#$2000,d0					; start from the year 2000
		move.b	(R_YearCur2).w,d0				; load current year
		beq.s	.NoYear2nd					; if no year has been set, branch
		swap	d2						; store link ID
		move.w	#$0080+120,d2					; set Y position
		swap	d2						; set up
		ext.w	d2						; clear shape
		ori.w	#$0E00,d2					; force shape to number sprite shape
		move.w	#$0080+54,d1					; set starting X position
		bsr.s	.DrawNumbers					; draw the year

	.NoYear2nd:
		bra.s	.NoChange

	.NoNumbers:
		bset.b	#$07,(R_PalNumber).w				; set years as finished
		bne.s	.NoChange					; if already set, branch
		sf.b	(R_PalFade3).w					; force fading not to occur
		sf.b	(R_PalFade4).w					; ''

	.NoChange:
		moveq	#$00,d0						; clear last sprite
		move.l	d0,(a5)						; ''
		rts							; return

	.DrawNumbers:
		moveq	#$04-1,d5					; four digits to render

	.NextNumber:
		addq.b	#$01,d2						; increase link ID
		move.l	d2,(a5)						; save Y pos and link ID to sprite table
		rol.w	#$04,d0						; get digit
		moveq	#$0F,d3						; ''
		and.w	d0,d3						; ''
		add.w	d3,d3						; multiply by C
		add.w	d3,d3						; ''
		move.w	d3,d4						; ''
		add.w	d4,d3						; ''
		add.w	d4,d3						; ''
		add.w	d6,d3						; add pattern index address
		move.w	d3,(a5)						; save pattern index
		move.w	d1,(a5)						; save X position
		addi.w	#$1C,d1						; move right
		dbf	d5,.NextNumber					; repeat for all number digits
		rts							; return

	.NoSprites:
		rts							; return

NullSprite:	dc.w	$0000

; ---------------------------------------------------------------------------
; Subroutine to draw sprites directly to VRAM
; ---------------------------------------------------------------------------
; d1.l	= XXXXPPPP
; d2.l	= YYYY00LL
; ---------------------------------------------------------------------------

DrawSprites:
		moveq	#-1,d3						; load number of pieces minus 1 for dbf
		add.w	(a0)+,d3					; load number of pieces
		bcc.s	.NoPieces					; if there are no pieces, branch

		tst.b	_Mirror(a1)					; is the monitor mirrored?
		bne.s	.MirrorPiece					; if so, branch

	; --- Normal version ---

	; sprite format:	YYYY 0S00 XXXX PPPP

	.NextPiece:
		move.l	(a0)+,d0					; load Y position and shape
		addq.b	#$01,d2						; increase link ID
		add.l	d2,d0						; add Y central and link ID
		move.l	d0,(a5)						; save to sprite table
		move.l	(a0)+,d0					; load X position and pattern index
		add.l	d1,d0						; add X central and main index
		swap	d0						; align for sprite table
		move.l	d0,(a5)						; save to sprite table
		dbf	d3,.NextPiece					; repeat for all piece

	.NoPieces:
		rts							; return

	; --- Mirror version ---

	.MirrorPiece:
		move.l	d4,-(sp)					; store d4 for now

	.Next:
		move.l	(a0)+,d0					; load Y position and shape
		addq.b	#$01,d2						; increase link ID
		add.l	d2,d0						; add Y central and link ID
		move.l	d0,(a5)						; save to sprite table
		move.l	(a0)+,d0					; load X position and pattern index
	swap	d0
	neg.w	d0
	moveq	#$00,d4
	move.b	-$06(a0),d4
	add.w	d4,d4
	add.w	.MirrX(pc,d4.w),d0
	swap	d0
		add.l	d1,d0						; add X central and main index
	eori.w	#$0800,d0
		swap	d0						; align for sprite table
		move.l	d0,(a5)						; save to sprite table
		dbf	d3,.Next					; repeat for all piece
		move.l	(sp)+,d4					; restore d4
		rts							; return

	.MirrX:	dc.w	-$0008,-$0008,-$0008,-$0008
		dc.w	-$0010,-$0010,-$0010,-$0010
		dc.w	-$0018,-$0018,-$0018,-$0018
		dc.w	-$0020,-$0020,-$0020,-$0020

	endc

; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to render font text
; ---------------------------------------------------------------------------

	if LITE=0

FontText:
		bclr.b	#$07,(R_UpdateText).w				; clear flag
		bne.s	.Update						; if it was set, branch
		rts							; return (no update)

	.Update:
		move.l	#(($6000|(VSH_MonDyn>>5))<<$10)|($6000|(VSH_MonDyn>>5)),d1 ; prepare tile index adding
		tst.b	(R_YearSlot).w					; are we rendering second slot?
		bpl.s	.NoSwapPal					; if not, branch
		eori.l	#$20002000,d1					; swap the palette line

	.NoSwapPal:

		moveq	#$00,d0						; load film ID
		move.b	(R_FilmCurrent1).w,d0				; ''
	if EASTEREGG=1
	tst.b	(R_S1NXLFTW).w
	beq.s	.NoS1NXL1
	moveq	#13,d0

	.NoS1NXL1:
	endc
		tst.b	(R_ClearNumbers).w				; force ID to 0 if clear numbers has been set
		seq.b	d2						; ''
		and.b	d2,d0						; ''
		add.w	d0,d0						; multiply by sizeof word
		leal	FilmText,a0					; load film text list
		adda.w	(a0,d0.w),a0					; advance to correct frame
		move.l	#$431C0000+(((VSH_PlaneB&$3FFF)<<$10)|((VSH_PlaneB>>$E)&3)),d2 ; prepare VDP plane address
		bsr.s	DrawText					; draw the text


		tst.b	(R_YearNumber).w
		bmi.s	.LastYear
		eori.l	#$20002000,d1					; swap palette line

	.LastYear:
		moveq	#$00,d0						; load film ID
		move.b	(R_FilmCurrent2).w,d0				; ''
	if EASTEREGG=1
	tst.b	(R_S1NXLFTW).w
	beq.s	.NoS1NXL2
	moveq	#13,d0

	.NoS1NXL2:
	endc
		tst.b	(R_ClearNumbers).w				; force ID to 0 if clear numbers has been set
		seq.b	d2						; ''
		and.b	d2,d0						; ''
		add.w	d0,d0						; multiply by sizeof word
		leal	FilmText,a0					; load film text list
		adda.w	(a0,d0.w),a0					; advance to correct frame
		move.l	#$49820000+(((VSH_PlaneB&$3FFF)<<$10)|((VSH_PlaneB>>$E)&3)),d2 ; prepare VDP plane address

	; --- The text rendering itself ---

DrawText:
		leal	MapFont,a1					; load font mappings to use
		move.w	#$8F80,(a6)					; set auto-increment to a row's worth
		moveq	#$00,d5						; clear d5 (blank tile)
		bra.s	.SingleLine					; jump into the loop

	.NewLine:
		subq.w	#$01,d4						; decrease line counter for dbf
		bmi.s	.EndOfLine					; if finished, branch

	.ClearLine:
		move.l	d3,(a6)						; set VDP write address
		addi.l	#$00020000,d3					; move right for next column
		move.l	d5,(a5)						; clear a column
		dbf	d4,.ClearLine					; repeat for rest of line

	.EndOfLine:
		addi.l	#$00800000,d2					; advance to next line
		add.b	d0,d0						; is it a single line?
		bmi.s	.SingleLine					; if not, branch for double line
		addi.l	#$00800000,d2					; advance to next line

	.SingleLine:
		moveq	#$1E,d4						; line counter
		move.l	d2,d3						; set next address

	.Start:
		move.b	(a0)+,d0					; load character
		bmi.s	.EndCheck					; if it's the end of a line or end of a string, branch

	.Letter:
		bne.s	.NoSpace					; if it's not a space character, branch
		lea	(a1),a2						; load mappings for space character
		bra.s	.SecondCol					; jump and do only 1 column instead of 2

	.NoSpace:
		lsl.w	#$03,d0						; multiply to size of a letter's mappings
		lea	(a1,d0.w),a2					; load correct font mapping

	.FirstCol:
		move.l	d3,(a6)						; set VDP write address
		addi.l	#$00020000,d3					; move right for next column
		move.l	(a2)+,d0					; load tiles
		add.l	d1,d0						; advance to correct VRAM address
		move.l	d0,(a5)						; save to plane
		subq.w	#$01,d4						; decrease tile count

	.SecondCol:
		move.l	d3,(a6)						; set VDP write address
		addi.l	#$00020000,d3					; move right for next column
		move.l	(a2)+,d0					; load tiles
		add.l	d1,d0						; advance to correct VRAM address
		move.l	d0,(a5)						; save to plane
		subq.w	#$01,d4						; decrease tile count

		moveq	#$00,d0						; clear upper byte
		move.b	(a0)+,d0					; load next character
		bpl.s	.Letter						; if it's NOT and end of line or string, branch

	.EndCheck:
		add.b	d0,d0						; is it the end of a line?
		bpl.s	.NewLine					; if so, branch for new line
		move.w	#$8F02,(a6)					; reset auto-increment
		rts							; return

	endc

; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to control plane B in various ways
; ---------------------------------------------------------------------------

MonitorPlaneB:
		moveq	#$00,d0						; clear d0
		move.b	(R_LogoFlag).w,d0				; load flag/mode
		add.w	d0,d0						; multiply by size-of word
		move.w	PB_Rout(pc,d0.w),d0				; load correct relative routine
		jmp	PB_Rout(pc,d0.w)				; add and jump

	; --- routine sequence ---

PB_Rout:	dc.w	StaticMons-PB_Rout				; 00
		dc.w	StaticMon2-PB_Rout				; 01
		dc.w	RenderLogo-PB_Rout				; 02
		dc.w	FadeLogoIn-PB_Rout				; 03
		dc.w	FadeLite-PB_Rout				; 04
		dc.w	FlickerHead-PB_Rout				; 05
		dc.w	DUMMYSLOT-PB_Rout				; 06
		dc.w	DUMMYSLOT-PB_Rout				; 07

		dc.w	PrematurePLC-PB_Rout				; 08

PrematurePLC:
		jsr	TestLong0(pc)					; check PLC list address
		bne.s	DUMMYSLOT					; if there are lists to decompress, branch
		move.b	#$02,(R_LogoFlag).w				; set to run normal sequence now
		move.b	#$10,(R_PalFade1).w
		move.b	#$10,(R_PalFade2).w
		move.b	#$10,(R_PalFade3).w
		move.b	#$10,(R_PalFade4).w
		move.b	#$10,(R_PalFadeMon).w
		sf.b	(R_PalFadeMAST).w
		move.w	#$8500|((($0000)>>$09)&$FF),(a6)		; force sprite table to be at 0 from now on
		move.l	#$40000000,(a6)					; need to write the first long-word because a copy will...
		move.l	#$00000000,(a5)					; '' ...not transfer to cache from simple register change

	; --- clear plane B ---

		move.l	#$8F019780,(a6)					; set increment mode and DMA mode
		move.l	#$941F93FF,(a6)					; set DMA size
		move.l	#$96009500,(a6)					; set DMA source (null for fill)
		move.l	#$40000080|(((VSH_PlaneB&$3FFF)<<$10)|((VSH_PlaneB>>$E)&3)),(a6) ; set DMA destination
		move.w	#$000,(a5)					; set DMA fill value
		nop							; delay, give VDP time to set DMA status
		nop							; '' (probably not needed)
		move.w	(a6),ccr					; load status
		bvs.s	*-$02						; if the VDP DMA busy flag was set (bit 1), branch to wait til finished...
		move.w	#$8F02,(a6)					; set VDP increment mode back to normal

DUMMYSLOT:
		rts							; return

; ---------------------------------------------------------------------------
; causing the head neon to flicker
; ---------------------------------------------------------------------------
FLICKERSPEED	=	$60	; must be component of 2 (2, 4, 8, $10, $20, etc...)
; ---------------------------------------------------------------------------

FlickerHead:
		addq.w	#$01,(R_FlickerTimer).w				; increase flickering timer
		moveq	#$02,d0						; set to show the final text only frame
		move.w	(R_FlickerTimer).w,d1				; load the timer
		cmpi.w	#FLICKERSPEED*5,d1				; have we finished?
		blt.s	.NoFinish					; if not, branch
		st.b	(R_Skip).w					; FORCE SCREEN TO FINISH NOW

	.NoFinish:

	if LITE=1

		cmpi.w	#-FLICKERSPEED,d1
		blt.s	.NoFlicker
		tst.w	d1
		bmi.s	.Flicker

	endc

		cmpi.w	#FLICKERSPEED*4,d1				; have we reached text only part?
		bge.s	.NoFlicker					; if not, branch
		moveq	#$00,d0						; set to show text and non-faded head frame
		divs.w	#FLICKERSPEED,d1				; divide into parts
		andi.w	#$0001,d1					; are we on a flickering part?
		beq.s	.NoFlicker					; if not, branch

	.Flicker:
		jsr	RandomNumber(pc)				; load a random frame for flickering

	.NoFlicker:

	; --- The actual logo display itself ---

DisplayLogo:
		andi.w	#$0003,d0					; keep within the table
		add.w	d0,d0						; multiply by sizeof table entry
		add.w	d0,d0						; '' (long-word)
		lea	DisplayList(pc,d0.w),a0				; load correct flicker data
		move.w	(a0)+,(a6)					; set either text only or not
		move.l	#$40000010,(a6)					; set VDP VSRAM write mode
		move.w	(a0)+,(a5)					; set either faded or non-faded head
		rts							; return

DisplayList:	dc.w	$9100,$0000					; Text and non-faded Head
		dc.w	$9100,$00E0					; Text and faded head
		dc.w	$911C,$0000					; Text Only
		dc.w	$9100,$0000	; only here in-case of accident	; Text Only

; ---------------------------------------------------------------------------
; fading the logo in for "lite" version only
; ---------------------------------------------------------------------------

FadeLite:

	if LITE=1

		subq.b	#$01,(R_PalFade2).w				; fade palette in
		bcc.s	.NoFinishFade					; if still fading, branch
		sf.b	(R_PalFade2).w					; keep at 0
		addq.b	#$01,(R_LogoFlag).w				; advance to next routine
		move.w	#-FLICKERSPEED*2,(R_FlickerTimer).w		; set to start as non-flicker

	.NoFinishFade:

	else
		addq.b	#$01,(R_LogoFlag).w				; advance to next routine

	endc

		rts							; return

; ---------------------------------------------------------------------------
; fading the logo in
; ---------------------------------------------------------------------------

FadeLogoIn:

	if LITE=0

		subq.b	#$01,(R_PalFade2).w				; fade palette in
	;	bcc.s	.NoFinishFade					; if still fading, branch
	cmpi.b	#$FE,(R_PalFade2).w				; waiting for FF is not enough, needs one more frame...
	bge.s	.NoFinishFade					; if still fading, branch

		sf.b	(R_PalFade2).w					; keep at 0

	else

		move.w	#$911C,(a6)					; hide the head

	endc

	; --- Loading plane B ---

		move.w	#VSH_LogoPlane+(2*($50*$1C)),d1			; prepare VDP source map buffer
		move.l	#$400000C0|(((VSH_PlaneB&$3FFF)<<$10)|((VSH_PlaneB>>$E)&3)),d0 ; prepare VDP plane address
		moveq	#$1C-1,d2					; number of rows
		bsr.s	TransLogo					; transfer the BG mappings now

	; --- Clearing window space ---
	; Window can be used to mask plane A to show a third
	; frame (on plane B) =3
	; -----------------------------

		move.l	#$8F019780,(a6)					; set increment mode and DMA mode
		move.l	#$941F93FF,(a6)					; set DMA size
		move.l	#$96009500,(a6)					; set DMA source (null for fill)
		move.l	#$40000080|(((VSH_Window&$3FFF)<<$10)|((VSH_Window>>$E)&3)),(a6) ; set DMA destination
		move.w	#$000,(a5)					; set DMA fill value
		nop							; delay, give VDP time to set DMA status
		nop							; '' (probably not needed)
		move.w	(a6),ccr					; load status
		bvs.s	*-$02						; if the VDP DMA busy flag was set (bit 1), branch to wait til finished...
		move.w	#$8F02,(a6)					; set VDP increment mode back to normal

	.NoFinishFade:
		rts							; return

; ---------------------------------------------------------------------------
; rendering the logo correctly
; ---------------------------------------------------------------------------

RenderLogo:

	; --- Loading palette ---

		lea	(R_Palette+$22).w,a1				; load palette buffer
		leal	LogoPalette,a0					; load logo's palette
		moveq	#((LogoPalette_End-LogoPalette)/2)-1,d0		; size of palette

	.LoadLogoPal:
		move.w	(a0)+,(a1)+					; copy colours across
		dbf	d0,.LoadLogoPal					; repeat for all palette colours

	; --- load V-scroll position ---

		move.l	#$40000010,(a6)					; set VSRAM write mode
		move.w	#$0000,(a5)					; force plane A to non-double buffer position now

	; --- Loading plane mappings ---

		move.w	#VSH_LogoPlane,d1				; prepare VDP source map buffer
		move.l	#$400000C0|(((VSH_PlaneA&$2000)<<$10)|((VSH_PlaneA>>$E)&3)),d0 ; prepare VDP plane address
		moveq	#($1C*2)-1,d2					; number of rows

TransLogo:
		move.l	#$8F019400,(a6)					; set auto-increment for DMA copy, and upper byte of size will always be 0
		move.l	#$96009500,-(sp)				; prepare source registers

	.NextRowLogo:
		move.l	#$97C09350,(a6)					; set DMA source (DMA copy) and DMA lower byte size
		movep.w	d1,$01(sp)					; set DMA source address
		move.l	(sp),(a6)					; ''
		move.l	d0,(a6)						; set DMA destination
		addi.l	#$00800000,d0					; advance to next row in destination
		addi.w	#$0050,d1					; advance to next row in source
	.Copy:	move.w	(a6),ccr					; load VDP status
		bvs.s	.Copy						; if VDP is still performing a DMA copy, branch
		dbf	d2,.NextRowLogo					; repeat for all rows
		addq.w	#$04,sp						; restore stack
		move.w	#$8F02,(a6)					; restore auto-increment mode

		addq.b	#$01,(R_LogoFlag).w				; advance to next routine
		rts							; return

; ---------------------------------------------------------------------------
; fading the palette line (when ready)
; ---------------------------------------------------------------------------

StaticMon2:

	if LITE=0	; keep pointer in, just null out routine

		bsr.s	CheckPrematureSkip

		cmpi.b	#$04,(R_LogoOrder).w				; have all logo films loaded?
		bcs.s	StaticMons					; if not, branch
		cmpi.b	#$10,(R_PalFade4).w				; has the palette fully faded out?
		beq.s	.NoLogo						; if not, branch
		addq.b	#$01,(R_PalFade4).w				; fade palette out
		addq.b	#$01,(R_PalFade3).w				; ''
		addq.b	#$01,(R_PalFade2).w				; ''
		addq.b	#$01,(R_PalFadeMon).w				; ''
		rts							; return

	.NoLogo:
		addq.b	#$01,(R_LogoFlag).w				; advance to next routine
		move.w	#$8500|((($0000)>>$09)&$FF),(a6)		; force sprite table to be at 0 from now on
		move.l	#$40000000,(a6)					; need to write the first long-word because a copy will...
		move.l	#$00000000,(a5)					; '' ...not transfer to cache from simple register change
		rts							; return

CheckPrematureSkip:
		tst.b	(R_Skip).w					; has the player pressed start while monitors are flying in?
		bne.s	.NoSkip						; if not, branch
		addq.b	#$01,(R_PalFadeMAST).w				; fade the master palette out
		cmpi.b	#$10+1,(R_PalFadeMAST).w			; have the palettes faded out fully?
		blt.s	.NoSkip						; if not, branch
		leal	LogoPLC,a1					; load logo art
		jsr	SetupPLC(pc)					; ''
		move.b	#$08,(R_LogoFlag).w				; set flag to special routine (involving loading data)
		addq.w	#$04,sp						; skip return address

	.NoSkip:

	endc

		rts							; return

; ---------------------------------------------------------------------------
; Subroutine to control the static on plane monitors by altering plane B
; ---------------------------------------------------------------------------

StaticMons:

	if LITE=0	; keep pointer in, just null out routine

		bsr.s	CheckPrematureSkip

		moveq	#$00,d3						; clear palette load flag
		bsr.s	.DoPlane					; perform the plane rendering/control
		tst.b	(R_LogoFlag).w					; has the palette for the logo been requested to load?
		beq.s	.NoLogoPal					; if not, branch
		lea	(R_Palette+$02).w,a1				; load palette buffer
		leal	LogoPalette,a0					; load logo's palette
		moveq	#((LogoPalette_End-LogoPalette)/2)-1,d0		; size of palette

	.LoadLogoPal:
		move.w	(a0)+,(a1)+					; copy colours across
		dbf	d0,.LoadLogoPal					; repeat for all palette colours

	.NoLogoPal:
		tst.b	(R_LoadLogo).w					; has the logo been requested to load?
		bpl.s	.NoLogoOrder					; if not, branch
		tst.b	d3						; has the logo started rendering?
		beq.s	.NoLogoOrder					; if not, branch
		addq.b	#$01,(R_LogoOrder).w				; advance to next logo screens

	.NoLogoOrder:
		rts							; retur

	; --- ---

	.DoPlane:
		lea	(R_Film).w,a0					; load start of film list
		moveq	#$04-1,d6					; number of films to check

MPB_NextFilm:
		tst.b	_Static(a0)					; is this film in static mode?
		bne.s	StaticOff					; if so, branch

	; --- Turning static on ---

StaticOn:
		tst.b	_Delay(a0)					; is the film delaying with static?
		beq.s	.NoStatic					; if not, branch
		st.b	_Static(a0)					; set static on
		lea	StaticList+((StaticList_End-StaticList)/2)(pc),a3 ; load static list (static ON)
		bsr.s	StaticRender					; render static on

	.NoStatic:
		lea	_FilmData(a0),a0				; advance to next film slot
		dbf	d6,MPB_NextFilm					; repeat for all films
		rts							; return

	; --- Turning static off ---

StaticOff:
		tst.b	_Delay(a0)					; is the film delaying with static?
		bne.s	.Static						; if so, branch
		sf.b	_Static(a0)					; set static off
		lea	StaticList(pc),a3				; load static list (static OFF)
		bsr.s	StaticRender					; render static off

	.Static:
		lea	_FilmData(a0),a0				; advance to next film slot
		dbf	d6,MPB_NextFilm					; repeat for all films
		rts							; return

	; --- static tile list ---

StatTile = $6000
StaticList:	rept	2
		dc.w	StatTile|((VSH_MonArt>>5)+$05),StatTile|((VSH_MonArt>>5)+$09),StatTile|((VSH_MonArt>>5)+$0D),StatTile|((VSH_MonArt>>5)+$11),StatTile|((VSH_MonArt>>5)+$15)
		dc.w	StatTile|((VSH_MonArt>>5)+$06),StatTile|((VSH_MonArt>>5)+$0A),StatTile|((VSH_MonArt>>5)+$0E),StatTile|((VSH_MonArt>>5)+$12),StatTile|((VSH_MonArt>>5)+$16)
		dc.w	StatTile|((VSH_MonArt>>5)+$07),StatTile|((VSH_MonArt>>5)+$0B),StatTile|((VSH_MonArt>>5)+$0F),StatTile|((VSH_MonArt>>5)+$13),StatTile|((VSH_MonArt>>5)+$17)
		dc.w	StatTile|((VSH_MonArt>>5)+$1E),StatTile|((VSH_MonArt>>5)+$20),StatTile|((VSH_MonArt>>5)+$22),StatTile|((VSH_MonArt>>5)+$24),StatTile|((VSH_MonArt>>5)+$26)
StatTile = $E000
		endr
StaticList_End:

; ---------------------------------------------------------------------------
; Subroutine to render static to a plane (on or off)
; ---------------------------------------------------------------------------

StaticRender:
		moveq	#$03-1,d5					; number of plane monitors the film can render on
		lea	_PlaneB(a0),a1					; load list of plane B slots

		jsr	TestLong0(pc)					; check PLC list address
		bne.s	.NextSlot					; if there are lists to decompress, branch

		moveq	#$04-1,d1					; is the slot we're about to staticalise the next in order to be switched for the logo?
		sub.w	d6,d1						; ''
		cmp.b	(R_LogoOrder).w,d1				; ''
		bne.s	.NextSlot					; if not, branch

		tst.b	_Static(a0)					; is the film changing from static
		bpl.s	.NextSlot					; if so, branch (ignore until after we're UN-static-ing)

		tst.b	(R_LoadLogo).w					; check if logos are allowed to load
		sne.b	d1						; set if so
		andi.w	#$0080,d1		 			; get only render bit
	; Doing ADD instead of OR will delay the change by another film's worth
	; this seemed to take a little long, but change OR to ADD to put it back on
		or.b	d1,(R_LoadLogo).w				; set the render flag on on/even frames
		bpl.s	.NextSlot					; if clear, branch
		move.b	#$01,(R_LogoFlag).w				; set to load the logo palette

	.NextSlot:
		move.l	(a1)+,d0					; load plane address
		beq.w	.NoSlot						; if none, branch

		jsr	TestLong0(pc)					; check PLC list address
		bne.s	.NoLogo						; if there are lists to decompress, branch
		moveq	#$04-1,d1					; is the slot we're about to staticalise the next in order to be switched for the logo?
		sub.w	d6,d1						; ''
		cmp.b	(R_LogoOrder).w,d1				; ''
		bne.s	.NoLogo						; if not, branch
		tst.b	(R_LoadLogo).w					; check if logos are allowed to load
		bpl.s	.NoLogo						; if clear, branch
		tst.b	_Static(a0)					; is the text changing from static
		bpl.s	.Logo						; if so, branch (ignore until after we're UN-static-ing)
		move.b	#$01,(R_LogoFlag).w				; set to load the logo palette

	.NoLogo:
		lea	(a3),a2						; load static tile list
		moveq	#$04-1,d4					; set number of rows to render

	.NextRow:
		move.l	d0,(a6)						; set monitor static address
		addi.l	#$00800000,d0					; advance to next column
		move.l	(a2)+,(a5)					; dump tiles
		move.l	(a2)+,(a5)					; ''
		move.w	(a2)+,(a5)					; ''
		dbf	d4,.NextRow					; repeat for all columns
		dbf	d5,.NextSlot					; repeat for all slots
		rts							; return

	.Logo:
		clr.l	-$04(a1)					; clear plane address (to prevent it from loading again)
		st.b	d3						; set palette load flag

	; ------------------------

	; Old version to DMA "Copy" forwards, unfortunately one of the
	; copies (full or individual films) need to have a palette line
	; change and thus need to be done manually, so I've chosen to
	; do the individual films as manual.

	;	move.l	d0,d1						; copy VDP address
	;	ori.b	#$C0,d0						; set DMA bits
	;	swap	d1						; get VRAM word address
	;	add.w	d1,d1						; ''
	;	add.w	d1,d1						; ''
	;	lsr.l	#$02,d1						; ''
	;	subi.w	#VSH_PlaneB,d1					; get relative address
	;	moveq	#$7E,d2						; get column
	;	and.w	d1,d2						; ''
	;	andi.w	#$0F80,d1
	;	mulu.w	#$28*2,d1					; get row
	;	lsr.l	#$07,d1						; ''
	;	add.w	d2,d1						; put back together (screen width rather than plane width)
	;	addi.w	#VSH_LogoPlane,d1				; get source address
	;	move.l	#$8F019400,(a6)					; set auto-increment for DMA copy, and upper byte of size will always be 0
	;	moveq	#$04-1,d2					; number of rows
	;	move.l	#$96009500,-(sp)				; prepare source registers

	;.NextRowLogo:
	;	move.l	#$97C0930A,(a6)					; set DMA source (DMA copy) and DMA lower byte size
	;	movep.w	d1,$01(sp)					; set DMA source address
	;	move.l	(sp),(a6)					; ''
	;	move.l	d0,(a6)						; set DMA destination
	;	addi.l	#$00800000,d0					; advance to next row in destination
	;	addi.w	#$0050,d1					; advance to next row in source
	;.Copy:	move.w	(a6),ccr					; load VDP status
	;	bvs.s	.Copy						; if VDP is still performing a DMA copy, branch
	;	dbf	d2,.NextRowLogo					; repeat for all rows
	;	addq.w	#$04,sp						; restore stack
	;	move.w	#$8F02,(a6)					; restore auto-increment mode

	; Manual version

		move.l	d0,d1						; copy VDP address
		swap	d1						; get VRAM word address
		add.w	d1,d1						; ''
		add.w	d1,d1						; ''
		lsr.l	#$02,d1						; ''
		subi.w	#VSH_PlaneB,d1					; get relative address
		moveq	#$7E,d2						; get column
		and.w	d1,d2						; ''
		andi.w	#$0F80,d1
		mulu.w	#$28*2,d1					; get row
		lsr.l	#$07,d1						; ''
		add.w	d2,d1						; put back together (screen width rather than plane width)
		addi.w	#VSH_LogoPlane,d1				; get source address
	; Just happens to spill over and alter mode bits...
	;	lsl.l	#$02,d1						; align for VDP
	;	lsr.w	#$02,d1						; ''
	;	swap	d1						; ''
		moveq	#$04-1,d4					; set number of rows to render

	.NextRowLogo:
	; Just happens to spill over and alter mode bits...
	;	move.l	d1,(a6)						; set VDP to read mode
	;	addi.l	#$00500000,d1					; advance for next row
	move.l	d1,d2
	lsl.l	#$02,d2
	lsr.w	#$02,d2
	swap	d2
	move.l	d2,(a6)						; set VDP to read mode
	addi.w	#$0050,d1					; advance for next row
		lea	-$05*2(sp),sp					; move stack back
		lea	(sp),a2						; load stack address
		rept	5
		move.w	(a5),(a2)+					; load tiles
		endr
		move.l	d0,(a6)						; set VDP to write mode
		addi.l	#$00800000,d0					; advance for next row
		rept	5
		move.w	(sp)+,d2					; load tile map out
		addi.w	#$8000-$2000,d2					; convert to another palette line
		move.w	d2,(a5)						; save tiles
		endr
		dbf	d4,.NextRowLogo					; repeat for all rows

	; ------------------------

	.NoSlot:
		dbf	d5,.NextSlot					; repeat for all slots
		rts							; return

	endc

; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to process PLC entries
; ---------------------------------------------------------------------------

ProcessPLC:
		jsr	LoadLong0(pc)					; load PLC list address
		beq.s	NoPLC						; if there are no lists to decompress, branch
		movea.l	d0,a1						; set address
		moveq	#$00,d0						; clear d0
		move.w	(a1)+,d0					; load PLC entry
		beq.s	.NoList						; if it's an end marker, branch
		add.l	a1,d0						; advance to correct address

	.NoList:
		move.l	d0,a0						; set address
		move.w	(a1)+,d0					; load VRAM address
		jsr	LZVRAM_PLC(pc)					; decompress entry
		beq.s	NoPLC						; if the previous file hasn't finished decompressing, branch

; ---------------------------------------------------------------------------
; Setting up a new PLC list
; --- input -----------------------------------------------------------------
; a1.l = address of PLC list (AAAAAAAA VVVV ...)
; ---------------------------------------------------------------------------

SetupPLC:
		move.l	a1,d0						; store PLC list address
		jsr	SaveLong0(pc)					; ''

NoPLC:
		rts							; return

; ===========================================================================
; ---------------------------------------------------------------------------
; LZVRAM decompression algorithm (FOR PLC!)
; --- input -----------------------------------------------------------------
; a0.l = address of source file
; d0.w = VRAM address to write to
; ---------------------------------------------------------------------------

LZVRAM_PLC:
		move.l	#$40300000,d1					; prepared VDP port setup
		move.w	d0,d1						; set VRAM address itself
		jsr	LoadLong1(pc)					; load VRAM address
		beq.s	.NewFile					; if there's no previous art to decompress, continue with new art
		move.l	d0,d1						; load previous address as new address
		jsr	LoadLong2(pc)					; load file address
		move.l	d0,a0						; ''
		jsr	LoadLong3(pc)					; load bitfield
		pea	(0).w						; set return as 0 (still decompressing a file)
		bsr.w	LZV_ContinueDec					; continue decompression
		bra.s	.Resume						; continue

	.NewFile:
		move.l	a0,d0						; load source address
		beq.w	.Finish						; if there is no source (was just checking for PLC resuming), branch
		pea	($FFFFFFFF).w					; set return as -1 (decompressing the new file)
		bsr.s	LZV_StartDec					; start new decompression

	.Resume:
		tst.b	(a0)+						; is there more data to decompress later?
		bmi.s	.Postpone					; if so, branch
		moveq	#$00,d1						; clear VRAM

	.Postpone:
		jsr	SaveLong3(pc)					; save bitfield
		move.l	a0,d0						; save file address
		jsr	SaveLong2(pc)					; ''
		move.l	d1,d0						; save VRAM address
		jsr	SaveLong1(pc)					; ''
		move.l	(sp)+,d0					; load return address
		rts							; return

	.Finish:
		suba.l	a1,a1						; clear PLC list
		moveq	#$01,d0						; set non-zero so PLC list saves
		rts							; return

; ---------------------------------------------------------------------------
; LZVRAM decompression algorithm
; --- input -----------------------------------------------------------------
; a0.l = address of source file
; d0.w = VRAM address to write to
; ---------------------------------------------------------------------------

LZVRAM:
		move.l	#$40300000,d1					; prepared VDP port setup
		move.w	d0,d1						; set VRAM address itself
		bsr.s	LZV_StartDec					; start new decompression
		tst.b	(a0)+						; is there more data to decompress?
		bpl.s	.Finish						; if not, branch

	.Proceed:
		bsr.w	LZV_Continue					; continue decompression
		tst.b	(a0)+						; is there more data to decompress?
		bmi.s	.Proceed					; if so, branch

	.Finish:
		rts							; return

; ---------------------------------------------------------------------------
; The algorithm itself
; ---------------------------------------------------------------------------

	; --- starting a new decompression ---

LZV_StartDec:
		move.l	d1,d2						; load ending address
		rol.l	#$02,d2						; align for VDP
		ror.w	#$02,d2						; ''
		swap	d2						; ''
		andi.b	#%00111111,d2					; clear DMA bit
	.Wait:	move.w	(a6),ccr					; load VDP status
		bvs.s	.Wait						; if VDP is still performing a DMA copy, branch
		move.w	#$8F02,(a6)					; set auto-increment back to 2
		move.l	d2,(a6)						; set manual destination address
		move.l	#$9596FF80,d2	; 80 so X can set below		; prepare source registers and minus value for length
		add.b	d2,d2						; set X flag
		bra.s	LZV_Start					; run decompression

	; --- resuming a decompression ---

LZV_ContinueDec:
		move.l	d1,d2						; load ending address
		rol.l	#$02,d2						; align for VDP
		ror.w	#$02,d2						; ''
		swap	d2						; ''
		andi.b	#%00111111,d2					; clear DMA bit
	.Wait:	move.w	(a6),ccr					; load VDP status
		bvs.s	.Wait						; if VDP is still performing a DMA copy, branch
		move.w	#$8F02,(a6)					; set auto-increment back to 2
		move.l	d2,(a6)						; set manual destination address
		move.l	#$9596FF00,d2					; prepare source registers and minus value for length
		bra.s	LZV_Continue					; continue decompression

	; --- the loop ---

	LZV_DMA:
		move.l	#$8F019400,(a6)					; set auto-increment for DMA copy, and upper byte of size will always be 0
		move.b	(a0)+,d2					; load length in minus
		add.w	d2,d2						; multiply by size of word
		add.w	d1,d2						; get source address
		rol.l	#$08,d2						; align registers
		ror.w	#$08,d2						; ''
		move.l	d2,(a6)						; set source registers
		move.l	d1,d2						; copy VDP register data
		add.b	d3,d3						; multiply copy by size of word
		add.w	d3,d1						; advance pattern index
		or.l	#$97C09300,d3					; set DMA source (DMA copy) and DMA lower byte size
		move.l	d3,(a6)						; ''
		rol.l	#$02,d2						; align for VDP
		ror.w	#$02,d2						; ''
		move.w	d2,(a6)						; set DMA destination part 1
		swap	d2						; set DMA destination part 2
		move.w	d2,(a6)						; ''
		move.l	d1,d2						; load ending address
		rol.l	#$02,d2						; align for VDP
		ror.w	#$02,d2						; ''
		swap	d2						; ''
		andi.b	#%00111111,d2					; clear DMA bit
	.Copy:	move.w	(a6),ccr					; load VDP status
		bvs.s	.Copy						; if VDP is still performing a DMA copy, branch
		move.w	#$8F02,(a6)					; set auto-increment back to 2
		move.l	d2,(a6)						; set manual destination address
		move.l	#$9596FF00,d2					; prepare source registers and minus value for length
		add.w	d0,d0						; get next bit
		bcs.s	LZV_Check					; if next word is LZSS, branch

	LZV_UNC:
		move.w	(a0)+,(a5)					; copy word to VRAM
		addq.w	#$02,d1						; increase VRAM address

	LZV_Continue:
		add.w	d0,d0						; get next bit
		bcc.s	LZV_UNC						; if next word is uncompressed, branch

	LZV_Check:
		bne.s	LZV_LZSS					; if there are still bits to deal with, branch

	LZV_Start:
		move.w	(a0)+,d0		; does not affect X	; load next row of bits
		addx.w	d0,d0						; check first bit (and add end marker flag)
		bcc.s	LZV_UNC						; if next word is uncompressed, branch

	LZV_LZSS:
		moveq	#$00,d3						; load copy
		move.b	(a0)+,d3					; ''
		bgt.s	LZV_DMA						; if this isn't the end, branch
		rts							; return

; ---------------------------------------------------------------------------
; Subroutine to load/save a long-word from/to VSRAM
; ---------------------------------------------------------------------------
VSRAMLOAD	=	$00300010
VSRAMSAVE	=	($40000000|VSRAMLOAD)
; ---------------------------------------------------------------------------

	; --- Loading ---

LoadLong0:
	move.l	(R_LZVRAM+$00).w,d0
	rts
		move.l	#($00<<$10)+VSRAMLOAD,(a6)			; set VDP to VSRAM read mode
		move.l	(a5),-(sp)					; load first two bytes
		move.l	(a5),-(sp)					; load second two bytes
		movep.l	$01(sp),d0					; load odd bytes together
		addq.w	#$08,sp						; restore stack
		swap	d0						; rearrange correctly (and check Z flag)
		rts							; return

TestLong0:
	tst.l	(R_LZVRAM+$00).w
	rts
		move.l	#($00<<$10)+VSRAMLOAD,(a6)			; set VDP to VSRAM read mode
		move.l	(a5),-(sp)					; load first two bytes
		move.l	(a5),-(sp)					; load second two bytes
		move.l	d0,-(sp)					; store d0
		movep.l	$01+4(sp),d0					; load odd bytes together
		move.l	d0,$04+$04(sp)					; store result
		move.l	(sp)+,d0					; restore d0
		addq.w	#$04,sp						; restore stack
		tst.l	(sp)+						; restore stack and test
		rts							; return

LoadLong1:
	move.l	(R_LZVRAM+$04).w,d0
	rts
		move.l	#($08<<$10)+VSRAMLOAD,(a6)			; set VDP to VSRAM read mode
		move.l	(a5),-(sp)					; load first two bytes
		move.l	(a5),-(sp)					; load second two bytes
		movep.l	$01(sp),d0					; load odd bytes together
		addq.w	#$08,sp						; restore stack
		swap	d0						; rearrange correctly (and check Z flag)
		rts							; return

LoadLong2:
	move.l	(R_LZVRAM+$08).w,d0
	rts
		move.l	#($10<<$10)+VSRAMLOAD,(a6)			; set VDP to VSRAM read mode
		move.l	(a5),-(sp)					; load first two bytes
		move.l	(a5),-(sp)					; load second two bytes
		movep.l	$01(sp),d0					; load odd bytes together
		addq.w	#$08,sp						; restore stack
		swap	d0						; rearrange correctly (and check Z flag)
		rts							; return

LoadLong3:
	move.l	(R_LZVRAM+$0C).w,d0
	rts
		move.l	#($18<<$10)+VSRAMLOAD,(a6)			; set VDP to VSRAM read mode
		move.l	(a5),-(sp)					; load first two bytes
		move.l	(a5),-(sp)					; load second two bytes
		movep.l	$01(sp),d0					; load odd bytes together
		addq.w	#$08,sp						; restore stack
		swap	d0						; rearrange correctly (and check Z flag)
		rts							; return

	; --- Saving ---

SaveLong0:
	move.l	d0,(R_LZVRAM+$00).w
	rts
		subq.w	#$08,sp						; prepare stack space
		movep.l	d0,$01(sp)					; split long-word into individual bytes per word
		move.l	#($00<<$10)+VSRAMSAVE,(a6)			; set VDP to VSRAM write mode
		move.l	(sp)+,(a5)					; save first two bytes
		move.l	(sp)+,(a5)					; save second two bytes
		rts							; return

SaveLong1:
	move.l	d0,(R_LZVRAM+$04).w
	rts
		subq.w	#$08,sp						; prepare stack space
		movep.l	d0,$01(sp)					; split long-word into individual bytes per word
		move.l	#($08<<$10)+VSRAMSAVE,(a6)			; set VDP to VSRAM write mode
		move.l	(sp)+,(a5)					; save first two bytes
		move.l	(sp)+,(a5)					; save second two bytes
		rts							; return

SaveLong2:
	move.l	d0,(R_LZVRAM+$08).w
	rts
		subq.w	#$08,sp						; prepare stack space
		movep.l	d0,$01(sp)					; split long-word into individual bytes per word
		move.l	#($10<<$10)+VSRAMSAVE,(a6)			; set VDP to VSRAM write mode
		move.l	(sp)+,(a5)					; save first two bytes
		move.l	(sp)+,(a5)					; save second two bytes
		rts							; return

SaveLong3:
	move.l	d0,(R_LZVRAM+$0C).w
	rts
		subq.w	#$08,sp						; prepare stack space
		movep.l	d0,$01(sp)					; split long-word into individual bytes per word
		move.l	#($18<<$10)+VSRAMSAVE,(a6)			; set VDP to VSRAM write mode
		move.l	(sp)+,(a5)					; save first two bytes
		move.l	(sp)+,(a5)					; save second two bytes
		rts							; return

; ---------------------------------------------------------------------------
; Kosinski (Special) decompression algorithm
; ---------------------------------------------------------------------------

	if LITE=0

KosSpeDec:
		subq.w	#$02,sp						; allocate some space
		move.b	(a0)+,(sp)		; won't affect X	; load next bitfield
		move.w	(sp),d3			; won't affect X	; ''
		move.b	(a0)+,d3		; won't affect X	; ''
		ori.b	#%10000,ccr					; set X flag
		bra.s	.Start						; jump into the loop

	.LZCC:
		moveq	#$00,d0						; clear d0
		add.w	d3,d3						; check next bit
		bne.s	.LZCC_1OK					; if there are still bits left, branch
		move.b	(a0)+,(sp)		; won't affect X	; load next bitfield
		move.w	(sp),d3			; won't affect X	; ''
		move.b	(a0)+,d3		; won't affect X	; ''
		addx.w	d3,d3						; check next bit (and put in end marker)

	.LZCC_1OK:
		addx.b	d0,d0						; load first CC bit
		add.w	d3,d3						; check next bit
		bne.s	.LZCC_2OK					; if there are still bits left, branch
		move.b	(a0)+,(sp)		; won't affect X	; load next bitfield
		move.w	(sp),d3			; won't affect X	; ''
		move.b	(a0)+,d3		; won't affect X	; ''
		addx.w	d3,d3						; check next bit (and put in end marker)

	.LZCC_2OK:
		addx.b	d0,d0						; load second CC bit
		add.b	d0,d0						; multiply by size of move instruction
		neg.w	d0						; reverse
		moveq	#-1,d1						; load retrace address
		move.b	(a0)+,d1					; ''
		lea	(a1,d1.w),a2					; retrace back
		jmp	.CopyCC-(2*2)(pc,d0.w)				; copy correct amount
		rept	3+2
		move.b	(a2)+,(a1)+					; copy LZ data across
		endr
	.CopyCC:
		add.w	d3,d3						; check next bit
		bcs.s	.Check						; if LZSS, branch

	.UNC:
		move.b	(a0)+,(a1)+					; copy uncompressed byte
		add.w	d3,d3						; check next bit
		bcc.s	.UNC						; if uncompressed, branch
	.Check:	bne.s	.LZSS						; if there are still bits left, branch
		move.b	(a0)+,(sp)		; won't affect X	; load next bitfield
		move.w	(sp),d3			; won't affect X	; ''
		move.b	(a0)+,d3		; won't affect X	; ''
	.Start:	addx.w	d3,d3						; check next bit (and put in end marker)
		bcc.s	.UNC						; if uncompressed, branch

	.LZSS:
		add.w	d3,d3						; check next bit
		bcc.s	.LZRD						; if uncompressed, branch
		bne.s	.LZCC						; if there are still bits left, branch
		move.b	(a0)+,(sp)		; won't affect X	; load next bitfield
		move.w	(sp),d3			; won't affect X	; ''
		move.b	(a0)+,d3		; won't affect X	; ''
		addx.w	d3,d3						; check next bit (and put in end marker)
		bcs.s	.LZCC						; if CC type of LZSS, branch

	.LZRD:
		move.b	(a0)+,d2					; load retrace address
		moveq	#-1,d1						; ''
		move.b	(a0)+,d1					; '' (and short copy)
		moveq	#%111,d0					; load only copy
		and.b	d1,d0						; ''
		beq.s	.LZRDCC						; if the copy is larger, branch
		lsl.w	#$05,d1						; prepare retrace address
		move.b	d2,d1						; ''
		add.b	d0,d0						; multiply by size of move instruction
		neg.w	d0						; reverse
		lea	(a1,d1.w),a2					; retrace back
		jmp	.CopyR-(2*2)(pc,d0.w)				; copy correct amount
		rept	7+2
		move.b	(a2)+,(a1)+					; copy LZ data across
		endr
	.CopyR:
		add.w	d3,d3						; check next bit
		bcc.s	.UNC						; if uncompressed, branch
		bra.s	.Check						; if LZSS, branch

	.LZRDCC:
		moveq	#$00,d0						; clear d0
		move.b	(a0)+,d0					; load additional copy
		beq.w	.Finish						; if finished, branch
		lsl.w	#$05,d1						; prepare retrace address
		move.b	d2,d1						; ''
		add.w	d0,d0						; multiply by size of move instruction
		neg.w	d0						; reverse
		addi.w	#($0100-1)*2,d0					; ''
		lea	(a1,d1.w),a2					; retrace back
		jmp	.CopyRDCC(pc,d0.w)				; copy correct amount

	.CopyRDCC:
		rept	$100
		move.b	(a2)+,(a1)+					; copy LZ data across
		endr
		add.w	d3,d3						; check next bit
		bcc.w	.UNC						; if uncompressed, branch
		bra.w	.Check						; if LZSS, branch

	.Finish:
		addq.w	#$02,sp						; restore space
		rts							; return

	endc

; ===========================================================================
; ---------------------------------------------------------------------------
; Include data
; ---------------------------------------------------------------------------

		;	Address,	VRAM

LogoPLC:	dc.w	ArtLogo-(*+2), VSH_LogoArt
		dc.w	MapLogo-(*+2), VSH_LogoPlane
		dc.w	$0000	; end of list

LogoPalette:	incbin	"Contest Logo\Palette.pal", $02
LogoPalette_End:

	if LITE=0
ArtNumbers:	incbin	"Contest Logo\Numbers.lzv"			; PLC Size = 0
ArtFont:	incbin	"Contest Logo\Font Final Art.lzv"		; PLC Size = 0
MapFont:	incbin	"Contest Logo\Font Final Map.map"
	endc
ArtLogo:	incbin	"Contest Logo\Logo Art.lzv"			; PLC Size = $600
MapLogo:	incbin	"Contest Logo\Logo Map.lzv"			; PLC Size = $600

; ===========================================================================
; ---------------------------------------------------------------------------
; Monitor sprites
; ---------------------------------------------------------------------------

	if LITE=0

MonMap:		dc.w	MonMap042-MonMap
		dc.w	MonMap041-MonMap
		dc.w	MonMap040-MonMap
		dc.w	MonMap039-MonMap
		dc.w	MonMap038-MonMap
		dc.w	MonMap037-MonMap
		dc.w	MonMap036-MonMap
		dc.w	MonMap035-MonMap
		dc.w	MonMap034-MonMap
		dc.w	MonMap033-MonMap
		dc.w	MonMap032-MonMap
		dc.w	MonMap031-MonMap
		dc.w	MonMap030-MonMap
		dc.w	MonMap029-MonMap
		dc.w	MonMap028-MonMap
		dc.w	MonMap027-MonMap
		dc.w	MonMap026-MonMap
		dc.w	MonMap025-MonMap
		dc.w	MonMap024-MonMap
		dc.w	MonMap023-MonMap
		dc.w	MonMap022-MonMap
		dc.w	MonMap021-MonMap
		dc.w	MonMap020-MonMap
		dc.w	MonMap019-MonMap
		dc.w	MonMap018-MonMap
		dc.w	MonMap017-MonMap
		dc.w	MonMap016-MonMap
		dc.w	MonMap015-MonMap
		dc.w	MonMap014-MonMap
		dc.w	MonMap013-MonMap
		dc.w	MonMap012-MonMap
		dc.w	MonMap011-MonMap
		dc.w	MonMap010-MonMap
		dc.w	MonMap009-MonMap
		dc.w	MonMap008-MonMap
		dc.w	MonMap007-MonMap
		dc.w	MonMap006-MonMap
		dc.w	MonMap005-MonMap
		dc.w	MonMap004-MonMap
		dc.w	MonMap003-MonMap
		dc.w	MonMap002-MonMap
		dc.w	MonMap001-MonMap
MonMap_End:

MonMap042:	include	"Monitor 3D Generator\Output Monitor\Map 042.asm"
MonMap041:	include	"Monitor 3D Generator\Output Monitor\Map 041.asm"
MonMap040:	include	"Monitor 3D Generator\Output Monitor\Map 040.asm"
MonMap039:	include	"Monitor 3D Generator\Output Monitor\Map 039.asm"
MonMap038:	include	"Monitor 3D Generator\Output Monitor\Map 038.asm"
MonMap037:	include	"Monitor 3D Generator\Output Monitor\Map 037.asm"
MonMap036:	include	"Monitor 3D Generator\Output Monitor\Map 036.asm"
MonMap035:	include	"Monitor 3D Generator\Output Monitor\Map 035.asm"
MonMap034:	include	"Monitor 3D Generator\Output Monitor\Map 034.asm"
MonMap033:	include	"Monitor 3D Generator\Output Monitor\Map 033.asm"
MonMap032:	include	"Monitor 3D Generator\Output Monitor\Map 032.asm"
MonMap031:	include	"Monitor 3D Generator\Output Monitor\Map 031.asm"
MonMap030:	include	"Monitor 3D Generator\Output Monitor\Map 030.asm"
MonMap029:	include	"Monitor 3D Generator\Output Monitor\Map 029.asm"
MonMap028:	include	"Monitor 3D Generator\Output Monitor\Map 028.asm"
MonMap027:	include	"Monitor 3D Generator\Output Monitor\Map 027.asm"
MonMap026:	include	"Monitor 3D Generator\Output Monitor\Map 026.asm"
MonMap025:	include	"Monitor 3D Generator\Output Monitor\Map 025.asm"
MonMap024:	include	"Monitor 3D Generator\Output Monitor\Map 024.asm"
MonMap023:	include	"Monitor 3D Generator\Output Monitor\Map 023.asm"
MonMap022:	include	"Monitor 3D Generator\Output Monitor\Map 022.asm"
MonMap021:	include	"Monitor 3D Generator\Output Monitor\Map 021.asm"
MonMap020:	include	"Monitor 3D Generator\Output Monitor\Map 020.asm"
MonMap019:	include	"Monitor 3D Generator\Output Monitor\Map 019.asm"
MonMap018:	include	"Monitor 3D Generator\Output Monitor\Map 018.asm"
MonMap017:	include	"Monitor 3D Generator\Output Monitor\Map 017.asm"
MonMap016:	include	"Monitor 3D Generator\Output Monitor\Map 016.asm"
MonMap015:	include	"Monitor 3D Generator\Output Monitor\Map 015.asm"
MonMap014:	include	"Monitor 3D Generator\Output Monitor\Map 014.asm"
MonMap013:	include	"Monitor 3D Generator\Output Monitor\Map 013.asm"
MonMap012:	include	"Monitor 3D Generator\Output Monitor\Map 012.asm"
MonMap011:	include	"Monitor 3D Generator\Output Monitor\Map 011.asm"
MonMap010:	include	"Monitor 3D Generator\Output Monitor\Map 010.asm"
MonMap009:	include	"Monitor 3D Generator\Output Monitor\Map 009.asm"
MonMap008:	include	"Monitor 3D Generator\Output Monitor\Map 008.asm"
MonMap007:	include	"Monitor 3D Generator\Output Monitor\Map 007.asm"
MonMap006:	include	"Monitor 3D Generator\Output Monitor\Map 006.asm"
MonMap005:	include	"Monitor 3D Generator\Output Monitor\Map 005.asm"
MonMap004:	include	"Monitor 3D Generator\Output Monitor\Map 004.asm"
MonMap003:	include	"Monitor 3D Generator\Output Monitor\Map 003.asm"
MonMap002:	include	"Monitor 3D Generator\Output Monitor\Map 002.asm"
MonMap001:	include	"Monitor 3D Generator\Output Monitor\Map 001.asm"

	endc

; ===========================================================================
; ---------------------------------------------------------------------------
; Monitor art (uncompressed)
; ---------------------------------------------------------------------------

	if LITE=0

MonArt:		dc.l	MonArt042-MonArt
		dc.l	MonArt041-MonArt
		dc.l	MonArt040-MonArt
		dc.l	MonArt039-MonArt
		dc.l	MonArt038-MonArt
		dc.l	MonArt037-MonArt
		dc.l	MonArt036-MonArt
		dc.l	MonArt035-MonArt
		dc.l	MonArt034-MonArt
		dc.l	MonArt033-MonArt
		dc.l	MonArt032-MonArt
		dc.l	MonArt031-MonArt
		dc.l	MonArt030-MonArt
		dc.l	MonArt029-MonArt
		dc.l	MonArt028-MonArt
		dc.l	MonArt027-MonArt
		dc.l	MonArt026-MonArt
		dc.l	MonArt025-MonArt
		dc.l	MonArt024-MonArt
		dc.l	MonArt023-MonArt
		dc.l	MonArt022-MonArt
		dc.l	MonArt021-MonArt
		dc.l	MonArt020-MonArt
		dc.l	MonArt019-MonArt
		dc.l	MonArt018-MonArt
		dc.l	MonArt017-MonArt

	dc.l	MonArt000-MonArt

		dc.l	$00000000	; MonArt016-MonArt
		dc.l	$00000000	; MonArt015-MonArt
		dc.l	$00000000	; MonArt014-MonArt
		dc.l	$00000000	; MonArt013-MonArt
		dc.l	$00000000	; MonArt012-MonArt
		dc.l	$00000000	; MonArt011-MonArt
		dc.l	$00000000	; MonArt010-MonArt
		dc.l	$00000000	; MonArt009-MonArt
		dc.l	$00000000	; MonArt008-MonArt
		dc.l	$00000000	; MonArt007-MonArt
		dc.l	$00000000	; MonArt006-MonArt
		dc.l	$00000000	; MonArt005-MonArt
		dc.l	$00000000	; MonArt004-MonArt
		dc.l	$00000000	; MonArt003-MonArt
		dc.l	$00000000	; MonArt002-MonArt
		dc.l	$00000000	; MonArt001-MonArt
		dc.w	$FFFF

MonArt042:	incbin	"Monitor 3D Generator\Output Monitor\Art 042.art"
MonArt041:	incbin	"Monitor 3D Generator\Output Monitor\Art 041.art"
MonArt040:	incbin	"Monitor 3D Generator\Output Monitor\Art 040.art"
MonArt039:	incbin	"Monitor 3D Generator\Output Monitor\Art 039.art"
MonArt038:	incbin	"Monitor 3D Generator\Output Monitor\Art 038.art"
MonArt037:	incbin	"Monitor 3D Generator\Output Monitor\Art 037.art"
MonArt036:	incbin	"Monitor 3D Generator\Output Monitor\Art 036.art"
MonArt035:	incbin	"Monitor 3D Generator\Output Monitor\Art 035.art"
MonArt034:	incbin	"Monitor 3D Generator\Output Monitor\Art 034.art"
MonArt033:	incbin	"Monitor 3D Generator\Output Monitor\Art 033.art"
MonArt032:	incbin	"Monitor 3D Generator\Output Monitor\Art 032.art"
MonArt031:	incbin	"Monitor 3D Generator\Output Monitor\Art 031.art"
MonArt030:	incbin	"Monitor 3D Generator\Output Monitor\Art 030.art"
MonArt029:	incbin	"Monitor 3D Generator\Output Monitor\Art 029.art"
MonArt028:	incbin	"Monitor 3D Generator\Output Monitor\Art 028.art"
MonArt027:	incbin	"Monitor 3D Generator\Output Monitor\Art 027.art"
MonArt026:	incbin	"Monitor 3D Generator\Output Monitor\Art 026.art"
MonArt025:	incbin	"Monitor 3D Generator\Output Monitor\Art 025.art"
MonArt024:	incbin	"Monitor 3D Generator\Output Monitor\Art 024.art"
MonArt023:	incbin	"Monitor 3D Generator\Output Monitor\Art 023.art"
MonArt022:	incbin	"Monitor 3D Generator\Output Monitor\Art 022.art"
MonArt021:	incbin	"Monitor 3D Generator\Output Monitor\Art 021.art"
MonArt020:	incbin	"Monitor 3D Generator\Output Monitor\Art 020.art"
MonArt019:	incbin	"Monitor 3D Generator\Output Monitor\Art 019.art"
MonArt018:	incbin	"Monitor 3D Generator\Output Monitor\Art 018.art"
MonArt017:	incbin	"Monitor 3D Generator\Output Monitor\Art 017.art"
; MonArt016:	incbin	"Monitor 3D Generator\Output Monitor\Art 016.art"
; MonArt015:	incbin	"Monitor 3D Generator\Output Monitor\Art 015.art"
; MonArt014:	incbin	"Monitor 3D Generator\Output Monitor\Art 014.art"
; MonArt013:	incbin	"Monitor 3D Generator\Output Monitor\Art 013.art"
; MonArt012:	incbin	"Monitor 3D Generator\Output Monitor\Art 012.art"
; MonArt011:	incbin	"Monitor 3D Generator\Output Monitor\Art 011.art"
; MonArt010:	incbin	"Monitor 3D Generator\Output Monitor\Art 010.art"
; MonArt009:	incbin	"Monitor 3D Generator\Output Monitor\Art 009.art"
; MonArt008:	incbin	"Monitor 3D Generator\Output Monitor\Art 008.art"
; MonArt007:	incbin	"Monitor 3D Generator\Output Monitor\Art 007.art"
; MonArt006:	incbin	"Monitor 3D Generator\Output Monitor\Art 006.art"
; MonArt005:	incbin	"Monitor 3D Generator\Output Monitor\Art 005.art"
; MonArt004:	incbin	"Monitor 3D Generator\Output Monitor\Art 004.art"
; MonArt003:	incbin	"Monitor 3D Generator\Output Monitor\Art 003.art"
; MonArt002:	incbin	"Monitor 3D Generator\Output Monitor\Art 002.art"
; MonArt001:	incbin	"Monitor 3D Generator\Output Monitor\Art 001.art"
MonArt000:	; END
MonArt001_016:	incbin	"Monitor 3D Generator\Output Monitor\Art 001 - 016.lzv"		; PLC Size = 0

	endc

; ===========================================================================
; ---------------------------------------------------------------------------
; Film code
; ---------------------------------------------------------------------------

	if LITE=0

; RenderFilm:
		include	"Film Generator\RenderFilm.asm"
; MapFilm:
		include	"Film Generator\MapFilm.asm"

	endc

; ===========================================================================
; ---------------------------------------------------------------------------
; Film Data
; ---------------------------------------------------------------------------
dcsb	macro String
Index = $00
	rept strlen(\String)
Char substr Index+$01,Index+$01,\String
	if "\Char"="¬"
		dc.b	$80
	elseif "\Char"="~"
		dc.b	$A0
	elseif "\Char"="#"
		dc.b	$FF
	elseif "\Char"=" "
		dc.b	$00
	elseif "\Char"="-"
		dc.b	$01
	elseif "\Char"="."
		dc.b	$02
	elseif "\Char"="'"
		dc.b	$03
	elseif "\Char"=")"
		dc.b	$2B
	elseif "\Char"="("
		dc.b	$2A
	elseif "\Char"="%"
		dc.b	$29
	elseif "\Char"="&"
		dc.b	$28
	elseif "\Char"<"A"
		dc.b	("\Char"-'0')+$04
	elseif "\Char"<"a"
		dc.b	("\Char"-'A')+$04+10
	else
		dc.b	("\Char"-'a')+$04+10
	endif
Index = Index+$01
	endr
	endm
; ---------------------------------------------------------------------------

	if LITE=0

	; --- List of films which have any colours ---

FilmList_AnyCols:	dc.l	Film_2002-FilmList_AnyCols
			dc.l	Film_2004-FilmList_AnyCols
			dc.l	Film_2005-FilmList_AnyCols
			dc.l	Film_2006-FilmList_AnyCols
			dc.l	Film_2007-FilmList_AnyCols
			dc.l	Film_2008-FilmList_AnyCols
			dc.l	Film_2009-FilmList_AnyCols
			dc.l	Film_2010-FilmList_AnyCols
			dc.l	Film_2011-FilmList_AnyCols
			dc.l	Film_2012-FilmList_AnyCols
			dc.l	Film_2013-FilmList_AnyCols
			dc.l	Film_2014-FilmList_AnyCols
			dc.l	Film_2015-FilmList_AnyCols
			dc.l	Film_2016-FilmList_AnyCols
			dc.l	Film_2017-FilmList_AnyCols
			dc.l	Film_2018-FilmList_AnyCols
			dc.l	Film_2019-FilmList_AnyCols
			dc.l	Film_2020-FilmList_AnyCols
			dc.l	Film_2021-FilmList_AnyCols
			dc.w	$FFFF

Film_1936:		incbin	"Film Frames\1936 - Static\Data\_Pal.bin"
			include	"Film Frames\1936 - Static\Data\_List.asm"

Film_2002:		incbin	"Film Frames\2002 - Sonic 2 Delta\Data\_Pal.bin"
			include	"Film Frames\2002 - Sonic 2 Delta\Data\_List.asm"
Film_2004:		incbin	"Film Frames\2004 - South Island Adventure\Data\_Pal.bin"
			include	"Film Frames\2004 - South Island Adventure\Data\_List.asm"
Film_2005:		incbin	"Film Frames\2005 - Shadow Adventure\Data\_Pal.bin"
			include	"Film Frames\2005 - Shadow Adventure\Data\_List.asm"
Film_2006:		incbin	"Film Frames\2006 - Sonic Megamix\Data\_Pal.bin"
			include	"Film Frames\2006 - Sonic Megamix\Data\_List.asm"
Film_2007:		incbin	"Film Frames\2007 - Sonic Megamix\Data\_Pal.bin"
			include	"Film Frames\2007 - Sonic Megamix\Data\_List.asm"
Film_2008:		incbin	"Film Frames\2008 - Sonic 2 Advanced Edit\Data\_Pal.bin"
			include	"Film Frames\2008 - Sonic 2 Advanced Edit\Data\_List.asm"
Film_2009:		incbin	"Film Frames\2009 - Sonic Boom\Data\_Pal.bin"
			include	"Film Frames\2009 - Sonic Boom\Data\_List.asm"
Film_2010:		incbin	"Film Frames\2010 - Sonic 2 Retro Remix\Data\_Pal.bin"
			include	"Film Frames\2010 - Sonic 2 Retro Remix\Data\_List.asm"
Film_2011:		incbin	"Film Frames\2011 - The S Factor\Data\_Pal.bin"
			include	"Film Frames\2011 - The S Factor\Data\_List.asm"
Film_2012:		incbin	"Film Frames\2012 - Sonic ERaZor\Data\_Pal.bin"
			include	"Film Frames\2012 - Sonic ERaZor\Data\_List.asm"
Film_2013:		incbin	"Film Frames\2013 - The S Factor\Data\_Pal.bin"
			include	"Film Frames\2013 - The S Factor\Data\_List.asm"
Film_2014:		incbin	"Film Frames\2014 - Sonic South Island Warped\Data\_Pal.bin"
			include	"Film Frames\2014 - Sonic South Island Warped\Data\_List.asm"
Film_2015:		incbin	"Film Frames\2015 - Sonic 1 The Next Level\Data\_Pal.bin"
			include	"Film Frames\2015 - Sonic 1 The Next Level\Data\_List.asm"
Film_2016:		incbin	"Film Frames\2016 - Sonic Scorched Quest\Data\_Pal.bin"
			include	"Film Frames\2016 - Sonic Scorched Quest\Data\_List.asm"
Film_2017:		incbin	"Film Frames\2017 - Metal Sonic Rebooted\Data\_Pal.bin"
			include	"Film Frames\2017 - Metal Sonic Rebooted\Data\_List.asm"
Film_2018:		incbin	"Film Frames\2018 - S3K Battle Race\Data\_Pal.bin"
			include	"Film Frames\2018 - S3K Battle Race\Data\_List.asm"
Film_2019:		incbin	"Film Frames\2019 - Sonic 2 Advanced Edit\Data\_Pal.bin"
			include	"Film Frames\2019 - Sonic 2 Advanced Edit\Data\_List.asm"
Film_2020:		incbin	"Film Frames\2020 - Pantufa The Cat\Data\_Pal.bin"
			include	"Film Frames\2020 - Pantufa The Cat\Data\_List.asm"
Film_2021:		incbin	"Film Frames\2021 - Sonic 1 Definitive\Data\_Pal.bin"
			include	"Film Frames\2021 - Sonic 1 Definitive\Data\_List.asm"

	; --- Year displaying values ---

		; the year numbers to display
FilmYears:	dc.b	$02,$04,$05,$06,$07,$08,$09,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21

		; films that can be shown on a monitor (00 = yes | FF = no)
Film_MonOnly:	dc.b	$FF,$00,$00,$00,$00,$FF,$FF,$FF,$00,$FF,$FF,$FF,$FF,$00,$FF,$FF,$FF,$FF,$FF	; for ONLY monitor colour films
Film_AnySlot:	dc.b	$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00	; for ANY films (all are 00)

	; --- Font displaying ---

FilmText:	dc.w	Text_NULL-FilmText
		dc.w	Text_2002-FilmText
		dc.w	Text_2004-FilmText
		dc.w	Text_2005-FilmText
		dc.w	Text_2006-FilmText
		dc.w	Text_2007-FilmText
		dc.w	Text_2008-FilmText
		dc.w	Text_2009-FilmText
		dc.w	Text_2010-FilmText
		dc.w	Text_2011-FilmText
		dc.w	Text_2012-FilmText
		dc.w	Text_2013-FilmText
		dc.w	Text_2014-FilmText
		dc.w	Text_2015-FilmText
		dc.w	Text_2016-FilmText
		dc.w	Text_2017-FilmText
		dc.w	Text_2018-FilmText
		dc.w	Text_2019-FilmText
		dc.w	Text_2020-FilmText
		dc.w	Text_2021-FilmText

Text_NULL:	dcsb	"¬"
		dcsb	"¬"
		dcsb	"¬"
		dcsb	"¬"
		dcsb	"¬"
		dcsb	"¬#"

Text_2002:	dcsb	"Sonic 2 Delta¬"
		dcsb	"~"
		dcsb	"   - Esrael -¬"
		dcsb	"¬¬#"

Text_2004:	dcsb	"  South Island¬"
		dcsb	"    Adventure¬"
		dcsb	"~"
		dcsb	" - Hivebrain -¬"
		dcsb	"¬¬#"

Text_2005:	dcsb	"      Shadow¬"
		dcsb	"   Adventure¬"
		dcsb	"~"
		dcsb	"     - Dude -¬"
		dcsb	"¬¬#"

Text_2007:
Text_2006:	dcsb	"Sonic Megamix¬"
		dcsb	"~"
		dcsb	"     - Team -¬"
		dcsb	"  - Megamix -¬"
		dcsb	"¬¬#"

Text_2019:
Text_2008:	dcsb	"      Sonic 2¬"
		dcsb	"Advanced Edit¬"
		dcsb	"~"
		dcsb	"   - Team AE -¬"
		dcsb	"¬¬#"

Text_2009:	dcsb	"  Sonic Boom¬"
		dcsb	"~"
		dcsb	"     - S%GA -¬"
		dcsb	"¬¬#"

Text_2010:	dcsb	"       Sonic 2¬"
		dcsb	"   Retro Remix¬"
		dcsb	"~"
		dcsb	"      - Thorn -¬"
		dcsb	"   - DNXDelta -¬"
		dcsb	"¬¬#"

Text_2013:
Text_2011:	dcsb	" The S-Factor¬"
		dcsb	"~"
		dcsb	" - Aquaslash -¬"
		dcsb	"     - & Pals -¬"
		dcsb	"¬¬#"

Text_2012:	dcsb	" Sonic ERaZor¬"
		dcsb	"~"
		dcsb	"    - Selbi -¬"
		dcsb	"¬¬#"


Text_2014:	dcsb	"  Sonic South¬"
		dcsb	"Island Warped¬"
		dcsb	"~"
		dcsb	" - Shockwave -¬"
		dcsb	"¬¬#"


Text_2015:	dcsb	"       Sonic 1¬"
		dcsb	"The Next Level¬"
		dcsb	"~"
		dcsb	"  - Markey -¬"
		dcsb	"      - Jester -¬"
		dcsb	"¬¬#"


Text_2016:	dcsb	"        Sonic¬"
		dcsb	"     Scorched¬"
		dcsb	"        Quest¬"
		dcsb	"~"
		dcsb	"- Team Painto -¬"
		dcsb	"¬¬#"


Text_2017:	dcsb	"  Metal Sonic¬"
		dcsb	"    Rebooted¬"
		dcsb	"~"
		dcsb	"- Lone Devil -¬"
		dcsb	"¬¬#"


Text_2018:	dcsb	"    Sonic 3&K¬"
		dcsb	"  Battle Race¬"
		dcsb	"~"
		dcsb	"     - Natsumi -¬"
		dcsb	"- MarkeyJester -¬"
		dcsb	"¬¬#"



Text_2020:	dcsb	"     Pantufa¬"
		dcsb	"        The Cat¬"
		dcsb	"~"
		dcsb	"  - VAdaPEGA -¬"
		dcsb	"¬¬#"



Text_2021:	dcsb	"(RETRO) Sonic¬"
		dcsb	" 1 Definitive¬"
		dcsb	"~"
		dcsb	"  - Radiant -¬"
		dcsb	"    - Nexus -¬"
		dcsb	"¬¬#"

		even

	endc

; ===========================================================================
; ---------------------------------------------------------------------------
; Finishing the screen, restoring VDP and return to the user's game
; ---------------------------------------------------------------------------

Finish:

	; --- Restoring 68k RAM space ---

		move.l	#$00000000|((VSH_68kRAM&$3FFF)<<$10)|((VSH_68kRAM>>$E)&3),(a6) ; set VDP read mode
		lea	(R_RAM).w,a1					; load RAM space to use
		move.w	#(R_RAM_Size/4)-1,d1				; size of RAM to reload

	.Load68kRAM:
		move.l	(a5),(a1)+					; reload RAM
		dbf	d1,.Load68kRAM					; repeat til RAM is reloaded

	; --- Restoring VDP and return ---

		bsr.s	ClearVDP					; clear VRAM, VSRAM, and CRAM

		lea	RestoreVDP(pc),a0				; load VDP resister data to restore
		moveq	#$13-1,d2					; number of registers to restore
		move.w	#$8000,d0					; prepare VDP register ID
		move.w	#$0100,d1					; prepare increment value

	.Restore:
		move.b	(a0)+,d0					; load VDP ID
		move.w	d0,(a6)						; save register to VDP
		add.w	d1,d0						; advance to next ID
		dbf	d2,.Restore					; repeat for all registers
	;	move.w	#$0000,($A11100).l				; start the Z80
		rte							; return (and restore sr)

; ===========================================================================
; ---------------------------------------------------------------------------
; Subroutine to clear VDP memory (CRAM, VSRAM, and VRAM)
; ---------------------------------------------------------------------------

ClearVDP:
		moveq	#$00,d0						; clear d0

		move.l	#$C0000000,(a6)					; set to write to CRAM
		bsr.s	.ClearRamVDP					; clear CRAM
		move.l	#$40000010,(a6)					; set to write to VSRAM
		bsr.s	.ClearRamVDP					; clear VSRAM

		move.l	#$8F019780,(a6)					; set increment mode and DMA mode
		move.l	#$94FF93E0,(a6)					; set DMA size
		move.l	#$96009500,(a6)					; set DMA source (null for fill)
		move.l	#$40200080,(a6)					; set DMA destination
		move.w	d0,(a5)						; set DMA fill value
		nop							; delay, give VDP time to set DMA status
		nop							; '' (probably not needed)
		move.w	(a6),ccr					; load status
		bvs.s	*-$02						; if the VDP DMA busy flag was set (bit 1), branch to wait til finished...
		move.w	#$8F02,(a6)					; set VDP increment mode back to normal
		rts							; return

	; --- Clearing CRAM/VSRAM ---

	.ClearRamVDP:
		moveq	#($80/4)-1,d1					; size of CRAM/VSRAM

	.ClearVDPRAM:
		move.l	d0,(a5)						; clear CRAM/VSRAM
		dbf	d1,.ClearVDPRAM					; repeat until CRAM/VSRAM is clear
		rts							; return

; ===========================================================================
; ---------------------------------------------------------------------------
; The VDP registers will need restoring, but since I can't know what the
; values are meant to be before entering, I not only HAVE to change them for
; my needs, but I have to restore them the way they were, and the only way to
; do that is to get the user to specify what the register contents were.
; ---------------------------------------------------------------------------

RestoreVDP:	; the VDP regiseters will be included on the *user's* source...

	if GAME=1

	; --- VDP Register Restoration ---
	; For Sonic 1 and 2
	; --------------------------------

		dc.b	%00000100				; $80	; 00LH 01CD - Leftover SMS bar (0N|1Y) | H-Interrupt (0N|1Y) | H,V Counter (0N|1Y) | Disable video signal (0N|1Y)
		dc.b	%01110100				; $81	; SDVM P100 - SMS mode (0N|1Y) | Display (0N|1Y) | V-Interrupt (0N|1Y) | DMA (0N|1Y) | V-resolution (0-1C|1-1E)
		dc.b	((($C000)>>$0A)&$FF)			; $82	; 00FE DCBA - Scroll Plane A Map Table VRam address
		dc.b	((($A000)>>$0A)&$FF)			; $83	; 00FE DCB0 / 00FE DC00 (20 H-resol) - Window Plane A Map Table VRam address
		dc.b	((($E000)>>$0D)&$FF)			; $84	; 0000 0FED - Scroll Plane B Map Table VRam address
		dc.b	((($F800)>>$09)&$FF)			; $85	; 0FED CBA9 / 0FED CBA0 (20 H-resol) - Sprite Plane Map Table VRam address
		dc.b	%00000000				; $86	; 0000 0000 - Unknown/Unused Register
		dc.b	$20					; $87	; 00PP CCCC - Backdrop Colour: Palette Line | Colour ID
		dc.b	%00000000				; $88	; 0000 0000 - Unknown/Unused Register
		dc.b	%00000000				; $89	; 0000 0000 - Unknown/Unused Register
		dc.b	$DF					; $8A	; 7654 3210 - H-Interrupt Register
		dc.b	%00000011				; $8B	; 0000 EVHH - External Interrupt (0N|1Y) | V-Scroll (0-Full|1-2Celled) | H-Scroll: (00-Full|10-Celled|11-Sliced)
		dc.b	%10000001				; $8C	; APHE SNNB - H-resol (0N|1Y) | Pixel int (0N|1Y) | H-sync (0N|1Y) | Extern-pix (0N|1Y) | S/H (0N|1Y) | Interlace (00N|01Y|11-Split) | H-resol (0-20|1-28)
		dc.b	((($FC00)>>$0A)&$FF)			; $8D	; 00FE DCBA - Horizontal Scroll Table VRam address
		dc.b	%00000000				; $8E	; 0000 0000 - Unknown/Unused Register
		dc.b	$02					; $8F	; 7654 3210 - Auto Increament
		dc.b	%00000001				; $90	; 00VV 00HH - Plane Y Size (00-20|01-40|11-80) | Plane X size (00-20|01-40|11-80)
		dc.b	$00					; $91	; 7654 3210 - Window Horizontal Position
		dc.b	$00					; $92	; 7654 3210 - Window Vertical Position
		even

	elseif GAME=2

	; --- VDP Register Restoration ---
	; For Sonic 3
	; --------------------------------

		dc.b	%00000100				; $80	; 00LH 01CD - Leftover SMS bar (0N|1Y) | H-Interrupt (0N|1Y) | H,V Counter (0N|1Y) | Disable video signal (0N|1Y)
		dc.b	%00110100				; $81	; SDVM P100 - SMS mode (0N|1Y) | Display (0N|1Y) | V-Interrupt (0N|1Y) | DMA (0N|1Y) | V-resolution (0-1C|1-1E)
		dc.b	((($C000)>>$0A)&$FF)			; $82	; 00FE DCBA - Scroll Plane A Map Table VRam address
		dc.b	((($9000)>>$0A)&$FF)			; $83	; 00FE DCB0 / 00FE DC00 (20 H-resol) - Window Plane A Map Table VRam address
		dc.b	((($E000)>>$0D)&$FF)			; $84	; 0000 0FED - Scroll Plane B Map Table VRam address
		dc.b	((($F800)>>$09)&$FF)			; $85	; 0FED CBA9 / 0FED CBA0 (20 H-resol) - Sprite Plane Map Table VRam address
		dc.b	%00000000				; $86	; 0000 0000 - Unknown/Unused Register
		dc.b	$00					; $87	; 00PP CCCC - Backdrop Colour: Palette Line | Colour ID
		dc.b	%00000000				; $88	; 0000 0000 - Unknown/Unused Register
		dc.b	%00000000				; $89	; 0000 0000 - Unknown/Unused Register
		dc.b	$00					; $8A	; 7654 3210 - H-Interrupt Register
		dc.b	%00000000				; $8B	; 0000 EVHH - External Interrupt (0N|1Y) | V-Scroll (0-Full|1-2Celled) | H-Scroll: (00-Full|10-Celled|11-Sliced)
		dc.b	%10000001				; $8C	; APHE SNNB - H-resol (0N|1Y) | Pixel int (0N|1Y) | H-sync (0N|1Y) | Extern-pix (0N|1Y) | S/H (0N|1Y) | Interlace (00N|01Y|11-Split) | H-resol (0-20|1-28)
		dc.b	((($F000)>>$0A)&$FF)			; $8D	; 00FE DCBA - Horizontal Scroll Table VRam address
		dc.b	%00000000				; $8E	; 0000 0000 - Unknown/Unused Register
		dc.b	$02					; $8F	; 7654 3210 - Auto Increament
		dc.b	%00000001				; $90	; 00VV 00HH - Plane Y Size (00-20|01-40|11-80) | Plane X size (00-20|01-40|11-80)
		dc.b	$00					; $91	; 7654 3210 - Window Horizontal Position
		dc.b	$00					; $92	; 7654 3210 - Window Vertical Position
		even
	endc

; ===========================================================================






















