The code at sub_612A8 whittles this value down to its four lower bits, generating a random number between 0 and 15, which is then used as an index into a table containing the actual subtype values, which in turn range from 0 to 7:
byte_612E0: dc.b 0 ; 1-Up Ball dc.b 3 ; Clear dc.b 1 ; Replace Ball dc.b 4 ; Bumper dc.b 2 ; Ring Ball dc.b 4 ; Bumper dc.b 5 ; Flame Barrier dc.b 4 ; Bumper dc.b 6 ; Aqua Barrier dc.b 3 ; Clear dc.b 7 ; Thunder Barrier dc.b 4 ; Bumper dc.b 5 ; Flame Barrier dc.b 6 ; Aqua Barrier dc.b 7 ; Thunder Barrier dc.b 2 ; Ring BallThis effectively converts the uniform distribution of the randomly-generated number into a weighted probability function: for instance, the Thunder Barrier appears twice in the table, so it's twice as likely as a Replace Ball, which only appears once. Meanwhile, it's only half as likely as a bumper, which appears four times in the table.
There's a trick, though. Whenever the resulting gumball is a 1-Up Ball, a RAM flag is set which causes any subsequent 1-Ups to be replaced with the fourth entry from the table, producing a bumper:
sub_612A8: jsr (Random_Number).l andi.w #$F,d0 bne.s loc_612C2 movea.w $46(a0),a1 bset #7,$38(a1) beq.s loc_612C2 moveq #3,d0 loc_612C2: move.b byte_612E0(pc,d0.w),d0 move.b d0,$2C(a0) ...As a result, only a single 1-Up Ball will ever spawn per bonus stage, and once it does, the random distribution becomes even more skewed toward bumpers. Here's all of this information compiled into a table, because people like tables:
Gumball Type | Likelyhood (before 1-up) | Likelyhood (after 1-up) |
---|---|---|
1-Up Ball | 1/16 | 0/16 |
Replace Ball | 1/16 | 1/16 |
Ring Ball | 2/16 | 2/16 |
Clear | 2/16 | 2/16 |
Bumper | 4/16 | 5/16 |
Flame Barrier | 2/16 | 2/16 |
Aqua Barrier | 2/16 | 2/16 |
Thunder Barrier | 2/16 | 2/16 |
Hi. Sorry to derail, but the last comment I left on an old post seemed to go unnoticed, so I don't know if you get notifications for these.
ReplyDeletehttps://s3unlocked.blogspot.co.uk/2017/10/knuckles-in-sonic-2-control-quirks.html
I think the second behaviour quirk you mentioned in this post is the result of a bug. There's some code in S3K that isn't in KiS2, at loc_16E10 in the current S3K Git disasm. The equivalent label in KiS2's Git disasm is loc_315B04.
What I think this new code does is handle floor collision, because Knuckles still seems to move briefly after the player stops pressing the D-Pad. The issue is, this new code overwrites d1 with the distance Knuckles is from the floor. d1 is checked immediately afterwards, has Knuckles's frame ID added to it, and is then used to calculate which frame Knuckles should display.
d1 will always be a positive number, usually a large one depending on how far Knuckles is from the ground. This means, when Knuckles's frame ID is added to it, it goes well beyond the ceiling value of $BC, causing the game to reset it to $B7, making Knuckles display the first frame of his animation. Chances are the number could overflow, too, causing him to display his last frame instead.
Safe to say, editing the code to properly back up d1 causes it to behave like KiS2 instead.
Sorry that you felt your comment went unnoticed. I can assure you I read each and every comment, but often I don't have anything to add, and other times, they end up falling through the cracks.
DeleteAdmittedly, which is which isn't obvious from casual observation, so I'll try to improve on that front. In the future though, please bring up issues like this in the relevant post. Thanks.
That being said, excellent work! I haven't looked at the code in question in the time being, so I'll take your word for it. Would you mind if I cobble up your analysis into a follow-up post sometime in the future?
Sure, go ahead.
DeleteAre the gum balls that are fully grey supposed to be black? (The ones inside of the machine) Every single gum ball is in the machine except for the bumpers. Also, what is that turquoise colored ball behind the rest supposed to be?
ReplyDeleteMore on the gumball sprites coming next post.
Delete