Ok i'm porting the sonic 2 beta sonic's animations,maps pattern load cues,art every thing works but when I try to port the animations I get this F:\SONIC HACKING\SONIC1.ASM(25528) :Error:Branch (32942 bytes) is out of range F:\SONIC HACKING\SONIC1.ASM(25530) :Error:Branch (32932 bytes) is out of range I need some help. the code is;=============================================================================== ; Sub Routine Sonic_Animate ; [ Begin ] ;=============================================================================== Sonic_Animate: ; loc_10AB2: lea (Sonic_AnimateData), a1 ; loc_10CB4 moveq #0,d0 move.b $1C(a0), d0 cmp.b $1D(a0), d0 beq.s loc_10ADA move.b d0, $1D(a0) move.b #$00, $1B(a0) move.b #$00, $1E(a0) bclr #$5, $22(a0) loc_10ADA: add.w d0,d0 adda.w $00(a1,d0), a1 move.b (a1), d0 bmi.s loc_10B4A move.b $22(a0),d1 andi.b #$1,d1 andi.b #$FC, $1(a0) or.b d1, $1(a0) subq.b #$1, $1E(a0) bpl.s loc_10B18 move.b d0, $1E(a0) loc_10B00: moveq #0,d1 move.b $1B(a0),d1 move.b $1(a1,d1), d0 cmpi.b #$F0,d0 bcc.s loc_10B1A loc_10B10: move.b d0, $1A(a0) addq.b #$1, $1B(a0) loc_10B18: rts loc_10B1A: addq.b #$1,d0 bne.s loc_10B2A move.b #$00, $1B(a0) move.b $1(a1), d0 bra.s loc_10B10 loc_10B2A: addq.b #$1,d0 bne.s loc_10B3E move.b $2(a1,d1), d0 sub.b d0, $1B(a0) sub.b d0,d1 move.b $1(a1,d1), d0 bra.s loc_10B10 loc_10B3E: addq.b #$1,d0 bne.s loc_10B48 move.b $2(a1,d1), $1C(a0) loc_10B48: rts loc_10B4A: subq.b #$1, $1E(a0) bpl.s loc_10B18 addq.b #$1,d0 bne loc_10C3E moveq #0,d0 move.b $27(a0), d0 bne loc_10BD8 moveq #0,d1 move.b $26(a0), d0 move.b $22(a0),d2 andi.b #$1,d2 bne.s loc_10B72 not.b d0 loc_10B72: addi.b #$10,d0 bpl.s loc_10B7A moveq #$3,d1 loc_10B7A: andi.b #$FC, $1(a0) eor.b d1,d2 or.b d2, $1(a0) btst #$5, $22(a0) bne loc_10C82 lsr.b #$4,d0 andi.b #$6,d0 move.w $14(a0),d2 bpl.s loc_10B9E neg.w d2 loc_10B9E: lea (Sonic_Animate_Run), a1 ; loc_10D00 cmpi.w #$600,d2 bcc.s loc_10BB0 lea (Sonic_Animate_Walk), a1 ; loc_10CF2 loc_10BB0: move.b d0,d1 lsr.b #$1,d1 add.b d1,d0 add.b d0,d0 add.b d0,d0 move.b d0,d3 neg.w d2 addi.w #$800,d2 bpl.s loc_10BC6 moveq #0,d2 loc_10BC6: lsr.w #$8,d2 lsr.w #$1,d2 move.b d2, $1E(a0) bsr loc_10B00 add.b d3, $1A(a0) rts loc_10BD8: move.b $27(a0), d0 moveq #0,d1 move.b $22(a0),d2 andi.b #$1,d2 bne.s loc_10C06 andi.b #$FC, $1(a0) addi.b #$B,d0 divu.w #$16,d0 addi.b #$9B,d0 move.b d0, $1A(a0) move.b #$00, $1E(a0) rts loc_10C06: andi.b #$FC, $1(a0) tst.b $29(a0) beq.s loc_10C1E ori.b #$1, $1(a0) addi.b #$B,d0 bra.s loc_10C2A loc_10C1E: ori.b #$3, $1(a0) neg.b d0 addi.b #$8F,d0 loc_10C2A: divu.w #$16,d0 addi.b #$9B,d0 move.b d0, $1A(a0) move.b #$00, $1E(a0) rts loc_10C3E: addq.b #$1,d0 bne.s loc_10C82 move.w $14(a0),d2 bpl.s loc_10C4A neg.w d2 loc_10C4A: lea (Sonic_Animate_Roll2), a1 ; loc_10D18 cmpi.w #$600,d2 bcc.s loc_10C5C lea (Sonic_Animate_Roll), a1 ; loc_10D0E loc_10C5C: neg.w d2 addi.w #$400,d2 bpl.s loc_10C66 moveq #0,d2 loc_10C66: lsr.w #$8,d2 move.b d2, $1E(a0) move.b $22(a0),d1 andi.b #$1,d1 andi.b #$FC, $1(a0) or.b d1, $1(a0) bra loc_10B00 loc_10C82: move.w $14(a0),d2 bmi.s loc_10C8A neg.w d2 loc_10C8A: addi.w #$800,d2 bpl.s loc_10C92 moveq #0,d2 loc_10C92: lsr.w #$6,d2 move.b d2, $1E(a0) lea (Sonic_Animate_Push), a1 ; loc_10D22 move.b $22(a0),d1 andi.b #$1,d1 andi.b #$FC, $1(a0) or.b d1, $1(a0) bra loc_10B00 Sonic_AnimateData: ; loc_10CB4: dc.w Sonic_Animate_Walk-Sonic_AnimateData ; loc_10CF2 dc.w Sonic_Animate_Run-Sonic_AnimateData ; loc_10D00 dc.w Sonic_Animate_Roll-Sonic_AnimateData ; loc_10D0E dc.w Sonic_Animate_Roll2-Sonic_AnimateData ; loc_10D18 dc.w Sonic_Animate_Push-Sonic_AnimateData ; loc_10D22 dc.w Sonic_Animate_Wait-Sonic_AnimateData ; loc_10D30 dc.w Sonic_Animate_Balance-Sonic_AnimateData ; loc_10D59 dc.w Sonic_Animate_LookUp-Sonic_AnimateData ; loc_10D5D dc.w Sonic_Animate_Duck-Sonic_AnimateData ; loc_10D62 dc.w Sonic_Animate_Spindash-Sonic_AnimateData ; loc_10D67 dc.w Sonic_Animate_WallRecoil1-Sonic_AnimateData ; loc_10D74 dc.w Sonic_Animate_WallRecoil2-Sonic_AnimateData ; loc_10D77 dc.w Sonic_Animate_0x0C-Sonic_AnimateData ; loc_10D7D dc.w Sonic_Animate_Stop-Sonic_AnimateData ; loc_10D81 dc.w Sonic_Animate_Float1-Sonic_AnimateData ; loc_10D8C dc.w Sonic_Animate_Float2-Sonic_AnimateData ; loc_10D90 dc.w Sonic_Animate_0x10-Sonic_AnimateData ; loc_10D97 dc.w Sonic_Animate_S1LzHang-Sonic_AnimateData ; loc_10D9B dc.w Sonic_Animate_Unused_0x12-Sonic_AnimateData ; loc_10D9F dc.w Sonic_Animate_Unused_0x13-Sonic_AnimateData ; loc_10DA5 dc.w Sonic_Animate_Unused_0x14-Sonic_AnimateData ; loc_10DAA dc.w Sonic_Animate_Bubble-Sonic_AnimateData ; loc_10DAD dc.w Sonic_Animate_Death1-Sonic_AnimateData ; loc_10DB4 dc.w Sonic_Animate_Drown-Sonic_AnimateData ; loc_10DB7 dc.w Sonic_Animate_Death2-Sonic_AnimateData ; loc_10DBA dc.w Sonic_Animate_Unused_0x19-Sonic_AnimateData ; loc_10DBD dc.w Sonic_Animate_Hurt-Sonic_AnimateData ; loc_10DC6 dc.w Sonic_Animate_S1LzSlide-Sonic_AnimateData ; loc_10DC9 dc.w Sonic_Animate_0x1C-Sonic_AnimateData ; loc_10DCD dc.w Sonic_Animate_Float3-Sonic_AnimateData ; loc_10DD1 dc.w Sonic_Animate_0x1E-Sonic_AnimateData ; loc_10DD8 Sonic_Animate_Walk: ; loc_10CF2: dc.b $FF, $10, $11, $12, $13, $14, $15, $16, $17, $C, $D, $E, $F, $FF Sonic_Animate_Run: ; loc_10D00: dc.b $FF, $3C, $3D, $3E, $3F, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF Sonic_Animate_Roll: ; loc_10D0E: dc.b $FE, $6C, $70, $6D, $70, $6E, $70, $6F, $70, $FF Sonic_Animate_Roll2: ; loc_10D18: dc.b $FE, $6C, $70, $6D, $70, $6E, $70, $6F, $70, $FF Sonic_Animate_Push: ; loc_10D22: dc.b $FD, $77, $78, $79, $7A, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF Sonic_Animate_Wait: ; loc_10D30: dc.b $7, $1, $1, $1, $1, $1, $1, $1, $1, $1, $1, $1, $1, $1, $1, $1 dc.b $1, $1, $1, $1, $1, $1, $1, $1, $1, $1, $1, $1, $1, $1, $1, $2 dc.b $3, $3, $3, $4, $4, $5, $5, $FE, $4 Sonic_Animate_Balance: ; loc_10D59: dc.b $7, $89, $8A, $FF Sonic_Animate_LookUp: ; loc_10D5D: dc.b $5, $6, $7, $FE, $1 Sonic_Animate_Duck: ; loc_10D62: dc.b $5, $7F, $80, $FE, $1 Sonic_Animate_Spindash: ; loc_10D67: dc.b $00, $71, $72, $71, $73, $71, $74, $71, $75, $71, $76, $71, $FF Sonic_Animate_WallRecoil1: ; loc_10D74: dc.b $3F, $82, $FF Sonic_Animate_WallRecoil2: ; loc_10D77: dc.b $7, $8, $8, $9, $FD, $5 Sonic_Animate_0x0C: ; loc_10D7D: dc.b $7, $9, $FD, $5 Sonic_Animate_Stop: ; loc_10D81: dc.b $3, $81, $82, $83, $84, $85, $86, $87, $88, $FE, $2 Sonic_Animate_Float1: ; loc_10D8C: dc.b $7, $94, $96, $FF Sonic_Animate_Float2: ; loc_10D90: dc.b $7, $91, $92, $93, $94, $95, $FF Sonic_Animate_0x10: ; loc_10D97: dc.b $2F, $7E, $FD, $00 Sonic_Animate_S1LzHang: ; loc_10D9B: dc.b $5, $8F, $90, $FF Sonic_Animate_Unused_0x12: ; loc_10D9F: dc.b $F, $43, $43, $43, $FE, $1 Sonic_Animate_Unused_0x13: ; loc_10DA5: dc.b $F, $43, $44, $FE, $1 Sonic_Animate_Unused_0x14: ; loc_10DAA: dc.b $3F, $49, $FF Sonic_Animate_Bubble: ; loc_10DAD: dc.b $B, $97, $97, $12, $13, $FD, $00 Sonic_Animate_Death1: ; loc_10DB4: dc.b $20, $9A, $FF Sonic_Animate_Drown: ; loc_10DB7: dc.b $20, $99, $FF Sonic_Animate_Death2: ; loc_10DBA: dc.b $20, $98, $FF Sonic_Animate_Unused_0x19: ; loc_10DBD: dc.b $3, $4E, $4F, $50, $51, $52, $00, $FE, $1 Sonic_Animate_Hurt: ; loc_10DC6: dc.b $40, $8D, $FF Sonic_Animate_S1LzSlide: ; loc_10DC9: dc.b $9, $8D, $8E, $FF Sonic_Animate_0x1C: ; loc_10DCD: dc.b $77, $00, $FD, $00 Sonic_Animate_Float3: ; loc_10DD1: dc.b $3, $91, $92, $93, $94, $95, $FF Sonic_Animate_0x1E: ; loc_10DD8: dc.b $3, $3C, $FD, $00 ;=============================================================================== ; Sub Routine Sonic_Animate ; [ End ]
Out-of-range errors, probably the most common type of error and also one of the most annoying ones. Basically, whatever it is you're doing there isn't the direct cause for your compilation failing; it's just that somewhere else the game tried to reach something, but can't do so now because of the newly inserted code being larger than what was there before. Simple rules apply to fixing these errors. Open the mentioned file, find the mentioned lines, and check what size your branch has. In 9 out of 10 cases you'll find that the line is something like: Code: bra.s SomeLabel Simply replace the .s (which stands for "short") with a .w (which stands for "word"). Shorts, as the name implies, only have a small branching range (but are more efficient for short distances, hence their point), whereas words are much, much larger (in numbers, shorts have a total range of a byte; words have a range of, well, a word). However, should you find that the errors in question already have a .w, a different way is required to fix them, which is replacing them with so-called "jumps". Jumps are essentially the same thing as branches, only that they don't relatively go to another place based on where the branch is executed, but rather work on an absolute basis, meaning they can go from one end of the ROM to the other with ease. The disadvantage is that there are no conditional jumps (so nothing like "beq" or "bne" applies to jumps, although some people have made custom macros to simulate "jeq" and the likes), and jumps are also considerably less efficient. Only use them when you absolutely must! (No pun intended.) In case you have a bra.w and that line only, you can simply replace it with jmp. In case you have a bsr.w and that line only, you can simply replace it with jsr. If it's any other command than bra or bsr, it's a conditional operation. Fixing those errors can be a little harder to grasp. There are two ways to do this. The first one: You need to create a new label somewhere else which jumps to the actual result, and instead go to that via the branch. I think an example is easier to understand: This: Code: cmpi.b #$18,($FFFFFFFF).w ; is that RAM address set to $18? bne.w SomeOutOfRangeLabel ; if not, branch Becomes this: Code: cmpi.b #$18,($FFFFFFFF).w ; is that RAM address set to $18? bne.s JumpTo_SomeOutOfRangeLabel ; if not, branch ; some other code in between here JumpTo_SomeOutOfRangeLabel: jmp SomeOutOfRangeLabel The other method (which I've also touched in my old as hell Basic Error Fixing Guide) is negating the instruction and instead making a skip. Negating bne results into beq, negating bgt results into ble and so on. As an example (based on the above code): Code: cmpi.b #$18,($FFFFFFFF).w ; is that RAM address set to $18? beq.s SkipJump ; if YES, branch (changed from bne) jmp SomeOutOfRangeLabel SkipJump: ... I personally prefer this second method, as I don't need to find a place to put the JumpTo branch and instead can keep everything in one place. However, it requires knowledge of the various conditional branch instructions, so you should memorize the table at the bottom of this page. Here's hope this made any sense to you. It's really easy to fix these errors and becomes second nature at some point (because you need to prepare to get confronted with them a lot), but they can be confusing and infuriating for beginners. LATE EDIT: Fixed IPB's conversion bullshit.
Actually don't replace the .s with .w, just remove it and let the assembler decide if it should use a byte or a word for the branch. A few years ago I removed all instances of .s and .w in the Sonic One disassembly and enabled branch optimizations (this was with asm68k) and the final size of s1built.bin decreased. This was because some branches that were using a word offset could have used a byte offset.
The assembler "asm68k", does not run enough passes to ensure the smallest size is used, in fact, I recall asm68k (only running one main pass of optimisation) causes backwards branches to optimise fine, but forward branches to remain at word, despite being able to assemble as short. If you want to get the best result, you will need an assembler than runs multi-passing until no optimisations can be found, I believe the AS assembler is able to do this. However, telling people that they should optimise best for size, is wrong, and it's wrong because it depends on circumstance and situation. One individual may need the size, therefore, letting the assembler find the best result is the most suited. Another individual may require quick assembly results for fast and immediate testing (i.e. write, assemble, test, write, assemble, test), therefore, size optimisation with minor branch instructions is not suited as it can take precious time, if the code is complex and requires quick actions to be taken to prevent forgetting vital details, fast assembly time is a importance. I am not trying to deter people from following your suggestion, I think it is the right suggestion, I just think it's for the wrong reasons. One should not place .s or .w unless it is necessary (e.g. a jump table of branches with specific size), and should assign the assembler to multi-pass, or NOT, depending on the required situation (do they need ROM speed/size, or assembly speed?).
Optimizations are very context-sensitive, with different situations calling for different types of optimizations. One size does not fit all. Also, would help if you actually indicated which lines are the two indicated by the error. Sure, some of us who know the system well enough could just go through your code and hand-calculate the branches, but we've got better things to do with our lives, to be honest. Really, though, with out-of-range errors, the assembler pretty directly points you to where the problem is, and solutions are pretty straightforward. Selbi covered a reasonable enough approach to correcting it on your own. Really not terribly hard once you get the hang of it. On an unrelated but administrative note, topic names in all caps are pretty obnoxious, so please don't do that. Basic English grammar and spelling is all we ask, and we're usually pretty forgiving on both.
I usually rather to do optimizations by hand, to ensure it is correctly optimized. If it does not matter in the case, I leave it up to the assembler to do whatever.
But really, how much size does it save by going from .w to .b? Like, bugger all? Yeah, yeah, if you did it with every single one and add them all up it could come to save quite a bit. But I think it would be pointles to do it to save space unless your final ROM size came to 513KBs or 1025KBs, etc =P
Completely unrelated, I just noticed that the code boxes were entirely fucked up in my post. Sigh. IPB is gone and it still haunts me.