Revision 1.2 uploaded: http://www.sendspace.com/file/vcl56c * SEGA animation fixed (thanx MainMemory). * Remaining sprites added (including tornado sprites for Tails' mode). * Added a duck laser attack for when crouching. * Couple of sprite fixes that didn't quite look right. * Handful of other bug fixes I didn't keep track of. Okay if I wiki this by the way?
And in a year+ absence, another update: Sally's projectile is now REAL and long distance! A very special thanks to Snkenjoi for coding this. Admittedly there are parts where a projectile in a Sonic game seemed better on paper, Sally frequently outruns her laser attack and some elements are extremely difficult to aim onto (see SCZ and OOZ boss) but owning parts such as the last boss are a lot of fun and at least now Sally isn't an Amy-lite. I'm wondering whether to keep her hitbox when she fires so she isn't completely vulnerable, since it's now extremely easy for her to get hit. Bugs: * The slide and close range fire is still needed for some objects such as the CPZ and HTZ bricks until I figure out how to code the projectile object to work with them. Go to the wiki entry for the new revision.
If you're worried about Sally outrunning her projectile, would it be possible to add Sally's current speed to the projectile's base speed when it's fired?
Would it be easy enough to have Sally switch art files when she turns super? (I know S3+K does, even if the dissassembly screws it up). If so I could at least make a more impressive super form for her by switching some colors around, even if her transformation sequence would likely look fucked up. This is my mock up. While the colors are still underplayed, I thought it made a funny nod to her old blonde color scheme. The next revision fixes this by clearing Sally's x velocity. While this means slowing her down whenever she has to attack, it gets rid of the issue and makes it easier to aim too. She also has a downward fire move too, which makes some parts a whole lot easier.
With the right sound effect and a recoil animation, you could easily make this feel as deliberate as it is.
Doing so would be easy enough just set the art, mappings and dplc files to load when turning super and set the normal ones when reverting from super to normal. Then you will also have to most likely make the super form animation lists from scratch, since I'd assume you would be replacing every sprite with a super form version?
Another new revision! * Sally has a new downward laser ability, fire while airbourne holding downward, Sally also gets a vertical boost. * Super Sal has been tweaked up a bit, better color scheme and her laser is boosted. * Sally's laser can now shoot through most breakable objects (except the wing fortress entrance capsule, which still needs a close up attack to break). Bugs: * An odd bug sometimes occurs where Sal can just smash through some objects just by rushing through them a certain way. * While Sally herself is fixed, some sprites still aren't refined to the super pallette.
Okay I've been attempting to convert the projectile code into the Sonic 1 hack. So far I've gotten the basic physics to work (eg. it shoots from Sally and hits things) but the art itself refuses to load no matter what I do. If anyone can see any flaws I've made in the conversion please say so. This has been driving me crazy for a while now: Code (ASM): ObjDE: moveq #0,d0 move.b $24(a0),d0 move.w Obj_Blob_Index(pc,d0),d0 jmp Obj_Blob_Index(pc,d0) Obj_Blob_Index: dc.w Obj_Blob_Init-Obj_Blob_Index dc.w Obj_Blob_Move-Obj_Blob_Index dc.w Obj_Blob_Destroy-Obj_Blob_Index Obj_Blob_Init: move.l #SME_0iwB5,mappings(a0) ; ($C) move.w #$79C,art_tile(a0) move.w #$2,priority(a0) move.b #$8,width_pixels(a0) move.b #$4,render_flags(a0) move.b #$4,y_radius(a0) ; $A move.b #$18,$30(a0) ; distance laser will travel move.w #$C4,d0 ; play sound jsr (PlaySound).l cmpi.b #$29,(MainCharacter+anim).w beq.s ObjDE_DownwardNICOLE ; if not, branch move.w #$660,x_vel(a0) ; speed of laser jmp ObjDE_ContNICOLE ObjDE_DownwardNICOLE: move.w #$660,y_vel(a0) ; speed of laser ObjDE_ContNICOLE: add.w #$10,x_pos(a0) btst #0,($FFFFB001).w beq.s + neg.w x_vel(a0) sub.w #$20,x_pos(a0) + lea (ArtSNK_Laser0).l,a1 move.w #$79C*$20,d2 jsr (SNKDec).l addq.b #2,$24(a0) ; Obj_Blob_Move: cmp.b #$0,$30(a0) beq.w Obj_Blob_Destroy sub.b #$1,$30(a0) bsr.w ObjectMove move.b $40,$20(a0) ; lol clr.w d0 move.b $1A(a0),d0 asl.w #$1,d0 ; *2 for correct offset lea (LaserArtPointers).l,a1 adda.w (a1,d0.w),a1 move.w #$79C*$20,d2 jsr (SNKDec).l lea (Ani_Laser).l,a1 jsr AnimateSprite jsr (TouchResponse).l ;Touch_KillEnemy, Touch_Monitor jmp DisplaySprite Obj_Blob_Destroy: clr.b ($FFFFFFA4).w ; clear NICOLE flag jmp DeleteObject Ani_Laser: dc.w laser0-Ani_Laser laser0: dc.b 3,0,1,1,2,2,3,3,$FD,0 even SME_0iwB5: dc.w SME_0iwB5_8-SME_0iwB5, SME_0iwB5_12-SME_0iwB5 dc.w SME_0iwB5_1C-SME_0iwB5, SME_0iwB5_26-SME_0iwB5 SME_0iwB5_8: dc.b 0, 1 dc.b $F8, 5, 0, 0, 0, 0, $FF, $F8 SME_0iwB5_12: dc.b 0, 1 dc.b $F8, 5, 0, 0, 0, 0, $FF, $F8 SME_0iwB5_1C: dc.b 0, 1 dc.b $F8, 5, 0, 0, 0, 0, $FF, $F8 SME_0iwB5_26: dc.b 0, 1 dc.b $F8, 5, 0, 0, 0, 0, $FF, $F8 even Sonic 1 attempt: Code (ASM): Obj10: moveq #0,d0 move.b $24(a0),d0 move.w Obj_Blob_Index(pc,d0),d0 jmp Obj_Blob_Index(pc,d0) Obj_Blob_Index: dc.w Obj_Blob_Init-Obj_Blob_Index dc.w Obj_Blob_Move-Obj_Blob_Index dc.w Obj_Blob_Destroy-Obj_Blob_Index Obj_Blob_Init: lea ($FFFFD000).w,a1 move.l #SME_0iwB5,4(a0) ; ($C) move.w #$7A0,2(a0) move.w #$2,$18(a0) move.b #$8,$19(a0) move.b #$4,1(a0) move.b #$4,$16(a0) ; $A move.b #$18,$30(a0) ; distance laser will travel cmpi.b #$25,$1C(a1) ; is NICOLE attack being performed? beq.w Obj10_DownwardNICOLE ; if not, branch move.w #$660,$10(a0) ; speed of laser jmp Obj10_ForwardNICOLE Obj10_DownwardNICOLE: move.w #$660,$12(a0) ; speed of laser Obj10_ForwardNICOLE: add.w #$10,8(a0) btst #0,$22(a1) beq.s Obj10_Cont neg.w $10(a0) sub.w #$20,8(a0) Obj10_Cont: lea (ArtSNK_Laser0).l,a1 move.w #$7A0*$20,d2 jsr (SNKDec).l addq.b #2,$24(a0) ; Obj_Blob_Move: cmp.b #$0,$30(a0) beq.w Obj_Blob_Destroy sub.b #$1,$30(a0) jsr SpeedToPos2 move.b $40,$20(a0) ; lol clr.w d0 move.b $1A(a0),d0 asl.w #$1,d0 ; *2 for correct offset lea (LaserArtPointers).l,a1 adda.w (a1,d0.w),a1 move.w #$7A0*$20,d2 jsr (SNKDec).l lea (Ani_Laser).l,a1 jsr AnimateSprite jsr (TouchResponse).l ;Touch_KillEnemy, Touch_Monitor jmp DisplaySprite Obj_Blob_Destroy: clr.b ($FFFFFFA4).w ; clear NICOLE flag jmp DeleteObject Ani_Laser: dc.w laser0-Ani_Laser laser0: dc.b 3,0,1,1,1,2,2,2,3,3,3,$FD,0 even SME_0iwB5: dc.w SME_0iwB5_8-SME_0iwB5, SME_0iwB5_12-SME_0iwB5 dc.w SME_0iwB5_1C-SME_0iwB5, SME_0iwB5_26-SME_0iwB5 SME_0iwB5_8: dc.b 0, 1 dc.b $F8, 5, 0, 0, 0, 0, $FF, $F8 SME_0iwB5_12: dc.b 0, 1 dc.b $F8, 5, 0, 0, 0, 0, $FF, $F8 SME_0iwB5_1C: dc.b 0, 1 dc.b $F8, 5, 0, 0, 0, 0, $FF, $F8 SME_0iwB5_26: dc.b 0, 1 dc.b $F8, 5, 0, 0, 0, 0, $FF, $F8 even Also, more a question for the long run, is it possible to put new gameplay objects into the S3+K disassembly (I don't think I've seen any projects that do so, unless Tiddle's extras in Complete apply). If it is, you know what must happen...
What's a Tiddle? (Canned laughter) I create all sorts of objects for S3C, though they're mostly of the helper object kind. There's no special trick to it compared to any of the other games, as far as I know, but there are a few things to remember: Instead of a single byte object ID at the start of the object's memory, there is a four byte pointer directly to the location of the object's code. This is really handy because you can have objects that you just spawn on demand that don't need to waste space in any of the level object lists (e.g. none of the player objects have IDs, because you'd never place them in a level layout), and you can also avoid the boring routine counter and jump table by just pushing a new code address to (a0) when you want the object to run different code next frame. Objects in S3&K use both this technique and the old routine technique, which obviously still works fine. If you do need the object to appear in a level, you need to add it to as slot under either Sprite_Listing3 or Sprite_ListingK (or both) depending on which levels you want to be able to use it in. Sprite_ListingK covers the levels that only appear in S&K excluding Flying Battery and the bonus stages, and Sprite_Listing3 covers everything else. The files for these are "Levels/Misc/Object list - Sonic 3.asm" and "Levels/Misc/Object list - Sonic & Knuckles.asm". I understand there are various differences in areas such as priority definition, but I don't really work with the other games so I can't tell you a lot about that. As usual, all the necessary helper routines probably have different names from any of the other disassemblies. So basically, write some object-style code, add a pointer to the start of it into one of the object lists if you want it in a level, ??? and profit.
Whoops, I always make that typo. Yeah, I know you added a huge load of stuff to Sonic 3, I just wasn't sure if it was along the lines of full new objects rather than, like you said, 'helper objects' or additions to existing routines. By location do you mean like the line in the ASM? Depending on if it translates any easier than Sonic 1, I may have something for next year's hacking contest. :D
For code writing purposes, I mean its starting label. So you'd define a simple object like: Code (Text): Obj_TitleANDKnuckles: move.l #Map_TitleANDKnuckles,mappings(a0) move.w #$E4C0,art_tile(a0) move.w #$120,x_pos(a0) move.w #$108,y_pos(a0) move.w #$80,priority(a0) move.b #$54,width_pixels(a0) move.b #$C,height_pixels(a0) move.l #Obj_TitleANDKnuckles_Display,(a0) Obj_TitleANDKnuckles_Display: move.w (Player_1+y_pos).w,d0 addi.w #$5C,d0 move.w d0,y_pos(a0) jmp (Draw_Sprite).l This is the big &KNUCKLES on the title screen that I don't use. Note how it skips its initialisation routine once run by changing its own code pointer to Obj_TitleANDKnuckles_Display, so Process_Sprites will come straight back to that point in future, rather than using a routine counter and jump table. If you're creating it procedurally, you'd do something like: Code (Text): jsr (Create_New_Sprite).l bne.s + move.l #Obj_TitleANDKnuckles,(a1) + As usual you can set anything else like x_pos(a1) and y_pos(a1) before the + if you want to, but there's no point with this object since it writes its own in anyway. If you have it in a level layout, you still give it an object ID by placing it in one of the lists I mentioned (add dc.l #Obj_TitleANDKnuckles like the other entries in those lists) and use that ID in the level layout. That much still works like it used to. But if you go and snoop in object RAM, you'll see its first four bytes are something like 00 00 49 6A, which is the ROM location of where the object code ended up. (Having your assembly generate a listing file as the Git disassemblies now do is really helpful for tracking this back to the actual code that object is running).
Thanx. I'll try. :P Concerning the Sonic 3 translation, I gave it a quick shot. I put it in the listings of both the 3 and Knuckles files too. So far it seems to be recognizing the object at least, but all it does is crash the game. I'm not fluent in Sonic 3 commands, is there anything in this that looks off here?: Code (ASM): Obj_Laser: moveq #0,d0 move.b $24(a0),d0 move.w Obj_Blob_Index(pc,d0.w),d0 jmp Obj_Blob_Index(pc,d0.w) Obj_Blob_Index: dc.w Obj_Blob_Init-Obj_Blob_Index dc.w Obj_Blob_Move-Obj_Blob_Index dc.w Obj_Blob_Destroy-Obj_Blob_Index Obj_Blob_Init: move.l #SME_0iwB5,mappings(a0) ; ($C) move.w #$79C,art_tile(a0) move.w #$2,priority(a0) move.b #$8,width_pixels(a0) move.b #$4,render_flags(a0) move.b #$4,y_radius(a0) ; $A move.l Obj_Laser_Display,(a0) Obj_Laser_Display: lea (Player_1).w,a1 move.b #$18,$30(a0) ; distance laser will travel move.w #$C4,d0 ; play sound jsr (Play_Sound).l cmpi.b #$29,$20(a1) beq.s Obj_Laser_DownwardNICOLE ; if not, branch move.w #$660,$18(a0) ; speed of laser jmp Obj_Laser_ContNICOLE Obj_Laser_DownwardNICOLE: move.w #$660,$1A(a0) ; speed of laser Obj_Laser_ContNICOLE: add.w #$10,x_pos(a0) btst #0,(Player_1).w beq.s + neg.w $10(a0) sub.w #$20,x_pos(a0) + lea (ArtSNK_Laser0).l,a1 move.w #$79C*$20,d2 jsr (SNKDec).l addq.b #2,$24(a0) ; Obj_Blob_Move: cmp.b #$0,$30(a0) beq.w Obj_Blob_Destroy sub.b #$1,$30(a0) jsr (loc_358A8).l move.b $40,$20(a0) ; lol clr.w d0 move.b mapping_frame(a0),d0 asl.w #$1,d0 ; *2 for correct offset lea (LaserArtPointers).l,a1 adda.w (a1,d0.w),a1 move.w #$79C*$20,d2 jsr (SNKDec).l lea (Ani_Laser).l,a1 jsr (Animate_Sprite).l jsr (sub_FE6E).l ;enemy and monitor data jmp (Draw_Sprite).l Obj_Blob_Destroy: clr.b ($FFFFFFA4).w ; clear NICOLE flag jmp Delete_Current_Sprite Ani_Laser: dc.w laser0-Ani_Laser laser0: dc.b 3,0,1,1,2,2,3,3,$FD,0 even SME_0iwB5: dc.w SME_0iwB5_8-SME_0iwB5, SME_0iwB5_12-SME_0iwB5 dc.w SME_0iwB5_1C-SME_0iwB5, SME_0iwB5_26-SME_0iwB5 SME_0iwB5_8: dc.b 0, 1 dc.b $F8, 5, 0, 0, 0, 0, $FF, $F8 SME_0iwB5_12: dc.b 0, 1 dc.b $F8, 5, 0, 0, 0, 0, $FF, $F8 SME_0iwB5_1C: dc.b 0, 1 dc.b $F8, 5, 0, 0, 0, 0, $FF, $F8 SME_0iwB5_26: dc.b 0, 1 dc.b $F8, 5, 0, 0, 0, 0, $FF, $F8 even I can get most of the other coding needed from my Amy hack, so if I get this bit working, I could probably get a basic build of S3 Sally done fairly quick.
Seriously enjoying this hack, E-122. Sally is doing a lot of things here to stand out from Amy in play style, and I'm liking the changes. (The disabled air cap leaves a lot of room for insane moves too, because after I fell in Chemical Plant Zone 2, I spindashed and jumped off a ramp to fly back above the water.) Although I think I'm going a little nuts with being able to shoot at things here. :specialed: I was camping at the rightmost totem-pole in Aquatic Ruin's boss while shooting at Eggman, and Sally's physics were pretty much disabled when the totems collapsed. I could walk around in mid-air, and it didn't stop until she jumped. I'm trying to remember if this is an issue in the vanilla game too, but here's a screenshot from playing on my DS with jEnesis.
It's likely to do with this bug here: http://info.sonicretro.org/SCHG_How-to:Fix_ARZ_Boss_Walking_on_Air_Glitch I'll try fixing it for a later update.
New revision uploaded: * Scan mode added. Like with S1, not a lot of objects to try it on, but effective enough when found. * Laser compatibility with WFZ entrance capsule added. * Some odd effects caused by laser reacting with objects fixed. * Odd cosmetic fixes. * Glitch that causes Sally to sometimes break objects by charging into them fixed. * Glitch that causes the projectile to collect rings fixed. * ARZ boss glitch which breaks Sally's gravity fixed. Remaining bugs: * Laser art is garbled in splitscreen. * Some art still doesn't transition properly with super mode. * Title screen glitches a little when skipped with Start button.
Don't know if you're still struggling with this, but there are a couple things I noticed: 1. SST offsets have changed in S3&K, for example, routine should be 5(a0) not $24(a0). Have a look at this wiki page for more info (I refer to it so often it's the top result if I type 'I' in my address bar :v: ) 2. I'm a bit concerned about this: Code (Text): lea (ArtSNK_Laser0).l,a1 move.w #$79C*$20,d2 jsr (SNKDec).l addq.b #2,$24(a0) ; I'm not familiar with the labels you're using, and SNKDec doesn't exist in the disasm I have, but many of the data loading routines do not work while in a level (for example, they can only be used on a menu screen, or when loading a level, but cannot be called by objects). I'm guessing you're trying to use DPLCs? In which case look at Sonic_Load_PLC, and the generic version Perform_DPLC for examples on how the game does it already. If you don't have those labels, loc_12CD6 and loc_8504A should go into the middle of them respectively. Hope this helps a bit!
Contest build added to the wiki. Not much new except a little bonus cheat: Play 03, 03, 03, 0B, 10, 10, 10 and 04 on the level select sound test for a hidden bonus. Sally in Sonic 1 is also updated, but since it has little but some rather minor bug and palette fixes, I'm not sure if it's worth noting.