Okay those two problems are solved, but I have another query. Anyone here have experience porting Tails' tails to Sonic 1? I've been trying to translate the coding from Sonic 2, but all I get is either nothing or the tails sprites appearing instead of the character.
Hey, I just wanted to ask: does anybody know any good hacking utilities for Mac? I kinda want to take a stab at ROM hacking and want to know a good program I can use to get started.
@TheOneAndOnlyJoebro64 Depends really on what your aim is. SonLVL is .net based, so you should(?) be able to run it using Mono. Just don't ask me how. That let's you edit level layouts and art. Same with SonPLN, which lets you edit planemaps (title screens, menus etc.) SonMapEd is what we use to edit sprites, but AFAIK it's Windows only. You'd need to install Wine to use it on MacOS. I'm working on a cross-platform replacement to SonMapEd but it still needs more time on the fire before I can recommend it. I think there are a few other options, but they're not very Sonic-specific, so they're a bit more work to use. Personally, I've tried other tools listed on the wiki but always swung back to SonMapEd. Building the games, I believe that the AS branches were started with the goal of providing a cross-platform build environment, but I've never had to use it on MacOS personally, so I can't give you specific advice. Have a look on the Sonic Retro Github for the disassemblies. I very much suspect that if you use Wine, you'll be able to use all the above tools as though you were on Windows. I actually had a lot of success with Wine, but things can *feel* a bit hacky because, really, Windows apps have no business running on MacOS. You'll need a decent text editor, I used TextWrangler when I coded on Mac. If you're not a programmer already, get ready to become one. You'll need to learn 68k assembly. Now that I've covered just about everything, I'll give you what I consider to be the most important advice I can, based on 10 years of using MacOS: install Windows. Yeah, I know that sounds dickish, but I'm being serious. MacOS is designed for the 10% of use cases that will satisfy 90% of all users. Anything outside of that is more hard work than it should be, and frankly, it's a lot of work for hackers to release tools for it when there's a relatively small userbase compared to Windows. I struggled for 10 years to do anything remotely out of the ordinary on MacOS, until I was going to the seaside for a week (away from my desktop) and wanted to work on my hack, so I installed Windows on my MacBook. You can always dual boot if you really want to. Of course, YMMV, but that really is a serious suggestion. If you don't like it, take it up with Tim Cook.
For what it's worth, Flex 2 is listed on the Wiki as compatible with MacOS. I haven't used it that much, but it is well regarded. It's different from SonMapEd, but it has a few nice quality of life upgrades, and a strong user interface design.
Okay, so I'm obviously going to have to figure out how to do more accurate collision edits. Code (Text): Sprite_Collisions_No_InstaShield: cmpi.b #$24,$20(a0) ; check if bit 2 of the Air Attack flag is set bne.s TouchResponse_NoHammer ; branch if it isn't move.w $10(a0),d2 ; load Amy's x-axis value move.w $14(a0),d3 ; load Amy's y-axis value subi.w #$2A,d2 ; These values subi.w #$16,d3 ; plus the next two move.w #$30,d4 ; represent the expanded move.w #$30,d5 ; attack range bsr.s loc_FF06 ; branch to the object ram check TouchResponse_NoHammer: move.w $10(a0),d2 move.w $14(a0),d3 subi.w #8,d2 moveq #0,d5 move.b $1E(a0),d5 subq.b #3,d5 sub.w d5,d3 move.w #$10,d4 add.w d5,d5 loc_FF06: lea (Collision_response_list).w,a4 move.w (a4)+,d6 beq.s locret_FF1C loc_FF0E: movea.w (a4)+,a1 move.b $28(a1),d0 bne.s loc_FF1E loc_FF16: subq.w #2,d6 bne.s loc_FF0E moveq #0,d0 locret_FF1C: rts Someone helped with the code to edit this, but this was when I had no idea what it all fully meant and just fiddled with it like crazy until Amy broke the monitors every time. Is there a big mistake I've made here, is there a way to go about this more accurately, like only extending the hit box from facing forward?
@E-122-Psi It's been a while since I looked at S3 object code, but at a first glance at the image, it looks as though your object origin is very far back from where it should be. If it isn't already, make sure the sprite for this frame is centered properly round about Amy's forward hand, reduce the hitbox to 50%, then work from there, making sure you test the move in both directions. The object position needs to move forward in the facing direction for this move, right now, based on the code, it looks as though it's moving specifically left. The hitbox doesn't have any notion of forwards and backwards, so the center of the object is the center of the hitbox. Edit: Had a closer read of the code now that I've had a nap. That subi #$2A is moving the attack very off-centre considering that the range is $30/2 in either direction of the attack centre. If I'm reading this right, that means that you've got $2A attack range on one side of the object center and $6 on the other side. And it's always moving the attack in the same direction, regardless of which way the player is facing. If you want the centre of the attack to be offset from the object centre, you need to add OR subtract your intended offset from d2 depending on the direction the player is facing. Then you need to tweak that $30 until you've got your intended attack width. Y'know what, after a third read I've actually realised I barely remember S3 object code at all, so it's probably best to ignore the above. I do recommend though that you draw for us what you intend the attack range to be relative to Amy. We need to know how far you want it to be off her object centre, and how large you want it to be. If you want the attack to be forward of Amy, then you definitely need to change that initial block of code to be aware of Amy's direction, because as it stands right now the attack will always be offset in the same direction, regardless of her facing. You can get her facing from bit 0 of $2A(a0) (maybe that's where you got that $2A from in your code? You've misunderstood some previous advice, if so) and then apply the correct offset to d2. If you also want her attack to be offset on the y-axis, you need to do the same with bit 1 of $2A(a0) and d3 (because, Death Egg shenanigans). It kinda looks as though whoever gave you this code intended it for eg. Mighty's ground pound from Mania, which is fine for Mighty because it extends equally in both directions from his centre, but it needs changes as I've described for a directional attack. As generous as it was for them to gift you this code, I'd recommend that you avoid using code that you don't understand.
Okay I've tried something like that but I think I'm still getting the wrong end of the stick here: Code (Text): Sprite_Collisions_No_InstaShield: cmpi.b #$24,$20(a0) ; check if bit 2 of the Air Attack flag is set bne.s TouchResponse_NoHammer ; branch if it isn't btst #0,$2A(a0) beq Collisions_Right move.w $10(a0),d2 ; load Amy's x-axis value move.w $14(a0),d3 ; load Amy's y-axis value subi.w #$18,d2 ; These values subi.w #$18,d3 ; plus the next two move.w #$20,d4 ; represent the expanded move.w #$20,d5 ; attack range bsr.s loc_FF06 ; branch to the object ram check Collisions_Right: move.w $10(a0),d2 ; load Amy's x-axis value move.w $14(a0),d3 ; load Amy's y-axis value addi.w #$18,d2 ; These values subi.w #$18,d3 ; plus the next two move.w #$20,d4 ; represent the expanded move.w #$20,d5 ; attack range bsr.s loc_FF06 ; branch to the object ram check TouchResponse_NoHammer: move.w $10(a0),d2 move.w $14(a0),d3 subi.w #8,d2 moveq #0,d5 move.b $1E(a0),d5 subq.b #3,d5 sub.w d5,d3 move.w #$10,d4 add.w d5,d5 loc_FF06: lea (Collision_response_list).w,a4 move.w (a4)+,d6 beq.s locret_FF1C There's a change in collision but it just means that one direction has a ridiculously large hitbox from both angles and the other small. And no the $2A thing was just me desperately trying to make the attack hit a damn box properly, hence why we got to ridiculous sizes like $30.
@E-122-Psi Cool. I'd recommend pulling the value for d4 down to 1, and gradually increasing upwards from there, instead of taking your existing values and decreasing them. $20 in particular sounds pretty big, that's like 4 whole tiles if the attack range is d4*1, and it's 8 tiles if it's d4*2. Another thing I'm not certain about is whether d2 describes the attack centre or the left-edge, I suspect it's the left-edge based on your description. If it is the left-edge, then you need to alter the modifiers for d2 depending on the width you settle on for the attack. Reducing the values for d4 drastically will help you figure all of this out for yourself. Edit: I'm pretty convinced that d2 describes the left edge, which would make the attack width d4*1. If that's the case, your modifier for d2 needs to be modified by d4 in one direction. If it isn't the case, then you definitely need to reduce d4 because it's making your attack 8 tiles wide. Edit 2: With the code as it is, you're still going to have the attack off-centre on the y-axis in the wrong direction when the gravity gets flipped on Death Egg.
As mentioned though, no matter whether I sub or add, it just changes d2's range from both sides, not just left or right (eg. if I sub a big number, it covers a wide range from either direction). How would d4 modify that to work from only one angle?
Right, I've opened up my laptop, so let's look at the original implementation (the labels are different in my copy of the disasm, but w/e): Code (Text): Touch_NoInstaShield: move.w x_pos(a0),d2 ; Get player's x_pos move.w y_pos(a0),d3 ; Get player's y_pos subi.w #8,d2 ; Subtract Obj_Sonic's x_radius-1 from x_pos (becomes player's left collision boundary) moveq #0,d5 move.b y_radius(a0),d5 subq.b #3,d5 ; Now player's collision height sub.w d5,d3 ; Note the lack of a check for if the player is ducking ; Height is no longer reduced by ducking move.w #$10,d4 ; Player's collision width add.w d5,d5 From this we know that after that subi.w #8, d2 IS Sonic's (Amy's) left boundary. BEFORE that (as in your code), it's his object centre. The value you need to be returning for d2 is the left boundary of where your attack needs to be. We also know that d4 is the width of the attack * 1 (because 8 * 2 = 16). Now it's time for some good old ASCII art and maths. We're going to set d2 to +-8 from Amy's centre, d4 to 4. A is Amy's centre, L is the left edge of the attack, R is the right edge. Code (Text): 0123456789012345678901234567890123456789 L R A L R Now, that doesn't look right, does it? In fact, it kinda describes exactly the problem you're experiencing, except for the fact that your d4 is larger than your d2, which pushes one of your collision areas right over Amy's centre. But what if you made d2=A-8 when facing left and d2=A+8-d4 (4 is still our value for d4) when facing right? Code (Text): 0123456789012345678901234567890123456789 L R A L R Fixed. Now, test and tweak the values until you get the result you need.
What so -4 like this? Code (Text): Sprite_Collisions_No_InstaShield: cmpi.b #$24,$20(a0) ; check if bit 2 of the Air Attack flag is set bne.s TouchResponse_NoHammer ; branch if it isn't btst #0,$2A(a0) beq Collisions_Right move.w $10(a0),d2 ; load Amy's x-axis value move.w $14(a0),d3 ; load Amy's y-axis value subi.w #$18,d2 ; These values subi.w #$18,d3 ; plus the next two move.w #$20,d4 ; represent the expanded move.w #$20,d5 ; attack range bsr.s loc_FF06 ; branch to the object ram check Collisions_Right: move.w $10(a0),d2 ; load Amy's x-axis value move.w $14(a0),d3 ; load Amy's y-axis value subi.w #$14,d2 ; These values subi.w #$18,d3 ; plus the next two move.w #$20,d4 ; represent the expanded move.w #$20,d5 ; attack range bsr.s loc_FF06 ; branch to the object ram check TouchResponse_NoHammer: move.w $10(a0),d2 move.w $14(a0),d3 subi.w #8,d2 moveq #0,d5 move.b $1E(a0),d5 subq.b #3,d5 sub.w d5,d3 move.w #$10,d4 add.w d5,d5 loc_FF06: lea (Collision_response_list).w,a4 move.w (a4)+,d6 beq.s locret_FF1C Sorry if I'm slow on getting this, I'm still not great with S3 flags and attributes.
Without wanting to be mean, this is nothing to do with programming or the Sonic games. It's grade school maths, with visual aids and all. No, not -4. 4 was an EXAMPLE. Minus d4 is what you need. If you're still struggling, find some lined paper, turn it so the lines are vertical. Mark one of the lines on the paper to represent Amy. Then mark 4 lines on the paper where you want the left and right boundaries for the attack facing both directions to be. This should be a symmetrical pattern with Amy in the middle. For each left boundary, count the gaps you cross to reach Amy, that number represents the value you add or subtract against d2 for the collision on that side. Your value for d4 is the number of gaps between either left boundary and the corresponding right boundary. Edit: Fuck it, like this: Code (Text): Sprite_Collisions_No_InstaShield: cmpi.b #$24,$20(a0) ; check if bit 2 of the Air Attack flag is set bne.s TouchResponse_NoHammer ; branch if it isn't btst #0,$2A(a0) beq Collisions_Right move.w $10(a0),d2 ; load Amy's x-axis value move.w $14(a0),d3 ; load Amy's y-axis value subi.w #$18,d2 ; These values subi.w #$18,d3 ; plus the next two move.w #$20,d4 ; represent the expanded move.w #$20,d5 ; attack range bsr.s loc_FF06 ; branch to the object ram check Collisions_Right: move.w $10(a0),d2 ; load Amy's x-axis value move.w $14(a0),d3 ; load Amy's y-axis value subi.w #$18,d2 ; These values subi.w #$18,d3 ; plus the next two move.w #$20,d4 ; represent the expanded move.w #$20,d5 ; attack range sub.w d4,d2 ; WAFER WOZ ERE TO FIX UR CODE bra.s loc_FF06 ; branch to the object ram check This is VERY slightly slower than an ideal fix, because we're doing the maths on the 68k instead of in your brain. But it's faster for me. Now, as before, just tweak and test the values until you reach the desired result. And do the same thing with the y-axis, d3 and d5 so Death Egg doesn't get screwy.
I get maths but no matter what I do the actual results don't mesh with that. d4 is the new expanded hit box width right? I add to d2 when left and subtract from it when right, and that adjusts it to one direction. But here's the thing, it doesn't do that. It just grows d4 both lengths one direction and shrinks it both lengths the other. It's not moving it, it's changing it's width.
@E-122-Psi You've got one more potential problem I see: bsr.s loc_FF06 Change it to a bra. Your code was recursive. I've changed the code in my post above to match. Now, you maybe intended for that, to make sure that Amy's regular collision works, but for the sake of testing your code for the hammer, I'll live with this change. It's on you to figure out how to continue from there. If you're still having issues, your issue is somewhere else.
Okay, I had to fiddle with a couple handles but I think I've got it running now. Sorry about that convolution.
@E-122-Psi No worries, glad we got there in the end. And I'm sorry if I was flippant, I do forget that this kinda stuff doesn't come as easy to some people as it does to me. Just drop me a mention in the post when you release.
It's fine I'm a very slow learner, and I should have took in this stuff ages ago. I'll do that, though it might be a while before I fix up the rest of the game (if I forget by then just note me though).
Okay, it's my turn with a few questions. So, I'm working on this VDP art editor, and one of the formats I'm gonna support is spritemaps for the Sonic series. I've started with S3 and noticed that even though the spritemap format includes a full VDP index, the palette line flag doesn't seem to be stored in the map. Which in retrospect I realise I must've known at some point for the minimal art editing I've done on the games. So, my questions are: - Is the palette line ignored completely? Ie. if a spritemap was included that did have a non-zero palette line flag, would it cause issues when the game tries to render the sprite? Is it masked off? - Is this behaviour consistent in the other spritemap formats for the series? - The same questions as above for the priority and flip flags. Thanks in advance! I know I could just test this, but that's a lot of flags and formats to dig through if someone already knows off-hand.
I am not sure where you've got your sources from, but the palette lines can be affected by the sprite mappings from Sonic 1 to Sonic 3 & Knuckles perfectly fine. The only catch you'd need to be concerned with, is the wrapping. Since the pattern index word from the object is added to the pattern index word of the sprite list before it's saved to the buffer (note I said "added" and not "OR'd" or "XOR'd"), then it's possible for the bits to carry over. For your circumstance it'd be the palette lines overflowing past palette line 4, wrapping back to palette line 1, but the priority/plane (high/low) bit being affect as a side effect of the carrying. The palette line is not ignored. The behaviour of the palette lines is consistent throughout all of the first four titles. It's all valid, nothing is ignored, but it's all added together, so if there is an overflow with any of the bits, they will carry to the upper bits. If you would like an example of this, Sonic 1's HUD sprites have versions where the palette line bits set the sprites to the second line for showing red instead of yellow.
Thanks @MarkeyJester . When I said that it's not stored in the map, I meant that when I opened eg. the .asm map for the Bubbles badnik, the palette line was 0, but I know that the game doesn't render it using that line. Knowing that the flags just get added to the VDP index means that it's not worth adding an option to edit the flags in my editor. Edit: Actually, I guess that the palette line flag is the ONLY flag that it makes sense to be able to edit, in the event that a user wanted to construct a spritemap that used more than one palette line, with the caveat that they would need to be careful to not cause an overflow if they set the palette line in the object code too high. That's a kinda neat trick, if someone wanted it, but does add a bit of complexity to my editor. Edit 2: And now I'm wondering whether I should set it up for the flip flags as well, in the event that a user wanted to do something tricky with XORing the flags in-engine to save on VRAM. I already use 16-bits internally for the x and y position for people that want to mess with the engine... *descending into the rabbit hole* For context, I'm actually intending the tool to be very generalized, because I was building it in anticipation of various bits of homebrew I have planned, but to also support Sonic game formats.