Some changes/fixes for Sonic 1
#46
Posted 17 August 2013 - 10:18 AM
I also used your code for the fades, and got my own white in and white out effect, similar to yours. I'm looking into re-working all of it to appear similar to this effect, but in the original 21 frames instead of the new 7. I'll post that here too.
#47
Posted 19 August 2013 - 10:43 AM
I'm re-bumping this thread again, to give you all a tutorial on a powerup I just finished for my new hack in progress: Sonic 1: Freehand (The Sketchhog hack)
This powerup is called Ring Time. For those who don't know what this is... it turns your enemies into rings when in proximity.
So, the first thing you will want to do, before anything else... is create a new frame for this monitor... using your art editor of choice (*cough* Insert shameless Sonic Triad plug here *cough*)
If you can't be arsed to do art, just have it use the normal ring art, which is what I did when I first put this together.
Now, go into _incObj/2E Monitor Content Power-Up.asm and scroll down to the end of the powerup checks. Replace "Pow_ChkRings" with the following:
Don't mind the check for Goggles, you can change that to Pow_ChkEnd if you don't want more powerups.
Notice v_ringtime and v_player+$2A. The first one... just make an equate for it in Variables.asm whereever you want to. I'd do it somewhere near v_shoes.
For the second one, $2A and $2B are unused SST's for Sonic, so they are now our RingTime powerup SST's. When we get the powerup, these will be set to a value, and they will ultimately tick down to 0, much like Speed Shoes and Invincibility do...
Now, to make this expire after a limited time, go to _incObj/Sonic Display.asm. Below @chkshoes, add this block of code:
Replace @chkgoggles with @exit if you have no other timed powerups intended. Now if you are familiar with the above @chkshoes code, you already know what this does. It decrements the ring time timer, and disables the powerup.
Now finally, to the piece de res.... ok I'll shut up. Here is how the powerup bears fruit. Go to _incObj/sub ReactToItem.asm. Replace "@proximity" with this (I attempted to comment stuff to help understand the code. My apologies if my comments aren't 100% accurate. I tried.)
So basically, this checks if an object is colliding with Sonic's sides. If it is NOT, then it checks to see if the object is in proximity. ($50 pixels). If it is, it then checks if the object is a badnik, by first checking obColType(a1) o see if it is an enemy, then checking obColProp(a1) to see if it is a boss. if every thing checks out... then we proceed. We can replace @outsidey with essentially the same code, as you can see below:
Now, finally let's get to RingTime_Enemy:
Essentially turns the badnik into rings. Now I used a new ring object for this... partly because using the standard lost rings will be a headache... IMO, THAT and you cannot collect lost rings in Sonic Freehand. If you do use RingLoss object for this... you'll have to do a little tweaking... as it is the RingLoss object that also reduces your rings to zero as it spawns the other rings.
So... yep, that's what I've got. It works fine considering the circumstances of my hack, but perhaps it isn't perfect for the standard Sonic 1 hack YET. If I did something wrong, or if something could be improved, please help me to make this better. I haven't tested this in stock Sonic 1, and the conditions of that game are far different than my hack... so it may work fine for me, while it could cause bugs for you. I hope that someone experienced enough can help us perfect this.
Hope this can be of use to anyone.
-KoH
This powerup is called Ring Time. For those who don't know what this is... it turns your enemies into rings when in proximity.
So, the first thing you will want to do, before anything else... is create a new frame for this monitor... using your art editor of choice (*cough* Insert shameless Sonic Triad plug here *cough*)
If you can't be arsed to do art, just have it use the normal ring art, which is what I did when I first put this together.
Now, go into _incObj/2E Monitor Content Power-Up.asm and scroll down to the end of the powerup checks. Replace "Pow_ChkRings" with the following:
; =========================================================================== Pow_ChkRings: cmpi.b #5,d0 ; does monitor contain 10 rings? bne.s Pow_ChkRingTime ; <---- ADD NEW CHECK HERE addi.w #10,(v_rings).w ; add 10 rings to the number of rings you have ori.b #1,(f_ringcount).w ; update the ring counter cmpi.w #100,(v_rings).w ; check if you have 100 rings bcs.s Pow_RingSound bset #1,(v_lifecount).w beq.w ExtraLife cmpi.w #200,(v_rings).w ; check if you have 200 rings bcs.s Pow_RingSound bset #2,(v_lifecount).w beq.w ExtraLife Pow_RingSound: music sfx_Ring,1 ; play ring sound ; =========================================================================== Pow_ChkRingTime: cmpi.b #6,d0 ; does monitor contain 'Ring Time'? bne.s Pow_ChkGoggles move.b #1,(v_ringtime).w ; make Sonic able to turn enemies into rings move.w #$4B0,(v_player+$2A).w ; time limit for the power-up music sfx_Ring,1 ; play ring sound ; ===========================================================================
Don't mind the check for Goggles, you can change that to Pow_ChkEnd if you don't want more powerups.
Notice v_ringtime and v_player+$2A. The first one... just make an equate for it in Variables.asm whereever you want to. I'd do it somewhere near v_shoes.
For the second one, $2A and $2B are unused SST's for Sonic, so they are now our RingTime powerup SST's. When we get the powerup, these will be set to a value, and they will ultimately tick down to 0, much like Speed Shoes and Invincibility do...
Now, to make this expire after a limited time, go to _incObj/Sonic Display.asm. Below @chkshoes, add this block of code:
@chkringtime:
tst.b (v_ringtime).w ; does Sonic have the powerup?
beq.s @chkgoggles ; if not, branch
tst.w ringtime(a0) ; check time remaining
beq.s @chkgoggles
subq.w #1,ringtime(a0) ; decrement timer
bne.s @chkgoggles
move.b #0,(v_ringtime).w ; cancel powerup
Replace @chkgoggles with @exit if you have no other timed powerups intended. Now if you are familiar with the above @chkshoes code, you already know what this does. It decrements the ring time timer, and disables the powerup.
Now finally, to the piece de res.... ok I'll shut up. Here is how the powerup bears fruit. Go to _incObj/sub ReactToItem.asm. Replace "@proximity" with this (I attempted to comment stuff to help understand the code. My apologies if my comments aren't 100% accurate. I tried.)
@proximity: andi.w #$3F,d0 add.w d0,d0 lea @sizes-2(pc,d0.w),a2 ; a2=other object's collision box size. moveq #0,d1 move.b (a2)+,d1 ; d1=a1's collision width. move.w obX(a1),d0 ; d0=a1's x-position sub.w d1,d0 ; d0=a1's x-position-minus its collision width. (Co-ordinate of its left side bounding box) sub.w d2,d0 ; d0=a1's left bounding box co-ordinate-(Sonic's position-8) bcc.s @outsidex ; branch if not touching (positive value or 0) add.w d1,d1 ; d1=a1's collision width*2 - a1's RIGHT bounding box co-ordinate add.w d1,d0 ; d0=(a1's left bounding box co-ordinate-(Sonic's position-8))+ d1, to check the right side. bcs.s @withinx ; branch if touching (negative value) bra.w @next ; =========================================================================== @outsidex: tst.b (v_ringtime).w ; is Ring Time active? beq.s @skipx ; if not, branch cmp.w #$50,d0 ; is the enemy within range, x-wise? bcc.s @skipx ; if not, branch move.b obColType(a1),d1 ; load collision type andi.b #$C0,d1 ; is object an enemy? bne.s @skipx ; if no, branch tst.b obColProp(a1) ; is enemy a badnik? beq.w RingTime_Enemy ; if yes, branch
So basically, this checks if an object is colliding with Sonic's sides. If it is NOT, then it checks to see if the object is in proximity. ($50 pixels). If it is, it then checks if the object is a badnik, by first checking obColType(a1) o see if it is an enemy, then checking obColProp(a1) to see if it is a boss. if every thing checks out... then we proceed. We can replace @outsidey with essentially the same code, as you can see below:
@outsidey:
tst.b (v_ringtime).w ; is Ring Time active?
beq.s @skipy ; if not, branch
cmp.w #$50,d0 ; is the enemy within range, y-wise?
bcc.s @skipy ; if not, branch
move.b obColType(a1),d1 ; load collision type
andi.b #$C0,d1 ; is object an enemy?
bne.w @skipy ; if no, branch
tst.b obColProp(a1) ; is enemy a badnik?
beq.s RingTime_Enemy ; if yes, branch
Now, finally let's get to RingTime_Enemy:
RingTime_Enemy:
move.b #id_RingBounce,0(a1) ; change object to bouncing ring
move.b #0,obRoutine(a1)
rts
Essentially turns the badnik into rings. Now I used a new ring object for this... partly because using the standard lost rings will be a headache... IMO, THAT and you cannot collect lost rings in Sonic Freehand. If you do use RingLoss object for this... you'll have to do a little tweaking... as it is the RingLoss object that also reduces your rings to zero as it spawns the other rings.
So... yep, that's what I've got. It works fine considering the circumstances of my hack, but perhaps it isn't perfect for the standard Sonic 1 hack YET. If I did something wrong, or if something could be improved, please help me to make this better. I haven't tested this in stock Sonic 1, and the conditions of that game are far different than my hack... so it may work fine for me, while it could cause bugs for you. I hope that someone experienced enough can help us perfect this.
Hope this can be of use to anyone.
-KoH
#49
Posted 19 August 2013 - 10:56 AM
Ah yes... I should've put that in. I'd say that I thought that would come naturally to anyone looking to implement this... but I know I'd be surprised at how wrong I am. XD
#50
Posted 20 November 2013 - 08:38 AM
Took this from Mercury's ReadySonic. I've had so much use for this mod... and it's already on a public forum with ReadySonic, so there's no reason why it isn't in the SCHG already. Added the page just now. It's not my best writing, I apologize.
http://info.sonicret...ge_Walls_system
I also made a small note about the fix Cinossu made for smoother rotation at the end of this guide.
http://info.sonicret...ge_Walls_system
I also made a small note about the fix Cinossu made for smoother rotation at the end of this guide.
#51
Posted 20 November 2013 - 11:22 PM
One simple hack I thaught about -originally for S3 but could apply to all MegaDrive titles as well- is to escape the 60 frames per second in the collissions engine.
Let me explain: The MegaDrive outputs 60 images per second, but the whole game physiscs are based on that clock.
My idea was to initially test how the engine changes, but not aletering the physics. This could be done processing twice for object collisions per frame, but moving objects by half every step.
This way, sonic would be moved twice per frame, but at half speed, checking for collissions evey time.
Why mod this? Remember high speed glitches that don't happen at lower speeds? Maybe this could be a way to go around that limitation, because the collissions engine would be moving objects at half speed. Also, this mod would also allow to go for higher speeds in the game, exceeding those 16 pixels per frame < maybe this is a little too much (even unneeded), but it'd be easy to achieve.
Yes, physics would be altered, but would be almost unnoticiable - this according to some simple simulations I've done.
Taking this concept further, the clock rate could be made variable and switch to this supposed higher precision only at higher speeds, and keep the lower speed sections with their former physics.
Maybe some of you experts out there could tell if this is possible, or if this could help achieve more continuity in the fastest sections of some levels -especially in S3.
Let me explain: The MegaDrive outputs 60 images per second, but the whole game physiscs are based on that clock.
My idea was to initially test how the engine changes, but not aletering the physics. This could be done processing twice for object collisions per frame, but moving objects by half every step.
This way, sonic would be moved twice per frame, but at half speed, checking for collissions evey time.
Why mod this? Remember high speed glitches that don't happen at lower speeds? Maybe this could be a way to go around that limitation, because the collissions engine would be moving objects at half speed. Also, this mod would also allow to go for higher speeds in the game, exceeding those 16 pixels per frame < maybe this is a little too much (even unneeded), but it'd be easy to achieve.
Yes, physics would be altered, but would be almost unnoticiable - this according to some simple simulations I've done.
Taking this concept further, the clock rate could be made variable and switch to this supposed higher precision only at higher speeds, and keep the lower speed sections with their former physics.
Maybe some of you experts out there could tell if this is possible, or if this could help achieve more continuity in the fastest sections of some levels -especially in S3.
#52
Posted 20 November 2013 - 11:26 PM
I'm no expert, but considering how the game sometimes lags just trying to run at 60fps, there's pretty much no way you'd be able to double the amount of processing it does per frame.
#53
Posted 21 November 2013 - 08:36 AM
As someone that has taken extreme measures in my hack to reduce the lag caused by an additional character, I can attest to what MainMemory is saying -- adding an extra character is nowhere near the same in terms of processing requirements as doubling all the updates for all objects, and it is bordering the limits of what the poor 68k can handle. Doubling all the game logic would basically make the game unplayable: you would end up with something like 60fps in physics updates displaying at maybe 30fps.
#54
Posted 21 November 2013 - 10:28 AM
Ok, I accept that. But since the character is moving half the distance, the only processing that should be done is character repositioning. I mean, this would only double character repositioning when colliding with tiles.
All other processing should remain the same, and once per frame.
To get a bit more technical, instead of doing this:
X[n+1] = X[n] + V[n]
check for tile collision
<continue to check other things and move objects>
do this:
X[n+1/2] = X[n] + V[n]/2
check for tile collision
X[n+1] = X[n+1/2] + V[n]/2
check for tile collision
<continue to check other things and move objects>
As far as I suppose, this would similar to having 2 characters on screen. If so, this shouldn't need much more processing power
All other processing should remain the same, and once per frame.
To get a bit more technical, instead of doing this:
X[n+1] = X[n] + V[n]
check for tile collision
<continue to check other things and move objects>
do this:
X[n+1/2] = X[n] + V[n]/2
check for tile collision
X[n+1] = X[n+1/2] + V[n]/2
check for tile collision
<continue to check other things and move objects>
As far as I suppose, this would similar to having 2 characters on screen. If so, this shouldn't need much more processing power
#55
Posted 11 October 2014 - 02:51 AM
Would there be any interest in a S2 Ring Manager in Sonic 1 guide? I had some time today... for once... and managed it. If so I'll try to find time to whip one up.
#56
Posted 15 March 2015 - 11:36 PM
Okay, most hackers here have likely caught onto this bug ages ago, but since there's no tutorial or anything of it, here's one for beginners.
The Roller badnik suffers from a slight graphics glitch due to it's VRAM clashing with leftover Caterkiller tiles, leading to this:

The inclusion of Caterkiller's data in Spring Yard Zone seems to be an error as it isn't used anywhere, thus we can take it out of here fine. Simply go to inc/pattern load cues.asm and find the SYZ data.
Now edit out Caterkiller and change the object number accordingly like so:
Voila. Roller's graphics should be fixed.
I've one query that's puzzled me since I was a kid, I've noticed the debug mode causes some VERY odd occurrences in Special Zone. It doesn't implement objects properly or even display most of them and exiting out of the maze can float you into these strange random areas with limited collision and numerous beta objects (solid emeralds can also be collected there). What would this be classified as exactly? Glitch? Unfinished programming? Necessary garbage data? What the heck is going on in this zone?
I also noticed the HUD objects are in the VRAM for this level as well, leaving me wondering whether it was supposed to be used in there (has anyone tried lasting ten minutes in there?).
The Roller badnik suffers from a slight graphics glitch due to it's VRAM clashing with leftover Caterkiller tiles, leading to this:

The inclusion of Caterkiller's data in Spring Yard Zone seems to be an error as it isn't used anywhere, thus we can take it out of here fine. Simply go to inc/pattern load cues.asm and find the SYZ data.
; --------------------------------------------------------------------------- ; Pattern load cues - Spring Yard ; --------------------------------------------------------------------------- PLC_SYZ: dc.w 4 dc.l Nem_SYZ ; SYZ main patterns dc.w 0 dc.l Nem_Crabmeat ; crabmeat enemy dc.w $8000 dc.l Nem_Buzz ; buzz bomber enemy dc.w $8880 dc.l Nem_Yadrin ; yadrin enemy dc.w $8F60 dc.l Nem_Roller ; roller enemy dc.w $9700 PLC_SYZ2: dc.w 7 dc.l Nem_Bumper ; bumper dc.w $7000 dc.l Nem_SyzSpike1 ; large spikeball dc.w $72C0 dc.l Nem_SyzSpike2 ; small spikeball dc.w $7740 dc.l Nem_Cater ; caterkiller enemy dc.w $9FE0 dc.l Nem_LzSwitch ; switch dc.w $A1E0 dc.l Nem_Spikes ; spikes dc.w $A360 dc.l Nem_HSpring ; horizontal spring dc.w $A460 dc.l Nem_VSpring ; vertical spring dc.w $A660
Now edit out Caterkiller and change the object number accordingly like so:
; --------------------------------------------------------------------------- ; Pattern load cues - Spring Yard ; --------------------------------------------------------------------------- PLC_SYZ: dc.w 4 dc.l Nem_SYZ ; SYZ main patterns dc.w 0 dc.l Nem_Crabmeat ; crabmeat enemy dc.w $8000 dc.l Nem_Buzz ; buzz bomber enemy dc.w $8880 dc.l Nem_Yadrin ; yadrin enemy dc.w $8F60 dc.l Nem_Roller ; roller enemy dc.w $9700 PLC_SYZ2: dc.w 6 dc.l Nem_Bumper ; bumper dc.w $7000 dc.l Nem_SyzSpike1 ; large spikeball dc.w $72C0 dc.l Nem_SyzSpike2 ; small spikeball dc.w $7740 dc.l Nem_LzSwitch ; switch dc.w $A1E0 dc.l Nem_Spikes ; spikes dc.w $A360 dc.l Nem_HSpring ; horizontal spring dc.w $A460 dc.l Nem_VSpring ; vertical spring dc.w $A660
Voila. Roller's graphics should be fixed.
I've one query that's puzzled me since I was a kid, I've noticed the debug mode causes some VERY odd occurrences in Special Zone. It doesn't implement objects properly or even display most of them and exiting out of the maze can float you into these strange random areas with limited collision and numerous beta objects (solid emeralds can also be collected there). What would this be classified as exactly? Glitch? Unfinished programming? Necessary garbage data? What the heck is going on in this zone?
I also noticed the HUD objects are in the VRAM for this level as well, leaving me wondering whether it was supposed to be used in there (has anyone tried lasting ten minutes in there?).
This post has been edited by E-122-Psi: 16 March 2015 - 12:22 AM
#57
Posted 16 March 2015 - 01:33 AM
E-122-Psi, on 15 March 2015 - 11:36 PM, said:
but since there's no tutorial or anything of it
Still, I believe this actually is the first time that the fix is detailed in a proper form, so nice work for that. It's one of those little things which pop up from time to time and everyone thinks "it's already known", so it's good to have it posted in a proper topic.
#58
Posted 16 March 2015 - 04:44 AM
Exiting out of the maze can make you go on areas which read incorrect RAM for layout data, which so happens to be garbage. The actual layouts are loaded on RAM and displayed as you move, while you go out of bounds you find random broken things. The stage does not have any actual objects, aside from Sonic, so they will follow the stage position, and not the stage graphics, so it seems all wonky. The HUD is likely something unimplemented on the stage, I don't know why its there, but likely for no purpose, just leftover. I am not sure if being on the stage for 10 minutes will kill you, its something to look into.
#59
Posted 16 March 2015 - 05:12 AM
Green Snake, on 16 March 2015 - 04:44 AM, said:
Exiting out of the maze can make you go on areas which read incorrect RAM for layout data, which so happens to be garbage. The actual layouts are loaded on RAM and displayed as you move, while you go out of bounds you find random broken things.
This is the same reason you find garbage tiles underneath Sonic 3's maps - it's doing exactly the same thing.
#60
Posted 23 March 2015 - 02:52 AM
The HUD art appears in VRAM as its not overwritten during the transition from zone to SS. Unless I'm mistaken... You won't find it in VRAM going there from Level Select immediately upon booting the game.
Secondly there is no time over in the Special Stage, that is... Unless you hack it in.
Secondly there is no time over in the Special Stage, that is... Unless you hack it in.
This post has been edited by KingofHarts: 23 March 2015 - 02:54 AM

06