Where does Sonic 1 Calculate SMPS Tempo?

Discussion in 'Discussion & Q&A' started by SMS Alfredo, Sep 5, 2018.

  1. SMS Alfredo

    SMS Alfredo Compact Disc Enthusiast Member

    Sep 3, 2018
    Little Planet
    So, as I'm pretty sure anyone that has worked even a tiny bit with SMPS knows, tempo is calculated using divider and modifier numbers. The problem with this system is that tempos with a divider of 02 are really the only ones you'll ever use. And even then, it's only between 75 and 149.4141 BPM. This is bad for me as I want to put songs in with tempos like 160 and 180 BPM.

    However, I think I've worked out a possible solution. Basically I'll write code where Sonic 1 calculates SMPS tempo that checks for some useless combo of the tempo values (like 05 36). If it comes out true, then I'll have it branch to code that returns a value that causes 160 or 180 BPM instead of going through the normal Tempo Calculation.

    ...except I've kinda run into a road block here. I have no idea where Sonic 1 even calculates SMPS tempo.
    And that's where you guys come in. Do you know where in the code it is? I'm using the Hivebrain 2005 disasembly if that helps at all.
  2. MarkeyJester

    MarkeyJester ♡ ! Member

    Jun 27, 2009
    Under "loc_71B82:" you will have:
    		subq.b	#1,1(a6)
    		bne.s	loc_71B9E
    		jsr	sub_7260C(pc)
    Which is responsible for the "frame" tempo (the 36 from your 05 36), and:
    sub_71D40:				; XREF: sub_71C4E; sub_71CEC; sub_72878
    		move.b	d5,d0
    		move.b	2(a5),d1
    		subq.b	#1,d1
    		beq.s	loc_71D4E
    		add.b	d5,d0
    		bra.s	loc_71D46
    ; ===========================================================================
    		move.b	d0,$F(a5)
    		move.b	d0,$E(a5)
    This is on a per channel basis, this one is responsible for the "divider" tempo the (the 05 from your 05 36).

    What you will probably want is a carry based tempo system, probably something along the lines of:
    		move.b	$02(a6),d0			; load tempo
    		add.b	d0,$01(a6)			; increase carry counter
    		bcc.s	NoSlowMusic			; if carry has not been set, branch
    		lea	$40+$0E(a6),a0			; load channel RAM (starting from timer)
    		moveq	#5+1+3,d1			; number of channels (5 FM, 1 DAC, 3 PSG)
    		addq.b	#$01,(a0)			; extend timer by an extra frame
    		lea	$30(a0),a0			; advance to next channel
    		dbf	d1,SlowChannel			; repeat for all channels
    ...which will cause a smoother change from 00 (fastest) to FF (slowest), this is not necessarily the best design out there, in fact, you could simply skip the whole driver for a frame if carry is set if you wanted which would cause FM LFO (modulation flag) to slow down too, which is entirely up to you. If you would prefer it being 00 slowest to FF fastest, then you could subsitute the "bcc" for a "bcs" and it'll function in reverse.

    Some newer SMPS drivers may have another solution which you could back-port if necessary. If you are after more precise tempos than this, then the above can be used, but you will be adding a word rather than a byte which should extend the precision by an extra x $100.
    Deactivated Account and Niko like this.

    AURORA☆FIELDS so uh yes Exiled

    Oct 7, 2011
    For the overflow method that Markey is talking about, I created a tutorial for how to port it. It should be in the tutorials section of the forums.
  4. SMS Alfredo

    SMS Alfredo Compact Disc Enthusiast Member

    Sep 3, 2018
    Little Planet
    Thanks for both of your replies, I tried the tutorial and it works perfectly for my needs!

    Guess I should check the tutorials section next time before making a thread.
  5. StephenUK

    StephenUK Working on a Quackshot disassembly Member

    Aug 5, 2007
    To be fair, until Natsumi contacted me the tutorial was stored away in the temporary archives so you wouldn't have found it. Entirely our fault there so don't worry about it
  6. LazloPsylus

    LazloPsylus The Railgun Member

    Nov 25, 2009
    Academy City
    Archive sorting has been abandoned for now, so they're all back in public view. Enjoy.
    RouRouRou, AkumaYin and Pacca like this.
  7. RouRouRou

    RouRouRou Ain't no fun if the aliens can't have none. Member

    Nov 20, 2016
    Thanks for bringing back the guides, I might try this one sometime as well. I didn't realise that they were on the front page. Although, the attached files don't download.
    Edit: Rewrote this whole thing.
    Edit - The Return: Added some more.
    Last edited: Sep 6, 2018
  8. ValleyBell

    ValleyBell Well-Known Member Member

    Dec 23, 2011
    I'm not exactly answering the question, but I feel the need to comment, because SMS Alfredo is obviously using mid2smps and its tempo calculator.

    A tempo divider of 1 is commonly used. (And if you know what you're doing, you can use a tempo divider of 4. My SMPS competition submission for round 39 used TpQ 6 with TDiv 4.)

    What controls the tempo range is the "Ticks per Quarter" setting (I'll call it TpQ) in the main dialog of mid2smps.

    With a setting of TpQ 24 and TDiv 1 (or TpQ 12 and TDiv 2, which is the default), you get a range of 75 to 150 BPM.
    If you use TpQ 16 and TDiv 1, you get a range of 112.5 to 225 BPM.
    Use TpQ 20 and TDiv 1 for 90 to 180 BPM.
    As you can see, playing with the TpQ setting allows you to access various BPM ranges. And you don't even need to modify the sound driver for it.

    Just make sure that your TpQ setting is always a multiple of 4 or you will get jittery playback. Or use multiples of 3 if you have a song with swing/shuffle rhythm.
    Deactivated Account likes this.
  9. SMS Alfredo

    SMS Alfredo Compact Disc Enthusiast Member

    Sep 3, 2018
    Little Planet
    Well I feel kinda stupid. I guess I just didn't really understand what the TpQ was supposed to be for.
    Then again, mid2smps never really tells you what it does, even in the Readme.

    I'm still probably going to keep the S3K tempo system though, as it allows for more accuracy.
    Thanks for the insight!