Removing the scroll block system

Discussion in 'Tutorials Archive' started by MarkeyJester, May 8, 2012.

Thread Status:
Not open for further replies.
  1. MarkeyJester

    MarkeyJester ♡ ! Member

    Joined:
    Jun 27, 2009
    Messages:
    2,867
    Firstly, a thanks to Jorge for this advice and ideas on this one, and to those in the SSRG IRC channel who tested the resulting ROM for bugs.


    Sonic 1 (and Sonic 2) have a scroll block system, I'll explain how that system works first, the FG of the draw code has only 1 X and Y position to follow when drawing the void tiles, this is because the FG doesn't really do anything fancy besides moving all together, the BG on the other hand has multiple scroll block sections.


    For Sonic 1's REV 00, there are only two scroll block sections (meaning only two parts of the BG may scroll at different speeds that the draw code can work with), and only GHZ puts both to use, Sonic 1's REV 01 has three scroll block sections (meaning only three parts of the BG may scroll differently that the draw code can work with), and Sonic 2 has four.


    Now, the idea of having different block sections of scrolling that communicate with the draw code positions, is really quite interesting, and it does well in general, however, there comes a time where you'll need to do something so surreal, you'll need much more than four scroll blocks, you could add more scroll blocks in, this however would require more RAM space for the new scroll block section's X and Y positions, and would require yet another routine for dealing with the extra scroll block.


    I've been experimenting with this for the past two days, and have built up a brand new draw code for Sonic 1, this draw code doesn't deal with scroll blocks, instead, it collects the positions directly from the scroll buffer, meaning the drawn blocks are always in sync with the scrolling no matter what speeds you've put them at. Anyway, enough babbling, let's get to the code:


    Firstly, we'll prepare the source code, all DMA transfers of the scroll buffer need changing slightly, go to the following routines:

    • loc_CD4:
    • loc_ED8:
    • loc_FAE:
    • loc_10D4:


    You will find in each of them there will be this exact instruction:



    Code:
    
       	 move.l	#$96E69500,(a5)


    Change the end 00 to 20:





    Code:
    
       	 move.l	#$96E69520,(a5)			; MJ: advanced by 40 (added 20)


    This will set the transfer from FFCC40 instead of FFCC00 (I'll explain why later).



    Next, go down to "SS_EndClrObjRam:", there, you'll find:





    Code:
    SS_EndClrObjRam:
    
    		move.l	d0,(a1)+
    
    		dbf	d1,SS_EndClrObjRam ; clear object RAM
    
    
    
    		move.b	#$7E,($FFFFD5C0).w ; load results screen object


    Under it, you'll need to put in:





    Code:
    
       	 moveq	#$00,d0					; MJ: clear d0
    
    		move.w	d0,($FFFFF700).w			; MJ: clear screen positions
    
    		move.w	d0,($FFFFF704).w			; MJ: ''
    
    		move.w	d0,($FFFFF708).w			; MJ: ''
    
    		move.w	d0,($FFFFF70C).w			; MJ: ''


    This is to prevent a certain glitch that occurs after the code is in. Next up, in routine "Title_LoadText:" you'll find this code:





    Code:
    
       	 lea	($C00004).l,a5
    
    		lea	($C00000).l,a6
    
    		lea	($FFFFF708).w,a3
    
    		lea	($FFFFA440).w,a4
    
    		move.w	#$6000,d2
    
    		bsr.w	LoadTilesFromStart2


    This code is for drawing the BG blocks at the beginning of the title screen, replace it with:





    Code:
       	 lea	($FFFFA440).w,a4			; MJ: load BG layout space
    
    		move.w	#$6000,d6				; MJ: prepare VRAM plane address
    
    		move.w	($FFFFF708).w,d4			; MJ: load BG X position
    
    		move.w	($FFFFF70C).w,d5			; MJ: load BG Y position
    
    		bsr.w	LoadBGTilesFromStart			; MJ: draw BG blocks


    Next go down to routine "loc_5334:" and you'll find this code:





    Code:
    
       	 lea	($C00004).l,a5
    
    		lea	($C00000).l,a6
    
    		lea	($FFFFF700).w,a3
    
    		lea	($FFFFA400).w,a4
    
    		move.w	#$4000,d2
    
    		bsr.w	LoadTilesFromStart2


    This is for redrawing the entire FG in the credits with the new flower chunks, if you have all emeralds, replace it with:





    Code:
    
       	 lea	($FFFFA400).w,a4			; MJ: load FG layout space
    
    		move.w	#$4000,d6				; MJ: prepare VRAM plane address
    
    		move.w	($FFFFF700).w,d4			; MJ: load X position
    
    		move.w	($FFFFF704).w,d5			; MJ: load Y position
    
    		bsr.w	LoadFGTilesFromStart			; MJ: draw FG blocks


    Now, because of there being no scroll blocks, and because the scroll buffer has been shifted up, the deformation routines need updating, so from "Deform_GHZ:" to "; End of function Deform_SBZ", replace it all with:





    Code:
    Deform_GHZ:				; XREF: Deform_Index
    
    		move.l	#$160F160F,($FFFFF74C).w		; MJ: set draw block sizes
    
    		move.w	($FFFFF73A).w,d4
    
    		ext.l	d4
    
    		asl.l	#$05,d4
    
    		move.l	d4,d1
    
    		asl.l	#$01,d4
    
    		add.l	d1,d4
    
    		add.l	d4,($FFFFF708).w
    
    		move.w	($FFFFF73A).w,d0			; MJ: load X add position
    
    		ext.l	d0					; MJ: extend incase it's negative
    
    		asl.l	#$07,d0					; MJ: multiply by 80 (shifting to decimal place)
    
    		add.l	d0,($FFFFF710).w			; MJ: add to current Bottom BG X position
    
    		lea	($FFFFCC00).w,a1
    
    		move.w	($FFFFF704).w,d0
    
    		andi.w	#$7FF,d0
    
    		lsr.w	#5,d0
    
    		neg.w	d0
    
    		addi.w	#$26,d0
    
    		move.w	d0,($FFFFF714).w
    
    		move.w	d0,d4
    
    		move.w	d0,($FFFFF70C).w			; update Top BG Y position
    
    		move.w	($FFFFF70C).w,($FFFFF618).w
    
    		move.w	#$7F,d1					; MJ: changed from 6F to 7F
    
    		sub.w	d4,d1
    
    		move.w	($FFFFF700).w,d0
    
    		cmpi.b	#4,($FFFFF600).w
    
    		bne.s	loc_633C
    
    		moveq	#0,d0
    
    
    
    loc_633C:
    
    		neg.w	d0
    
    		swap	d0
    
    		move.w	($FFFFF708).w,d0
    
    		neg.w	d0
    
    
    
    loc_6346:
    
    		move.l	d0,(a1)+
    
    		dbf	d1,loc_6346
    
    		move.w	#$27,d1
    
    		move.w	($FFFFF710).w,d0
    
    		neg.w	d0
    
    
    
    loc_6356:
    
    		move.l	d0,(a1)+
    
    		dbf	d1,loc_6356
    
    		move.w	($FFFFF710).w,d0
    
    		addi.w	#0,d0
    
    		move.w	($FFFFF700).w,d2
    
    	;	addi.w	#-$200,d2				; MJ: removed shift (the new draw code works so well, it draws the error properly =$)
    
    		sub.w	d0,d2
    
    		ext.l	d2
    
    		asl.l	#8,d2
    
    		divs.w	#$68,d2
    
    		ext.l	d2
    
    		asl.l	#8,d2
    
    		moveq	#0,d3
    
    		move.w	d0,d3
    
    		move.w	#$57,d1					; MJ: changed from 47 to 57
    
    		add.w	d4,d1
    
    
    
    loc_6384:
    
    		move.w	d3,d0
    
    		neg.w	d0
    
    		move.l	d0,(a1)+
    
    		swap	d3
    
    		add.l	d2,d3
    
    		swap	d3
    
    		dbf	d1,loc_6384
    
    		rts
    
    
    
    ; End of function Deform_GHZ
    
    
    
    ; ---------------------------------------------------------------------------
    
    ; Labyrinth Zone background layer deformation code
    
    ; ---------------------------------------------------------------------------
    
    
    
    ; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||
    
    
    
    
    
    Deform_LZ:				; XREF: Deform_Index
    
    		move.l	#$160F160F,($FFFFF74C).w		; MJ: set draw block sizes
    
    		move.w	($FFFFF73A).w,d4
    
    		ext.l	d4
    
    		asl.l	#7,d4
    
    		add.l	d4,($FFFFF708).w
    
    		move.w	($FFFFF73C).w,d5
    
    		ext.l	d5
    
    		asl.l	#7,d5
    
    		add.l	d5,($FFFFF70C).w
    
    
    
    		move.w	($FFFFF70C).w,($FFFFF618).w
    
    		lea	($FFFFCC00).w,a1
    
    		move.w	#$FF,d1					; MJ: changed from DF to FF
    
    		move.w	($FFFFF700).w,d0
    
    		neg.w	d0
    
    		swap	d0
    
    		move.w	($FFFFF708).w,d0
    
    		neg.w	d0
    
    
    
    loc_63C6:
    
    		move.l	d0,(a1)+
    
    		dbf	d1,loc_63C6
    
    		move.w	($FFFFF646).w,d0
    
    		sub.w	($FFFFF704).w,d0
    
    		rts	
    
    ; End of function Deform_LZ
    
    
    
    ; ---------------------------------------------------------------------------
    
    ; Marble Zone background layer deformation code
    
    ; ---------------------------------------------------------------------------
    
    
    
    ; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||
    
    
    
    
    
    Deform_MZ:				; XREF: Deform_Index
    
    		move.l	#$160F160F,($FFFFF74C).w		; MJ: set draw block sizes
    
    		move.w	($FFFFF73A).w,d4
    
    		ext.l	d4
    
    		asl.l	#6,d4
    
    		move.l	d4,d1
    
    		asl.l	#1,d4
    
    		add.l	d1,d4
    
    		add.l	d4,($FFFFF708).w
    
    
    
    		move.w	#$200,d0
    
    		move.w	($FFFFF704).w,d1
    
    		subi.w	#$1C8,d1
    
    		bcs.s	loc_6402
    
    		move.w	d1,d2
    
    		add.w	d1,d1
    
    		add.w	d2,d1
    
    		asr.w	#2,d1
    
    		add.w	d1,d0
    
    
    
    loc_6402:
    
    		move.w	d0,($FFFFF714).w
    
    		move.w	d0,($FFFFF70C).w			; update Top BG Y position
    
    		move.w	($FFFFF70C).w,($FFFFF618).w
    
    		lea	($FFFFCC00).w,a1
    
    		move.w	#$FF,d1					; MJ: changed from DF to FF
    
    		move.w	($FFFFF700).w,d0
    
    		neg.w	d0
    
    		swap	d0
    
    		move.w	($FFFFF708).w,d0
    
    		neg.w	d0
    
    
    
    loc_6426:
    
    		move.l	d0,(a1)+
    
    		dbf	d1,loc_6426
    
    		rts	
    
    ; End of function Deform_MZ
    
    
    
    ; ---------------------------------------------------------------------------
    
    ; Star Light Zone background layer deformation code
    
    ; ---------------------------------------------------------------------------
    
    
    
    ; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||
    
    
    
    
    
    Deform_SLZ:				; XREF: Deform_Index
    
    		move.l	#$160F160F,($FFFFF74C).w		; MJ: set draw block sizes
    
    		move.w	($FFFFF73A).w,d4
    
    		ext.l	d4
    
    		asl.l	#7,d4
    
    		add.l	d4,($FFFFF708).w
    
    		move.w	($FFFFF73C).w,d5
    
    		ext.l	d5
    
    		asl.l	#7,d5
    
    		add.l	d5,($FFFFF70C).w
    
    
    
    		move.w	($FFFFF70C).w,($FFFFF618).w
    
    		bsr.w	Deform_SLZ_2
    
    		lea	($FFFFA800).w,a2
    
    		move.w	($FFFFF70C).w,d0
    
    		move.w	d0,d2
    
    		subi.w	#$C0,d0
    
    		andi.w	#$3F0,d0
    
    		lsr.w	#3,d0
    
    		lea	(a2,d0.w),a2
    
    		lea	($FFFFCC00).w,a1
    
    		move.w	#$F,d1					; MJ: changed from E to F
    
    		move.w	($FFFFF700).w,d0
    
    		neg.w	d0
    
    		swap	d0
    
    		andi.w	#$F,d2
    
    		add.w	d2,d2
    
    		move.w	(a2)+,d0
    
    		jmp	loc_6482(pc,d2.w)
    
    ; ===========================================================================
    
    
    
    loc_6480:				; XREF: Deform_SLZ
    
    		move.w	(a2)+,d0
    
    
    
    loc_6482:
    
    		move.l	d0,(a1)+
    
    		move.l	d0,(a1)+
    
    		move.l	d0,(a1)+
    
    		move.l	d0,(a1)+
    
    		move.l	d0,(a1)+
    
    		move.l	d0,(a1)+
    
    		move.l	d0,(a1)+
    
    		move.l	d0,(a1)+
    
    		move.l	d0,(a1)+
    
    		move.l	d0,(a1)+
    
    		move.l	d0,(a1)+
    
    		move.l	d0,(a1)+
    
    		move.l	d0,(a1)+
    
    		move.l	d0,(a1)+
    
    		move.l	d0,(a1)+
    
    		move.l	d0,(a1)+
    
    		dbf	d1,loc_6480
    
    		rts	
    
    ; End of function Deform_SLZ
    
    
    
    
    
    ; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||
    
    
    
    
    
    Deform_SLZ_2:				; XREF: Deform_SLZ
    
    		lea	($FFFFA800).w,a1
    
    		move.w	($FFFFF700).w,d2
    
    		neg.w	d2
    
    		move.w	d2,d0
    
    		asr.w	#3,d0
    
    		sub.w	d2,d0
    
    		ext.l	d0
    
    		asl.l	#4,d0
    
    		divs.w	#$1C,d0
    
    		ext.l	d0
    
    		asl.l	#4,d0
    
    		asl.l	#8,d0
    
    		moveq	#0,d3
    
    		move.w	d2,d3
    
    		move.w	#$1C,d1					; MJ: changed from 1B to 1C
    
    
    
    loc_64CE:
    
    		move.w	d3,(a1)+
    
    		swap	d3
    
    		add.l	d0,d3
    
    		swap	d3
    
    		dbf	d1,loc_64CE
    
    		move.w	d2,d0
    
    		asr.w	#3,d0
    
    		move.w	#4,d1
    
    
    
    loc_64E2:
    
    		move.w	d0,(a1)+
    
    		dbf	d1,loc_64E2
    
    		move.w	d2,d0
    
    		asr.w	#2,d0
    
    		move.w	#4,d1
    
    
    
    loc_64F0:
    
    		move.w	d0,(a1)+
    
    		dbf	d1,loc_64F0
    
    		move.w	d2,d0
    
    		asr.w	#1,d0
    
    		move.w	#$1E,d1					; MJ: changed from 1D to 1E
    
    
    
    loc_64FE:
    
    		move.w	d0,(a1)+
    
    		dbf	d1,loc_64FE
    
    		rts	
    
    ; End of function Deform_SLZ_2
    
    
    
    ; ---------------------------------------------------------------------------
    
    ; Spring Yard Zone background layer deformation	code
    
    ; ---------------------------------------------------------------------------
    
    
    
    ; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||
    
    
    
    
    
    Deform_SYZ:				; XREF: Deform_Index
    
    		move.l	#$160F160F,($FFFFF74C).w		; MJ: set draw block sizes
    
    		move.w	($FFFFF73A).w,d4
    
    		ext.l	d4
    
    		asl.l	#6,d4
    
    		add.l	d4,($FFFFF708).w
    
    		move.w	($FFFFF73C).w,d5
    
    		ext.l	d5
    
    		asl.l	#4,d5
    
    		move.l	d5,d1
    
    		asl.l	#1,d5
    
    		add.l	d1,d5
    
    		add.l	d5,($FFFFF70C).w
    
    
    
    		move.w	($FFFFF70C).w,($FFFFF618).w
    
    		lea	($FFFFCC00).w,a1
    
    		move.w	#$FF,d1					; MJ: changed from DF to FF
    
    		move.w	($FFFFF700).w,d0
    
    		neg.w	d0
    
    		swap	d0
    
    		move.w	($FFFFF708).w,d0
    
    		neg.w	d0
    
    
    
    loc_653C:
    
    		move.l	d0,(a1)+
    
    		dbf	d1,loc_653C
    
    		rts	
    
    ; End of function Deform_SYZ
    
    
    
    ; ---------------------------------------------------------------------------
    
    ; Scrap	Brain Zone background layer deformation	code
    
    ; ---------------------------------------------------------------------------
    
    
    
    ; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||
    
    
    
    
    
    Deform_SBZ:				; XREF: Deform_Index
    
    		move.l	#$160F160F,($FFFFF74C).w		; MJ: set draw block sizes
    
    		move.w	($FFFFF73A).w,d4
    
    		ext.l	d4
    
    		asl.l	#6,d4
    
    		add.l	d4,($FFFFF708).w
    
    		move.w	($FFFFF73C).w,d5
    
    		ext.l	d5
    
    		asl.l	#4,d5
    
    		asl.l	#1,d5
    
    		add.l	d5,($FFFFF70C).w
    
    		move.w	($FFFFF70C).w,($FFFFF618).w
    
    		lea	($FFFFCC00).w,a1
    
    		move.w	#$FF,d1					; MJ: changed from DF to FF
    
    		move.w	($FFFFF700).w,d0
    
    		neg.w	d0
    
    		swap	d0
    
    		move.w	($FFFFF708).w,d0
    
    		neg.w	d0
    
    
    
    loc_6576:
    
    		move.l	d0,(a1)+
    
    		dbf	d1,loc_6576
    
    		rts
    
    
    
    ; End of function Deform_SBZ


    Next, delete the entire routine from "ScrollBlock1:" to "; End of function ScrollBlock4", this routine basically:





    Code:
    ScrollBlock1:				; XREF: Deform_GHZ; et al
    
    		move.l	($FFFFF708).w,d2
    
    		move.l	d2,d0
    
    		add.l	d4,d0
    
    		move.l	d0,($FFFFF708).w
    
    		move.l	d0,d1
    
    		swap	d1
    
    		andi.w	#$10,d1
    
    		move.b	($FFFFF74C).w,d3
    
    		eor.b	d3,d1
    
    		bne.s	loc_679C
    
    		eori.b	#$10,($FFFFF74C).w
    
    		sub.l	d2,d0
    
    		bpl.s	loc_6796
    
    		bset	#2,($FFFFF756).w
    
    		bra.s	loc_679C
    
    ; ===========================================================================
    
    
    
    loc_6796:
    
    		bset	#3,($FFFFF756).w
    
    
    
    loc_679C:
    
    		move.l	($FFFFF70C).w,d3
    
    		move.l	d3,d0
    
    		add.l	d5,d0
    
    		move.l	d0,($FFFFF70C).w
    
    		move.l	d0,d1
    
    		swap	d1
    
    		andi.w	#$10,d1
    
    		move.b	($FFFFF74D).w,d2
    
    		eor.b	d2,d1
    
    		bne.s	locret_67D0
    
    		eori.b	#$10,($FFFFF74D).w
    
    		sub.l	d3,d0
    
    		bpl.s	loc_67CA
    
    		bset	#0,($FFFFF756).w
    
    		rts	
    
    ; ===========================================================================
    
    
    
    loc_67CA:
    
    		bset	#1,($FFFFF756).w
    
    
    
    locret_67D0:
    
    		rts	
    
    ; End of function ScrollBlock1
    
    
    
    
    
    ; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||
    
    
    
    
    
    ScrollBlock2:				; XREF: Deform_SLZ
    
    		move.l	($FFFFF708).w,d2
    
    		move.l	d2,d0
    
    		add.l	d4,d0
    
    		move.l	d0,($FFFFF708).w
    
    		move.l	($FFFFF70C).w,d3
    
    		move.l	d3,d0
    
    		add.l	d5,d0
    
    		move.l	d0,($FFFFF70C).w
    
    		move.l	d0,d1
    
    		swap	d1
    
    		andi.w	#$10,d1
    
    		move.b	($FFFFF74D).w,d2
    
    		eor.b	d2,d1
    
    		bne.s	locret_6812
    
    		eori.b	#$10,($FFFFF74D).w
    
    		sub.l	d3,d0
    
    		bpl.s	loc_680C
    
    		bset	#0,($FFFFF756).w
    
    		rts	
    
    ; ===========================================================================
    
    
    
    loc_680C:
    
    		bset	#1,($FFFFF756).w
    
    
    
    locret_6812:
    
    		rts	
    
    ; End of function ScrollBlock2
    
    
    
    
    
    ; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||
    
    
    
    
    
    ScrollBlock3:				; XREF: Deform_GHZ; et al
    
    		move.w	($FFFFF70C).w,d3
    
    		move.w	d0,($FFFFF70C).w
    
    		move.w	d0,d1
    
    		andi.w	#$10,d1
    
    		move.b	($FFFFF74D).w,d2
    
    		eor.b	d2,d1
    
    		bne.s	locret_6842
    
    		eori.b	#$10,($FFFFF74D).w
    
    		sub.w	d3,d0
    
    		bpl.s	loc_683C
    
    		bset	#0,($FFFFF756).w
    
    		rts	
    
    ; ===========================================================================
    
    
    
    loc_683C:
    
    		bset	#1,($FFFFF756).w
    
    
    
    locret_6842:
    
    		rts	
    
    ; End of function ScrollBlock3
    
    
    
    
    
    ; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||
    
    
    
    
    
    ScrollBlock4:				; XREF: Deform_GHZ
    
    		move.w	($FFFFF710).w,d2
    
    		move.w	($FFFFF714).w,d3
    
    		move.w	($FFFFF73A).w,d0
    
    		ext.l	d0
    
    		asl.l	#7,d0
    
    		add.l	d0,($FFFFF710).w
    
    		move.w	($FFFFF710).w,d0
    
    		andi.w	#$10,d0
    
    		move.b	($FFFFF74E).w,d1
    
    		eor.b	d1,d0
    
    		bne.s	locret_6884
    
    		eori.b	#$10,($FFFFF74E).w
    
    		move.w	($FFFFF710).w,d0
    
    		sub.w	d2,d0
    
    		bpl.s	loc_687E
    
    		bset	#2,($FFFFF758).w
    
    		bra.s	locret_6884
    
    ; ===========================================================================
    
    
    
    loc_687E:
    
    		bset	#3,($FFFFF758).w
    
    
    
    locret_6884:
    
    		rts	
    
    ; End of function ScrollBlock4


    Just completely remove it, delete it, whatever, we no longer need the scroll blocks. Now it's time to replace the draw code itself.



    From "sub_6886:" down to "; End of function LoadTilesFromStart2", replace all of that with this:





    Code:
    ; ===========================================================================
    
    ; ---------------------------------------------------------------------------
    
    ; MJ - New draw code - By MarkeyJester - Special thanks to Jorge
    
    ; ---------------------------------------------------------------------------
    
    
    
    TileBuffer	=	$FFFFA800				; Entire Buffer
    
    TileBufferA	=	TileBuffer				; First half of buffer
    
    TileBufferB	=	TileBuffer+$80				; Second half of buffer
    
    HBufferSize	=	$0080
    
    VBufferSize	=	$0040
    
    LastFGXPos	=	$FFFFF718
    
    LastFGYPos	=	$FFFFF71A
    
    LastBGXPos	=	$FFFFF71C
    
    LastBGYPos	=	$FFFFF71E
    
    
    
    ; ===========================================================================
    
    ; ---------------------------------------------------------------------------
    
    ; Subroutine to	draw only the BG void tiles
    
    ; ---------------------------------------------------------------------------
    
    
    
    sub_6886:
    
    		lea	($C00000).l,a6				; load VDP data port
    
    		lea	$04(a6),a5				; load VDP address port
    
    		moveq	#$FFFFFFF0,d3				; prepare -10
    
    		bra	BGH_Draw				; continue
    
    
    
    ; ===========================================================================
    
    ; ---------------------------------------------------------------------------
    
    ; Drawing the FG Tiles in void space
    
    ; ---------------------------------------------------------------------------
    
    
    
    LoadTilesAsYouMove:
    
    		lea	($C00000).l,a6				; load VDP data port
    
    		lea	$04(a6),a5				; load VDP address port
    
    		lea	($FFFFA400).w,a4			; load FG layout space
    
    		move.w	#$4000,d6				; prepare VRAM plane address
    
    		moveq	#$FFFFFFF0,d3				; prepare -10
    
    
    
    ; ---------------------------------------------------------------------------
    
    ; FG Horizontal
    
    ; ---------------------------------------------------------------------------
    
    
    
    		move.w	($FFFFF700).w,d4			; load X position
    
    		move.w	($FFFFF704).w,d5			; load Y position
    
    		add.w	d3,d4					; move X back into void space
    
    		move.w	d5,d0					; copy Y pos to d0
    
    		and.w	d3,d0					; keep in range
    
    		add.w	d3,d5					; move Y back into void space
    
    		move.w	(LastFGYPos).w,d1			; load last Y position
    
    		and.w	d3,d1					; keep in range
    
    		move.w	d0,(LastFGYPos).w			; update new last Y position
    
    		sub.w	d1,d0					; minus last from new
    
    		beq	FGH_NoDraw				; if it hasn't moved, branch
    
    		bmi	FGH_UpDraw				; if it's moved up, branch
    
    		addi.w	#$00F0,d5				; increase Y down into lower void space
    
    
    
    FGH_UpDraw:
    
    		moveq	#$00,d7					; clear d7
    
    		move.b	($FFFFF74C).w,d7			; load number of horizontal blocks to draw
    
    		bsr	HorizLoadBlocks				; draw horizontal blocks
    
    
    
    FGH_NoDraw:
    
    
    
    ; ---------------------------------------------------------------------------
    
    ; FG Vertical
    
    ; ---------------------------------------------------------------------------
    
    
    
    		move.w	($FFFFF700).w,d4			; load X position
    
    		move.w	($FFFFF704).w,d5			; load Y position
    
    		add.w	d3,d5					; move Y back into void space
    
    		move.w	d4,d0					; copy X pos to d0
    
    		and.w	d3,d0					; keep in range
    
    		add.w	d3,d4					; move X back into void space
    
    		move.w	(LastFGXPos).w,d1			; load last X position
    
    		and.w	d3,d1					; keep in range
    
    		move.w	d0,(LastFGXPos).w			; update new last X position
    
    		sub.w	d1,d0					; minus last from new
    
    		beq	FGV_NoDraw				; if it hasn't moved, branch
    
    		bmi	FGV_LeftDraw				; if it's moved right, branch
    
    		addi.w	#$0150,d4				; increase X down into right void space
    
    
    
    FGV_LeftDraw:
    
    		moveq	#$00,d7					; clear d7
    
    		move.b	($FFFFF74D).w,d7			; load number of vertical blocks to draw
    
    		bsr	VertiLoadBlocks				; draw vertical blocks
    
    
    
    FGV_NoDraw:
    
    
    
    ; ---------------------------------------------------------------------------
    
    ; Drawing the BG Tiles in void space
    
    ; ---------------------------------------------------------------------------
    
    
    
    BGH_Draw:
    
    		lea	($FFFFA440).w,a4			; load BG layout space
    
    		move.w	#$6000,d6				; prepare VRAM plane address
    
    
    
    ; ---------------------------------------------------------------------------
    
    ; BG Horizontal
    
    ; ---------------------------------------------------------------------------
    
    
    
    		move.w	($FFFFCC02).w,d4			; load X position (From scroll buffer)
    
    		neg.w	d4					; reverse
    
    		subi.w	#$0010,d4				; move X back into void space
    
    		move.w	($FFFFF70C).w,d5			; load Y position
    
    		move.w	d5,d0					; copy Y pos to d0
    
    		and.w	d3,d0					; keep in range
    
    		add.w	d3,d5					; move Y back into void space
    
    		move.w	(LastBGYPos).w,d1			; load last Y position
    
    		and.w	d3,d1					; keep in range
    
    		move.w	d0,(LastBGYPos).w			; update new last Y position
    
    		sub.w	d1,d0					; minus last from new
    
    		beq	BGH_NoDraw				; if it hasn't moved, branch
    
    		bmi	BGH_UpDraw				; if it's moved up, branch
    
    		addi.w	#$00F0,d5				; increase Y down into lower void space
    
    		move.w	($FFFFCFC2).w,d4			; load X position (From scroll buffer)
    
    		neg.w	d4					; reverse
    
    		add.w	d3,d4					; move X back into void space
    
    
    
    BGH_UpDraw:
    
    		moveq	#$00,d7					; clear d7
    
    		move.b	($FFFFF74E).w,d7			; load number of horizontal blocks to draw
    
    		bsr	HorizLoadBlocks				; draw horizontal blocks
    
    
    
    BGH_NoDraw:
    
    
    
    ; ---------------------------------------------------------------------------
    
    ; BG Vertical
    
    ; ---------------------------------------------------------------------------
    
    
    
    		move.w	($FFFFF708).w,d0			; load X position
    
    		move.w	($FFFFF70C).w,d5			; load Y position
    
    		add.w	d3,d5					; move Y back into void space
    
    		move.w	(LastBGXPos).w,d1			; load last X position
    
    		move.w	d0,(LastBGXPos).w			; update new last X position
    
    		sub.w	d1,d0					; minus last from new
    
    		beq	BGV_NoDraw				; if it hasn't moved, branch
    
    		bmi	BGV_LeftDraw				; if it's moved right, branch
    
    		move.w	#$0150,d3				; set void space side to right
    
    
    
    BGV_LeftDraw:
    
    		lea	($FFFFCC02).w,a3			; load scroll address
    
    		moveq	#$00,d7					; clear d7
    
    		move.b	($FFFFF74F).w,d7			; load number of vertical blocks to draw
    
    		bsr	VertiLoadBlocksScroll			; draw vertical blocks using scroll
    
    
    
    BGV_NoDraw:
    
    		rts						; return
    
    
    
    ; ===========================================================================
    
    ; ---------------------------------------------------------------------------
    
    ; Subroutine to load tiles from blocks to a buffer space
    
    ; ---------------------------------------------------------------------------
    
    
    
    HorizLoadBlocks:
    
    		moveq	#$1E,d0					; prepare maximum number of blocks minus 1
    
    		sub.w	d7,d0					; subtract number of blocks to draw
    
    		move.w	d6,-(sp)				; store VRAM address
    
    		move.w	#$B000,d6				; prepare block address
    
    		move.w	d0,-(sp)				; store remaining blocks counter
    
    		move.w	d4,d0					; load X position
    
    		andi.w	#$01F0,d0				; keep in range
    
    		lsr.w	#$02,d0					; divide by 4 (every 10 pixels is 4 bytes of a double tile)
    
    		lea	(TileBuffer).w,a2			; load beginning of tile buffer
    
    		adda.w	d0,a2					; advance to correct tile buffer address
    
    		lea	$80(a2),a3				; ''
    
    
    
    HLB_NextBlock:
    
    		movea.w	d6,a1					; load block address
    
    		move.w	d4,d0					; load X position
    
    		lsr.w	#$08,d0					; divide by 100
    
    		andi.w	#$003F,d0				; keep in range
    
    		move.w	d5,d1					; load Y position
    
    		lsr.w	#$01,d1					; divide by 2 (100 to 80)
    
    		andi.w	#$0380,d1				; keep in range
    
    		or.w	d0,d1					; save X onto Y
    
    		moveq	#$FFFFFFFF,d0				; prepare RAM space FFFF????
    
    		move.b	(a4,d1.w),d0				; load chunk ID
    
    		beq.s	HLB_NullChunk				; if null, branch
    
    		subq.b	#$01,d0					; minus 1
    
    		andi.w	#$007F,d0				; keep in range
    
    		ror.w	#$07,d0					; multiply by 200
    
    		move.w	d4,d1					; load X position
    
    		lsr.w	#$03,d1					; divide by 8
    
    		andi.w	#$001E,d1				; keep in range of 20 in multiples of 2
    
    		move.w	d5,d2					; load Y position
    
    		add.w	d2,d2					; multiply by 2
    
    		andi.w	#$01E0,d2				; keep in range of 200 in multiples of 10
    
    		or.w	d2,d1					; save Y onto X
    
    		or.w	d1,d0					; save to chunk address
    
    		move.l	d0,a0					; set chunk address
    
    		move.w	(a0),d0					; load block ID
    
    		andi.w	#$03FF,d0				; clear flags
    
    		lsl.w	#$03,d0					; multiply by 8
    
    		adda.w	d0,a1					; advance to correct block address
    
    
    
    HLB_NullChunk:
    
    		move.l	(a1)+,d0				; load top two tiles
    
    		move.l	(a1)+,d1				; load bottom two tiles
    
    		btst	#$03,(a0)				; was the block mirrored?
    
    		beq	HLB_NoMirror				; if not, branch
    
    		eori.l	#$08000800,d0				; set mirror bits
    
    		eori.l	#$08000800,d1				; ''
    
    		swap	d0					; swap tiles over
    
    		swap	d1					; ''
    
    
    
    HLB_NoMirror:
    
    		btst	#$04,(a0)				; was the block flipped?
    
    		beq	HLB_NoFlip				; if not, branch
    
    		eori.l	#$10001000,d0				; set flip bits
    
    		eori.l	#$10001000,d1				; ''
    
    		exg	d0,d1					; swap tiles over
    
    
    
    HLB_NoFlip:
    
    		move.l	d0,(a2)+				; save top two tiles
    
    		move.l	d1,(a3)+				; save bottom two tiles
    
    		sub.w	d3,d4					; increase X position to next block
    
    		move.w	d4,d0					; copy to d0
    
    		andi.w	#$01F0,d0				; keep in range of the plane size
    
    		bne	HLB_NoEnd				; if it has not wrapped back to the beginning, branch
    
    		lea	(TileBuffer).w,a2			; reload tile buffer from beginning
    
    		lea	$80(a2),a3				; ''
    
    
    
    HLB_NoEnd:
    
    		dbf	d7,HLB_NextBlock			; repeat til done
    
    		move.w	(sp)+,d7				; load remaining blocks counter
    
    		bmi	HBL_NoClearBuffer			; if there's none, branch
    
    		moveq	#$00,d0					; clear d0
    
    
    
    HBL_ClearBuffer:
    
    		move.l	d0,(a2)+				; clear buffer
    
    		move.l	d0,(a3)+				; ''
    
    		dbf	d7,HBL_ClearBuffer			; repeat til done
    
    
    
    HBL_NoClearBuffer:
    
    		move.w	(sp)+,d6				; restore VRAM address
    
    		move.l	#$977F0000,d0				; prepare DMA source value
    
    		move.w	d5,d0					; load Y position
    
    		andi.w	#$00F0,d0				; keep in range
    
    		lsl.w	#$04,d0					; multiply by 10 (every 10 pixels is VRAM 0100+)
    
    		or.w	d6,d0					; set VRAM write bit
    
    		move.l	#((((((HBufferSize*$02)/$02)<<$08)&$FF0000)+(((HBufferSize*$02)/$02)&$FF))+$94009300),(a5) ; set DMA size
    
    		move.l	#((((((TileBuffer&$FFFFFF)/$02)<<$08)&$FF0000)+(((TileBuffer&$FFFFFF)/$02)&$FF))+$96009500),(a5) ; set DMA Source
    
    		move.l	d0,(a5)					; set DMA source/destination
    
    		move.w	#$0083,(a5)				; set DMA destination
    
    		rts						; return
    
    
    
    ; ===========================================================================
    
    ; ---------------------------------------------------------------------------
    
    ; Subroutine to load tiles from blocks to a buffer space
    
    ; ---------------------------------------------------------------------------
    
    
    
    VertiLoadBlocks:
    
    		move.w	d5,d0					; load Y position
    
    		andi.w	#$00F0,d0				; keep in range
    
    		lsr.w	#$02,d0					; divide by 4 (every 10 pixels is 4 bytes of a double tile)
    
    		lea	(TileBuffer).w,a2			; load beginning of tile buffer
    
    		adda.w	d0,a2					; advance to correct tile buffer address
    
    		lea	$80(a2),a3				; ''
    
    		move.w	d6,-(sp)				; store VRAM location
    
    		move.w	#$B000,d6				; prepare block address
    
    
    
    VLB_NextBlock:
    
    		movea.w	d6,a1					; load block address
    
    		move.w	d4,d0					; load X position
    
    		lsr.w	#$08,d0					; divide by 100
    
    		andi.w	#$003F,d0				; keep in range
    
    		move.w	d5,d1					; load Y position
    
    		lsr.w	#$01,d1					; divide by 2 (100 to 80)
    
    		andi.w	#$0380,d1				; keep in range
    
    		or.w	d0,d1					; save X onto Y
    
    		moveq	#$FFFFFFFF,d0				; prepare RAM space FFFF????
    
    		move.b	(a4,d1.w),d0				; load chunk ID
    
    		beq.s	VLB_NullChunk				; if null, branch
    
    		subq.b	#$01,d0					; minus 1
    
    		andi.w	#$007F,d0				; keep in range
    
    		ror.w	#$07,d0					; multiply by 200
    
    		move.w	d4,d1					; load X position
    
    		lsr.w	#$03,d1					; divide by 8
    
    		andi.w	#$001E,d1				; keep in range of 20 in multiples of 2
    
    		move.w	d5,d2					; load Y position
    
    		add.w	d2,d2					; multiply by 2
    
    		andi.w	#$01E0,d2				; keep in range of 200 in multiples of 10
    
    		or.w	d2,d1					; save Y onto X
    
    		or.w	d1,d0					; save to chunk address
    
    		move.l	d0,a0					; set chunk address
    
    		move.w	(a0),d0					; load block ID
    
    		andi.w	#$03FF,d0				; clear flags
    
    		lsl.w	#$03,d0					; multiply by 8
    
    		adda.w	d0,a1					; advance to correct block address
    
    
    
    VLB_NullChunk:
    
    		move.w	(a1)+,d0				; load left tile 1
    
    		move.w	(a1)+,d1				; load right tile 1
    
    		swap	d0					; send left
    
    		swap	d1					; ''
    
    		move.w	(a1)+,d0				; load left tile 2
    
    		move.w	(a1)+,d1				; load right tile 2
    
    		btst	#$03,(a0)				; was the block mirrored?
    
    		beq	VLB_NoMirror				; if not, branch
    
    		eori.l	#$08000800,d0				; set mirror bits
    
    		eori.l	#$08000800,d1				; ''
    
    		exg	d0,d1					; swap tiles over
    
    
    
    VLB_NoMirror:
    
    		btst	#$04,(a0)				; was the block flipped?
    
    		beq	VLB_NoFlip				; if not, branch
    
    		eori.l	#$10001000,d0				; set flip bits
    
    		eori.l	#$10001000,d1				; ''
    
    		swap	d0					; swap tiles over
    
    		swap	d1					; ''
    
    
    
    VLB_NoFlip:
    
    		move.l	d0,(a2)+				; save top two tiles
    
    		move.l	d1,(a3)+				; save bottom two tiles
    
    		sub.w	d3,d5					; increase Y position to next block
    
    		move.w	d5,d0					; copy to d0
    
    		andi.w	#$00F0,d0				; keep in range of the plane size
    
    		bne	VLB_NoEnd				; if it has not wrapped back to the beginning, branch
    
    		lea	(TileBuffer).w,a2			; reload tile buffer from beginning
    
    		lea	$80(a2),a3				; ''
    
    
    
    VLB_NoEnd:
    
    		dbf	d7,VLB_NextBlock			; repeat til done
    
    		move.w	(sp)+,d6				; restore VRAM location
    
    		move.l	#$977F0000,d0				; prepare DMA source value
    
    		move.w	d4,d0					; load X position
    
    		andi.w	#$01F0,d0				; keep in range
    
    		lsr.w	#$02,d0					; divide by 2 (every 10 pixels is VRAM 0002+)
    
    		or.w	d6,d0					; set VRAM write bit
    
    		move.w	#$8F80,(a5)				; set auto increment to 80 (next line)
    
    		move.l	#(((((VBufferSize/$02)<<$08)&$FF0000)+((VBufferSize/$02)&$FF))+$94009300),(a5) ; set DMA size
    
    		move.l	#((((((TileBufferA&$FFFFFF)/$02)<<$08)&$FF0000)+(((TileBufferA&$FFFFFF)/$02)&$FF))+$96009500),(a5) ; set DMA Source
    
    		move.l	d0,(a5)					; set DMA source/destination
    
    		move.w	#$0083,(a5)				; set DMA destination
    
    		addq.w	#$02,d0					; advance to tile on right in VRAM address
    
    		move.l	#(((((VBufferSize/$02)<<$08)&$FF0000)+((VBufferSize/$02)&$FF))+$94009300),(a5) ; set DMA size
    
    		move.l	#((((((TileBufferB&$FFFFFF)/$02)<<$08)&$FF0000)+(((TileBufferB&$FFFFFF)/$02)&$FF))+$96009500),(a5) ; set DMA Source
    
    		move.l	d0,(a5)					; set DMA source/destination
    
    		move.w	#$0083,(a5)				; set DMA destination
    
    		move.w	#$8F02,(a5)				; set auto increment back to 02 (word)
    
    		rts						; return
    
    
    
    ; ===========================================================================
    
    ; ---------------------------------------------------------------------------
    
    ; Subroutine to load tiles from blocks to a buffer space
    
    ; ---------------------------------------------------------------------------
    
    
    
    VertiLoadBlocksScroll:
    
    		move.l	#$00800000,a2				; prepare a2 as line shift register value
    
    		move.b	d5,d0					; load Y position
    
    		andi.w	#$000F,d0				; get only within the block position
    
    		add.b	d0,d0					; multiply by 4 (size of scanline data)
    
    		add.b	d0,d0					; ''
    
    		move.w	(a3),d4					; load first scanline position (for first block only)
    
    		suba.w	d0,a3					; shift scroll buffer address to correct beginning scanline of blocks
    
    		bra	VLBS_FirstBlock				; continue
    
    
    
    VLBS_NextBlock:
    
    		move.w	(a3),d4					; load scroll value
    
    
    
    VLBS_FirstBlock:
    
    		lea	$40(a3),a3				; advance to next 10 pixel block space
    
    		neg.w	d4					; reverse scroll value
    
    		add.w	d3,d4					; advance to correct side of screen
    
    		lea	($FFFFB000).w,a1			; load block address
    
    		move.w	d4,d0					; load X position
    
    		lsr.w	#$08,d0					; divide by 100
    
    		andi.w	#$003F,d0				; keep in range
    
    		move.w	d5,d1					; load Y position
    
    		lsr.w	#$01,d1					; divide by 2 (100 to 80)
    
    		andi.w	#$0380,d1				; keep in range
    
    		or.w	d0,d1					; save X onto Y
    
    		moveq	#$FFFFFFFF,d0				; prepare RAM space FFFF????
    
    		move.b	(a4,d1.w),d0				; load chunk ID
    
    		beq.s	VLBS_NullChunk				; if null, branch
    
    		subq.b	#$01,d0					; minus 1
    
    		andi.w	#$007F,d0				; keep in range
    
    		ror.w	#$07,d0					; multiply by 200
    
    		move.w	d4,d1					; load X position
    
    		lsr.w	#$03,d1					; divide by 8
    
    		andi.w	#$001E,d1				; keep in range of 20 in multiples of 2
    
    		move.w	d5,d2					; load Y position
    
    		add.w	d2,d2					; multiply by 2
    
    		andi.w	#$01E0,d2				; keep in range of 200 in multiples of 10
    
    		or.w	d2,d1					; save Y onto X
    
    		or.w	d1,d0					; save to chunk address
    
    		move.l	d0,a0					; set chunk address
    
    		move.w	(a0),d0					; load block ID
    
    		andi.w	#$03FF,d0				; clear flags
    
    		lsl.w	#$03,d0					; multiply by 8
    
    		adda.w	d0,a1					; advance to correct block ID
    
    
    
    VLBS_NullChunk:
    
    		move.w	d4,d2					; load X position
    
    		andi.w	#$01F0,d2				; keep within 200 pixels in multiples of 10
    
    		lsr.w	#$02,d2					; divide by 4
    
    		move.w	d5,d1					; load Y position
    
    		andi.w	#$00F0,d1				; keep within 100 pixels in multiples of 10
    
    		lsl.w	#$04,d1					; multiply by 10
    
    		or.w	d1,d2					; save Y onto X
    
    		or.w	d6,d2					; save VRAM address
    
    		swap	d2					; send left
    
    		move.w	#$0003,d2				; set VRAM address
    
    		move.l	(a1)+,d0				; load top two tiles
    
    		move.l	(a1)+,d1				; load bottom two tiles
    
    		btst	#$03,(a0)				; was the block mirrored?
    
    		beq	VLBS_NoMirror				; if not, branch
    
    		eori.l	#$08000800,d0				; set mirror bits
    
    		eori.l	#$08000800,d1				; ''
    
    		swap	d0					; swap tiles over
    
    		swap	d1					; ''
    
    
    
    VLBS_NoMirror:
    
    		btst	#$04,(a0)				; was the block flipped?
    
    		beq	VLBS_NoFlip				; if not, branch
    
    		eori.l	#$10001000,d0				; set flip bits
    
    		eori.l	#$10001000,d1				; ''
    
    		exg	d0,d1					; swap tiles over
    
    
    
    VLBS_NoFlip:
    
    		move.l	d2,(a5)					; set VDP VRAM address
    
    		move.l	d0,(a6)					; save top two tiles
    
    		add.l	a2,d2					; advance to next line
    
    		move.l	d2,(a5)					; set VDP VRAM address
    
    		move.l	d1,(a6)					; save bottom two tiles
    
    		addi.w	#$0010,d5				; increase Y position to next block
    
    		dbf	d7,VLBS_NextBlock			; repeat til done
    
    		rts						; return
    
    
    
    ; ===========================================================================
    
    ; ---------------------------------------------------------------------------
    
    ; Subroutine to	draw the entire level tiles on screen
    
    ; ---------------------------------------------------------------------------
    
    
    
    LoadTilesFromStart:
    
    		lea	($FFFFA400).w,a4			; load FG layout space
    
    		move.w	#$4000,d6				; prepare VRAM plane address
    
    		move.w	($FFFFF700).w,d4			; load X position
    
    		move.w	($FFFFF704).w,d5			; load Y position
    
    		bsr	LoadFGTilesFromStart			; draw FG
    
    		lea	($FFFFA440).w,a4			; load BG layout space
    
    		move.w	#$6000,d6				; prepare VRAM plane address
    
    		move.w	($FFFFF708).w,d4			; load BG X position
    
    		move.w	($FFFFF70C).w,d5			; load BG Y position
    
    
    
    ; ---------------------------------------------------------------------------
    
    ; Subroutine to	draw only the entire BG tiles
    
    ; ---------------------------------------------------------------------------
    
    
    
    LoadBGTilesFromStart:
    
    		lea	($C00000).l,a6				; load VDP data port
    
    		lea	$04(a6),a5				; load VDP address port
    
    		moveq	#$FFFFFFF0,d3				; prepare -10
    
    		add.w	d3,d4					; move X and Y positions back into void space
    
    		add.w	d3,d5					; ''
    
    		moveq	#$0F,d7					; set number of horizontal lines to draw
    
    		lea	($FFFFCC02).w,a3			; load scroll address
    
    		move.b	d5,d0					; load Y position
    
    		andi.w	#$000F,d0				; get only within the block position
    
    		add.b	d0,d0					; multiply by 4 (size of scanline data)
    
    		add.b	d0,d0					; ''
    
    		move.w	(a3),d4					; load first scanline position (for first block only)
    
    		suba.w	d0,a3					; shift scroll buffer address to correct beginning scanline of blocks
    
    		bra	DABG_FirstBlock
    
    
    
    DABG_NextLine:
    
    		move.w	(a3),d4					; load scroll value
    
    
    
    DABG_FirstBlock:
    
    		lea	$40(a3),a3				; advance to next 10 pixel block space
    
    		neg.w	d4					; reverse scroll value
    
    		add.w	d3,d4					; advance to correct side of screen (left side)
    
    		movem.w	d4/d7/a3,-(sp)				; store X pos and counter
    
    		moveq	#$1F,d7					; set repeat times (number of blocks) (20 blocks)
    
    		bsr	HorizLoadBlocks				; draw horizontal blocks
    
    		movem.w	(sp)+,d4/d7/a3				; restore X pos and counter
    
    		sub.w	d3,d5					; increase Y pos down
    
    		dbf	d7,DABG_NextLine			; repeat til all lines are done
    
    		rts						; return
    
    
    
    ; ---------------------------------------------------------------------------
    
    ; Subroutine to	draw only the entire FG tiles
    
    ; ---------------------------------------------------------------------------
    
    
    
    LoadFGTilesFromStart:
    
    		lea	($C00000).l,a6				; load VDP data port
    
    		lea	$04(a6),a5				; load VDP address port
    
    		moveq	#$FFFFFFF0,d3				; prepare -10
    
    		add.w	d3,d4					; move X and Y positions back into void space
    
    		add.w	d3,d5					; ''
    
    		moveq	#$0F,d7					; set number of horizontal lines to draw
    
    
    
    DAFG_NextLine:
    
    		movem.w	d4/d7,-(sp)				; store X pos and counter
    
    		moveq	#$1F,d7					; set repeat times (number of blocks) (20 blocks)
    
    		bsr	HorizLoadBlocks				; draw horizontal blocks
    
    		movem.w	(sp)+,d4/d7				; restore X pos and counter
    
    		sub.w	d3,d5					; increase Y pos down
    
    		dbf	d7,DAFG_NextLine			; repeat til all lines are done
    
    		rts						; return
    
    
    
    ; ===========================================================================

    And that's it, you now have unlimited scroll positions with the draw code in sync.


    It's important to understand that you can get lag from this, the reason is simply down to the draw code having to check the scroll buffer for each block, and because there isn't enough RAM space to store a second scroll buffer, the previous positions of the scroll buffer cannot be stored, so the draw code has to update ALL blocks even if the BG only moves a pixel, this is for BG horizontal movement only though, and the DMA transfers and optimisation of the other routines makes up for this enough, so much so that you should feel virtually no lag if you do not have debug mode enabled.


    When using, before, you were required to write from CC00 to CF7F, that is exactly E0 scanlines, now, you are required to write from CC00 to CFFF, where CC40 to CFBF is the E0 scanlines that are displayed, the reason why you need to write scanlines that are not on screen, is so that the draw code knows where the blocks are to be drawn (blocks are drawn outside the screen in a void space, not inside in full view), So be sure to write all positions down in the buffer, not doing so may result in blocks being drawn in the wrong place outside the screen, which may be viewable when the screen moves in.


    In addition, F700 and F704 are the FG's X and Y positions, the FG blocks will update when those positions are changed, F708 and F70C are the BG's X and Y positions, the BG blocks will update when those positions are changed. It doesn't matter if you do not use F708 or F70C for the actual scroll position or not, the actual draw code itself will NOT update unless the specified RAM locations above have been changed, so be sure to change them in some way if you do not use them directly.


    Additional notes are, this will not use up any additional space, the RAM locations from FFF718 to FFF71F (which would have been used for a scroll block), are now used as the last frame's FG and BG locations, while the space at FFA800 to FFA9FF (which is used for SLZ's block scrolling), is used for storing the tile values before DMA transfer, and because of the nature of SLZ only using that space temporarily, it can be used for the DMA transfer without consequences, so there are no additional RAM spaces you'll be required to sacrifice.
     
    Last edited by a moderator: May 9, 2012
    Nat The Porcupine likes this.
  2. Irixion

    Irixion Well-Known Member Member

    Joined:
    Aug 11, 2007
    Messages:
    670
    Location:
    Ontario, Canada
    Nicely done! Where can we expect to see lag from this? I mean, does it put that much stress on the system? If S2 has four instead of the three, how does S3K do this? :s
     
  3. MarkeyJester

    MarkeyJester ♡ ! Member

    Joined:
    Jun 27, 2009
    Messages:
    2,867
    You can expect to see lag when lossing a lot of rings (which is no suprise at all), or if you have debug mode enabled, it's not "much" strain though.


    Here's a ROM.


    And FYI, fuck S3K, there's no good assuming it has all the answers, I can see a lot of backgrounds in S3K that have a very repetetive design (HCZ for example), where such a background can be loaded onto the entire BG plane, and where no horizontal movement (vertical line) drawing is required, which I'm pretty sure is what they did, which you can equally do with this (Just don't change the FFF708 value), with no horizontal movement (vertical line) drawing, the lag will disolve drastically, but it means having your backgrounds kept within 2 chunks on an X line (or 4 if you have 128x128 chunks).


    EDIT: I've made some new changes to the draw code now, the processing times appears near equal to a standard Sonic 1 ROM.
     
    Last edited by a moderator: May 9, 2012
  4. EMK-20218

    EMK-20218 The Fuss Maker Exiled

    Joined:
    Aug 8, 2008
    Messages:
    1,067
    Location:
    Jardim Capelinha, São Paulo
    Sorry for the one-month bump >_<


    But I didn't figured how to use this code in my hack because it uses a 128x128 chunk system which had been ported from Sonic 2 Final. I got confused on the part which says to remove the draw code from sub_6886, because I noticed that the first section of this code was already commented on my source, and it looks a bit different from the Sonic 1's default code. My question is: Is this applied for the sources which has the 128x128 system implemented? If yes, does it needs another adaptions? (Two-Eight, Kraminator...)
     
Thread Status:
Not open for further replies.