- Group:
- Tech Member: Tech Members
- Active Posts:
- 312 (0.42 per day)
- Most Active In:
- Engineering & Reverse Engineering (226 posts)
- Joined:
- 06-July 13
- Profile Views:
- 9790
- Last Active:
14 minutes ago- Currently:
- Viewing Board Index
My Information
- Member Title:
- Needs to make an avatar
- Age:
- Age Unknown
- Birthday:
- August 22
- Gender:
-
Male
- Location:
- Englandland
Contact Information
- E-mail:
- Private
Previous Fields
- National Flag:
- uk
- SA2 Emblems:
- 5
Latest Visitors
-
Super Egg 
18 Jul 2015 - 13:28 -
JorgeBunny 
10 Jun 2015 - 17:25 -
NeoFusionBox 
25 May 2015 - 13:59 -
TheStoneBanana 
01 May 2015 - 04:12 -
nineko 
14 Apr 2015 - 04:26
Topics I've Started
-
Help with porting S3K's layout format?
26 May 2015 - 05:10 PM
Where to begin... Well, I ported S3K's layout format to my S2 hack. I thought I had a pretty good idea of how it all worked, and have been able to track down and fix every issue encountered (outside of a recently-discovered bug in WFZ I'm sure I can fix). All but one, anyhow.
MCZ's background now loads incorrect blocks as you progress through the level. I've been unable to find any code remotely related to layout reading outside of what I've already changed, so I'm lost as to what the problem could possibly be. It's not something I've encountered with any other level, and it appears even in otherwise-stock S2. That said, making MCZ use the 'standard' BG deformation instead of its own doesn't seem to incur the bug. I'll add some pics or a ROM when I get the chance.
So, erm, yeah. Can anyone spare a little help, here? -
S1-friendly improved Sonic 2 sound driver
19 April 2015 - 05:30 PM
Have you ever wanted to replace your Sonic 1 sound driver with Sonic 2's? Less buggy, doesn't need loads of (non-Z80) RAM, frees up a little of the 68k, and is more compatible with the original music and SFX than S3K's driver.
It's certainly possible, but bumps in the road are plentiful, and soon, limitations of S2's driver will get in your way. The driver isn't the most usable: compression woes, the mess of porting the thing in the first place, there are only two music banks, one DAC bank, and a very limited number of music slots. Not to mention, the driver itself has very little room for additions to the code. There's also the total lack of support for Special SFX, which GHZ's waterfall uses, and the MZ push SFX behaviour.
Over time, there have come guides that correct these, and it seems the only hurdle left is S1 support. The process is a little... involved, so, rather than a guide, I think something pre-made would be better. I might still eventually split some of this into guides, but that's for another time.
I suppose I should bring up one interesting barrier, sound driver compression: Sonic 2's disasm assembles and compresses the driver at build time. The compression used is Saxman. S3K's and S1's disasms don't do this. Until recently, S1 didn't compress anything at all, but the addition of a disassembled Z80 DAC driver necessitated the addition of a compress-to-Kosinski function, which S3K also has. Changing this would require the user compile a modified s1p2bin. It would be easier to just make the driver settle for Kosinski compression, which I think is better, anyway.
Anyhow, here's a features list.
Features:
- No Saxman-compressed music - Free up a lot of Z80 RAM
- Driver is Kosinski-compressed - Better compression, so it seems. Also, S1's disasm supports this by default
- Support for >2 music banks
- Support for >1 DAC banks
- Additional bugfixes
- Smaller FM frequencies table - More RAM
- S3K PSG frequency range
- Track RAM optimisation - More RAM
- Greater sound ID range - $01-$FF
- No sndDriverInput - Writes are direct, a la S3K
- Restored broken sound queue - Used for music

- DAC auto-bankswitch - No need to worry about sample alignment
- SMPS2ASM
- Toggleable features - What you do need, and what you don't
- Special SFX support
- MZ block push SFX support
- CPZ's gloop SFX support
- Spin dash rev SFX support
- Sonic 2 PSG envelopes
- Sonic 2 DAC samples
- Special SFX support
Download (code) | Download (ROM)
S1 VS S2:
Spoiler
Installation:
Spoiler
Fixing up the SEGA screen:
Spoiler
Correcting silence on screenmode change:
Spoiler
Expanding sound test:
Spoiler
Removing needless Z80 stops:
Spoiler
Changelog:
Spoiler
Credits:
Valley Bell - Bugfixes, S2Beta4 driver disassembly (source of Push SFX support)
Flamewing - SMPS2ASM, >$1F songs expansion, pointing out S3K's additional frequency values, improvement for DAC channel register setting
Vladikcomper - Elements of the DAC-related improvements
Clownacy - Making the driver good - No Saxman-compressed music - Free up a lot of Z80 RAM
-
Making Sonic 2's sound driver good
17 March 2015 - 06:31 PM
Because of its relation to S1's driver (it's a fixed Z80 port of it), I've been fooling around with S2's driver more than ever, and I've found some interesting things. So what say we give this driver some level of technical competence?
I have quite a few changes here that eventually link with each other, so if you're gonna follow along, don't skip anything. Also, flamewing's stuff ties into this, so check that out beforehand. It doesn't hurt to check out the other improvements scattered around my driver's topic (and here, and here, and here).
Optimising zWriteFMI/zWriteFMII
Spoiler
Adding common bankswitch subroutine
Spoiler
Improving common bankswitch subroutine
Spoiler
Optimising DAC playback loop
Spoiler
Adding multiple DAC banks
Spoiler
Adding automatic DAC bankswitching
Spoiler
From here, these are just small changes that don't impact each other.
Saving a bank
Spoiler
Making the jump tables smaller
Spoiler -
Strange fix to test out
11 January 2015 - 06:08 PM
Now, I've seen in S1 hacks, like Metal Sonic Hyperdrive, that when the title card makes the level fade in, the level art and the objects are slightly off-centre, causing the camera to move up or to down to align them once the gameplay begins. It's only for a couple of frames, but damn is it annoying. Porting S1's title card to S2 presents the same problem, only with the default zones. I've never noticed this bug with stock S1, but since I've seen it in hacks with new levels, I believe it's in there too, only it's masked in some way by the level design.
Now, to anyone who is experiencing this, I think I found a fix. More of a messy workaround, but it doesn't seem to work otherwise. I've only tested this with my S2 port, but... well, just give it a go.
For S2 users, under the '+' under Level_TtlCard, comment out the branch to JmpTo_DeformBgLayer.
Then, directly under Level_ClrHUD, add these lines:
jsr (ObjectsManager).l jsr (RunObjects).l jsr (BuildSprites).l
Then, at Level_FromCheckpoint, under the branch to SetLevelEndType, add that 'bsr.w JmpTo_DeformBgLayer' you removed earlier.
For S1 users, you should just move the branch to DeformLayers, under Level_SkipTtlCard, to under the branch to OscillateNumInit, under Level_SkipClr. You might also have to copy the three 'jsr's under to Level_LoadObj to there, also.
It's not what I'd call a sound fix, but giving the objects some more time to process, and deforming the background after some other stuff has been done seems to do the trick.
Anyone else have any input on this bug? -
How to improve PCM playback quality with Sonic 2's sound driver
29 December 2014 - 09:31 PM
So, get this: in Sonic 2, if you go to the sound test and play sound 7A, you get this horrible version of the Sega chant, but it sounds fine on the Sega screen. If you have an ear for it, apparently even the DAC drums are like that. As Vladikcomper said before, this is because of the Z80 being stopped frequently. Thing is, there are many times when it's being stopped for no flaming reason. For the most part, anyway. Here, we'll be doing what we can to fix that.
Unfortunately, hardware users won't see much benefit from this. The Sega sound only sounds slightly less strangled. It seems DMA still does a huge number on sound quality. Emulators sound better, though. What can't be helped is the DAC playback. As, no matter how much we optimise things on the 68k side, the Z80 will interrupt itself with V-Int, butchering the DAC quality. The Sega sound works around that by disabling interrupts, but that comes at the cost of pausing the entire sound driver. That said, hope you like splash screens. If that's your cup of tea, onto the guide!
First let's get something minor out of the way.
Replacing the current music pause/unpause system
The way the current system works will interfere with our upcoming modifications, so we're effectively gonna cut it out. But we still need the basic functionality, so we'll replace it with something more... direct.
Open s2.constants.asm, and find the definitions of MusID_Pause and MusID_Unpause. Make them $7F and $80, respectively.
Now find the only use of MusID_Pause in s2.asm. It should be but a single instruction:
move.b #MusID_Pause,(Music_to_play).w ; pause music
The address it writes to is part of a relay system we're going to be removing, sndDriverInput. You can study it yourself to see how it operates, but all you need to know is that it has some special-case code for MusID_Pause/Unpause, which writes $7F or $80 to zStopMusic. So, to take sndDriverInput out of the equation, we'll do this ourselves, which is why we changed MusID_Pause/Unpause's definitions from a sound ID to the data they'd eventually represent. Surround this lone instruction with stopZ80 and startZ80 (since the 68k can't write to the Z80's address space otherwise), and change the address '(Music_to_play).w' to '(Z80_RAM+zStopMusic).l'. Done. Now onto MusID_Unpause.
You should know the drill. It's exactly the same: stick a stopZ80 before the instruction, and a startZ80 after it; then change the destination address to '(Z80_RAM+zStopMusic).l'. Do this for all instances.
It's safe to build and test, but hang on! None of the sound commands are working! Music doesn't fade, the Sega chant doesn't play... At least the new pause works, but we gotta fix that bug!
Open s2.sounddriver.asm. Again, there's some special-case code that we gotta deal with. Go to zPlaySoundByIndex, and you'll find that it uses MusID_Pause. It's part of a check to invalidate sound IDs $FE and $FF, which used to be the original MusID_Pause/Unpause. That isn't the case anymore, and the constant is no longer appropriate, causing the sound commands to be invalidated, as the original MusID_Pause/Unpause would have.
Simply remove the check and the following conditional return, and you'll be as good as gold.
One last little change to make, though: what's gonna happen to sound IDs $FE and $FF? They're now unused, and are even buggy: try building your ROM and playing those sounds in the sound test. That isn't normal. The fix is simple: shift the sound commands to occupy the now-unused slots. A nice bonus to this is that you free up two sound IDs!
Back in s2.constants.asm, add 2 to all the sound commands: from MusID_StopSFX to MusID_Stop.
That's that done. There's still one last bug, but that'll be fixed later on.
Optimising Z80 stops
There are a lot of times where the Z80 is stopped, even when it doesn't need to be. For example, joypad-related reads and writes. We can do without all that unnecessary junk stopping the Z80. We'll also be removing the stops and starts used for sndDriverInput, which is actually an area where the Z80 should be stopped, but since we'll be removing that, we won't be needing the Z80 to be stopped either. Remember to not remove the ones you added when replacing the pause system.
Look for Z80 stops and starts here:
- VintSub0
- loc_4C4
- loc_54A
- Vint0_noWater
- VintSub14
- VintSub8
- loc_748
- Vint10_specialStage
- loc_86E
- VintSubA
- SS_PNTA_Transfer_Table
- VintSub1A
- VintSubC
- loc_BD6
- VintSub18
- VintSub16
- Do_ControllerPal
- H_Int
- JoypadInit
- ClearScreen
- EndingSequence
Removing the 68k-side sound queuing system
The sound driver itself already has a queuing system, so all this one serves to do is waste cycles and time: as you may have seen when removing all those Z80 stops, sndDriverInput is ran, and pauses the Z80, on every V-Int, and even on H-Int. That's a lot of time for the Z80 to be stopped, so let's get rid of that.
Find and delete sndDriverInput, then remove every branch and jump to it. Bonus: in doing that, we've eliminated that last bug I mentioned earlier.
Of course, in doing that, we've also effectively destroyed the sound queuing. But we'll fix that.
Overhauling PlaySound subroutines
What happens more often? V-Int, or a sound being queued? A frame passing by, or Sonic picking up a ring?
For limiting Z80 idling, PlaySound is simply more appropriate. In fact, S3K has it this way (not that its PCM playback is much better. See the above section on Z80 stops). What we're going to do is merge sndDriverInput and the PlaySound subroutines, regaining the functionality using code that isn't run so excessively often.
Let's start from the top: with PlayMusic. Replace it with this:
; sub_135E: PlayMusic: stopZ80 ; Stop the Z80 so the 68k can write to Z80 RAM cmpi.b #$80,(Z80_RAM+zQueueToPlay).l ; If this (zQueueToPlay) isn't $80, the driver is processing a previous sound request. bne.s + ; So we'll put this sound in a backup queue move.b d0,(Z80_RAM+zQueueToPlay).l ; Queue sound startZ80 ; Start the Z80 back up again so the sound driver can continue functioning rts + ;.usebackupqueue move.b d0,(Z80_RAM+zSFXUnknown).l ; Queue sound startZ80 ; Start the Z80 back up again so the sound driver can continue functioning rts ; End of function PlayMusic
Next up is PlaySound. Replace it with this:
; sub_137C: PlaySoundLocal: tst.b render_flags(a0) bpl.s ++ ; sub_1370 PlaySound: stopZ80 ; Stop the Z80 so the 68k can write to Z80 RAM move.b d0,(Z80_RAM+zSFXToPlay).l ; Queue sound startZ80 ; Start the Z80 back up again so the sound driver can continue functioning + rts ; End of function PlaySound
And, finally, PlaySoundStereo:
; sub_1376: PlaySoundStereo: stopZ80 ; Stop the Z80 so the 68k can write to Z80 RAM move.b d0,(Z80_RAM+zSFXStereoToPlay).l ; Queue sound startZ80 ; Start the Z80 back up again so the sound driver can continue functioning rts ; End of function PlaySoundStereo
Delete the original PlaySoundLocal. Note that if you followed my previous guide on extending the sound IDs from starting at $80 to $00, then those 'cmpi.b #$80's should be replaced with 'tst.b's.
Repairing the unused queue
Now, note that we're making use of an unused sound queue in PlayMusic as a 'backup queue'. This is to replace a lost functionality, where sndDriverInput would 'nag' the sound driver to ensure that a sound would be queued in the next frame if zQueueToPlay isn't currently available. The problem is that, like the one in Sonic 1's driver, this unused queue is half-implemented. Without a backup queue, music writes would be missed, so we've gotta repair this one.
In s2.sounddriver.asm, find zInitMusicPlayback. In there, you'll see some data being backed up, including two queues: the SFX queue and the stereo queue. Note that the unused queue is not. We'll have to add that.
Underneath the third 'push bc', add this:
ld c,(ix+0Bh) ; unused queue slot push bc
And, underneath the line '; Restore those queue/flags:', add this:
pop bc ld (ix+0Bh),c ; unused queue slot
And with that, we're done.
Conclusion
Try playing the Sega sound in the sound test now (remembering that its ID is now 7C). This time, after the work we've done, it's closer to how it is on the Sega screen. Now PCM playback is a bit more consistent in its quality. You've also freed up two sound IDs, and you've freed up RAM variables Music_to_play through Music_to_play_2.
Note that the entire guide has consisted of improving the PCM playback through the 68k side of things. The driver itself is pretty much untouched. Like I said, straight up improving the PCM stream loop would require modifications to the actual loop.
There is one last thing you may need to do. For me, in Regen, the Sega chant on the Sega screen plays itself twice if I let it run. Removing the sound under loc_3A3E6 fixes it. I'm cautious of recommending it because I don't know what the code is meant to do in the first place. Normally, if the Sega chant sound is queued while the Sega chant sound is playing, it's ignored. But it seems the improved playback causes the sound to end without delay, so this new sound plays just as the first ends, making it play twice. - VintSub0

Find My Content
14 minutes ago
Male