Skip to content

Instantly share code, notes, and snippets.

@magical
Last active August 29, 2015 14:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save magical/bbd62ff7706af4a549b0 to your computer and use it in GitHub Desktop.
Save magical/bbd62ff7706af4a549b0 to your computer and use it in GitHub Desktop.
Pokémon X capture routine analysis
; Pokemon X capture routine
; DllBattle.cro .text+0x2ee40
; tl;dr everything is pretty much the same
; but with more floating point.
; there are four shake checks again instead of three
; and the fourth root is now a 16/3 root.
; looks like we're going to use a truly staggering number of registers
2ee40: e92d4fff push {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, lr}
2ee44: e1a04001 mov r4, r1
2ee48: e3a09000 mov r9, #0
2ee4c: e1a0a003 mov r10, r3 ; the pokemon
; push some floating point registers too
2ee50: ed2d8b0c vpush {d8-d13}
2ee54: e24dd004 sub sp, sp, #4
2ee58: e28d106c add r1, sp, #108 ; = (13*4 + 6*8 + 4) + 4
; r5 and r8 are our "out" pointers for shakes and crit
2ee5c: e8910120 ldm r1, {r5, r8}
; if using the master ball, or something mysterious is non-zero...
2ee60: e59d7068 ldr r7, [sp, #104]
2ee64: e3570001 cmp r7, #1
2ee68: e5c89000 strb r9, [r8]
2ee6c: 0a000004 beq 0x2ee84
2ee70: e5940004 ldr r0, [r4, #4]
2ee74: e5900010 ldr r0, [r0, #16]
2ee78: e5d000b2 ldrb r0, [r0, #178]
2ee7c: e3500000 cmp r0, #0
2ee80: 0a000006 beq 0x2eea0
; ...automatic success!
2ee84: e3a00003 mov r0, #3
2ee88: e5c50000 strb r0, [r5]
2ee8c: e3a00001 mov r0, #1
; we'll come back here later on because who wants to clean up twice
2ee90: e28dd004 add sp, sp, #4
2ee94: ecbd8b0c vpop {d8-d13}
2ee98: e28dd010 add sp, sp, #16
2ee9c: e8bd8ff0 pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}
2eea0: e3a0100e mov r1, #14 ; get max hp
2eea4: e1a00003 mov r0, r3
2eea8: eb0114fc bl 0x742a0
2eeac: e080b080 add r11, r0, r0, lsl #1 ; mul by 3
2eeb0: e3a0100d mov r1, #13 ; get cur hp
2eeb4: e1a0000a mov r0, r10
2eeb8: eb0114f8 bl 0x742a0
2eebc: e2600000 rsb r0, r0, #0 ; negate
2eec0: ed9faaf2 vldr s20, [pc, #968] ; 0x2f290 = 0.5f
2eec4: e09b0080 adds r0, r11, r0, lsl #1 ; max*3 - cur*2
2eec8: eddfaaf1 vldr s21, [pc, #964] ; 0x2f294 = 0
2eecc: 0d9f0af1 vldreq s0, [pc, #964] ; 0x2f298 = -0.5f
2eed0: 0a000003 beq 0x2eee4
2eed4: e1a00600 lsl r0, r0, #12 ; convert to fixed point
2eed8: ee000a10 vmov s0, r0 ; convert to float
2eedc: eeb80a40 vcvt.f32.u32 s0, s0
2eee0: ee300a0a vadd.f32 s0, s0, s20 ; add 0.5
; If a thing is true (something about terrain?)...
; [This, of course, is where the dark grass penalty was in B/W
; but there is no dark grass in X/Y
; is there?]
2eee4: e5940004 ldr r0, [r4, #4]
2eee8: e5900010 ldr r0, [r0, #16]
2eeec: e59010a8 ldr r1, [r0, #168]
2eef0: eebd0ac0 vcvt.s32.f32 s0, s0
2eef4: e3110020 tst r1, #32
2eef8: ee106a10 vmov r6, s0
2eefc: 0a00001a beq 0x2ef6c
; get ye olde dex counte
2ef00: e5900084 ldr r0, [r0, #132]
2ef04: e3500000 cmp r0, #0
2ef08: 0a000011 beq 0x2ef54
2ef0c: e3a01000 mov r1, #0
2ef10: ebff46bf bl 0xa14
; 601+ - x1.0
2ef14: e3500f96 cmp r0, #600
2ef18: 83a00a01 movhi r0, #4096 ; 0x1000
2ef1c: 8a00000d bhi 0x2ef58
; 451-600 - x0.9
2ef20: e59f1374 ldr r1, [pc, #884] ; 0x2f29c = 0x1c2 = 450
2ef24: e1500001 cmp r0, r1
2ef28: 859f0370 ldrhi r0, [pc, #880] ; 0x2f2a0 = 0xe66
2ef2c: 8a000009 bhi 0x2ef58
; 301-450 - x0.8
2ef30: e3500f4b cmp r0, #300
2ef34: 859f0368 ldrhi r0, [pc, #872] ; 0x2f2a4 = 0xccd
2ef38: 8a000006 bhi 0x2ef58
; 151-301 - x0.7
2ef3c: e3500096 cmp r0, #150
2ef40: 859f0360 ldrhi r0, [pc, #864] ; 0x2f2a8 = 0xb33
2ef44: 8a000003 bhi 0x2ef58
; 31-150 - x0.5
2ef48: e350001e cmp r0, #30
2ef4c: 83a00b02 movhi r0, #2048 ; 0x800
2ef50: 8a000000 bhi 0x2ef58
; 0-30 - x0.3
2ef54: e59f0350 ldr r0, [pc, #848] ; 0x2f2ac = 0x4cd
; factor the penalty in
2ef58: e0c10096 smull r0, r1, r6, r0
; round
2ef5c: e2900b02 adds r0, r0, #2048 ; 0x800
2ef60: e2a11000 adc r1, r1, #0
2ef64: e1a00620 lsr r0, r0, #12
2ef68: e1806a01 orr r6, r0, r1, lsl #20
; Catch rate
2ef6c: e1da00bc ldrh r0, [r10, #12]
2ef70: e5da1153 ldrb r1, [r10, #339]
2ef74: e3a02008 mov r2, #8
2ef78: e58d2000 str r2, [sp]
2ef7c: ebff46a6 bl 0xa1c ; load pokemon's base stats
2ef80: e59d0000 ldr r0, [sp]
2ef84: e320f000 nop {0}
2ef88: ebff46a5 bl 0xa24 ; get catch rate
2ef8c: e6ff0070 uxth r0, r0
; Ball bonus
2ef90: e58d7000 str r7, [sp] ; the ball
2ef94: e0060096 mul r6, r6, r0 ; (factor catch rate in)
2ef98: e59d0034 ldr r0, [sp, #52]
2ef9c: e59d203c ldr r2, [sp, #60]
2efa0: e1a0300a mov r3, r10 ; pokemon
2efa4: e1a01004 mov r1, r4
2efa8: eb00029f bl 0x2fa2c ; ball bonus routine, see below
; multiply, round
2efac: e0c10096 smull r0, r1, r6, r0
2efb0: e2900b02 adds r0, r0, #2048 ; 0x800
2efb4: e2a11000 adc r1, r1, #0
2efb8: e1a00620 lsr r0, r0, #12
2efbc: e1800a01 orr r0, r0, r1, lsl #20
; divide by 3*Max HP
2efc0: e1a0100b mov r1, r11 ; r11 is 3*maxhp
2efc4: ebff44b4 bl 0x29c ; unsigned 32-bit division
; Status modifier
2efc8: e1a06000 mov r6, r0
2efcc: e1a0000a mov r0, r10
2efd0: eb00f9d5 bl 0x6d72c
; jump table
2efd4: e3500006 cmp r0, #6
2efd8: 379ff100 ldrcc pc, [pc, r0, lsl #2]
2efdc: ea000012 b 0x2f02c
; not sure which entry is which, but it doesn't really matter
2efe0: 0002f02c
2efe4: 0002f014
2efe8: 0002eff8
2efec: 0002eff8
2eff0: 0002f014
2eff4: 0002f014
; the large bonus is 2.5
2eff8: e3a00b0a mov r0, #10240 ; 0x2800
2effc: e0c01096 smull r1, r0, r6, r0
2f000: e2911b02 adds r1, r1, #2048 ; 0x800
2f004: e2a00000 adc r0, r0, #0
2f008: e1a01621 lsr r1, r1, #12
2f00c: e1816a00 orr r6, r1, r0, lsl #20
2f010: ea000005 b 0x2f02c
; the small bonus is 1.5
2f014: e3a00b06 mov r0, #6144 ; 0x1800
2f018: e0c10096 smull r0, r1, r6, r0
2f01c: e2900b02 adds r0, r0, #2048 ; 0x800
2f020: e2a11000 adc r1, r1, #0
2f024: e1a00620 lsr r0, r0, #12
2f028: e1806a01 orr r6, r0, r1, lsl #20
; Moving on. Lots of floating-point instructions ahead.
; Historically, this is where Entralink and Critical capture would be.
2f02c: e5940004 ldr r0, [r4, #4]
2f030: ed9fca9e vldr s24, [pc, #632] ; 0x2f2b0 (0x45800000 = 4096.0f)
2f034: ed9f9b9f vldr d9, [pc, #636] ; 0x2f2b8 (1/4096.0)
2f038: ed9f8ba0 vldr d8, [pc, #640] ; 0x2f2c0 (0)
; If wotsit is 0, skip this stuff
2f03c: e5900010 ldr r0, [r0, #16]
2f040: e59000b8 ldr r0, [r0, #184]
2f044: e3500000 cmp r0, #0
2f048: 0a000012 beq 0x2f098
; otherwise...
; convert our fixed-point intermediate catch rate into a floating point
; number to pass to the mysterious function below
2f04c: e1a01646 asr r1, r6, #12 ; r6 /= 4096
2f050: ee001a10 vmov s0, r1 ; convert to fp
2f054: e1a01a06 lsl r1, r6, #20 ; get fractional part
2f058: e1b01a21 lsrs r1, r1, #20
2f05c: eeb81bc0 vcvt.f64.s32 d1, s0
2f060: 1e001a10 vmovne s0, r1 ; add frac back in
2f064: 1eb80bc0 vcvtne.f64.s32 d0, s0
2f068: 1e200b09 vmulne.f64 d0, d0, d9
2f06c: 0eb00b48 vmoveq.f64 d0, d8
2f070: ee310b00 vadd.f64 d0, d1, d0
2f074: eeb70bc0 vcvt.f32.f64 s0, d0
2f078: ebff466b bl 0xa2c ; mysterious function
; here's what the mysterious function does: it takes its argument (s0),
; loads a mysterious number from somewhere based on its other argument (r0),
; multiplies them together and divides by 100 (well, multiplies by 0.01)
; all in double-precision floating point because why not!
; now of course we convert it back to 12-bit fixed point
2f07c: eeb40aea vcmpe.f32 s0, s21 ; s21 is 0.0
2f080: eef1fa10 vmrs APSR_nzcv, fpscr
2f084: eef00a4a vmov.f32 s1, s20 ; s20 is 0.5
2f088: ce400a0c vmlagt.f32 s1, s0, s24 ; s24 is 4096.0
2f08c: de500a0c vnmlsle.f32 s1, s0, s24
2f090: eebd0ae0 vcvt.s32.f32 s0, s1
2f094: ee106a10 vmov r6, s0
; whew
; Critical capture
2f098: e5940004 ldr r0, [r4, #4]
2f09c: e59fa224 ldr r10, [pc, #548] ; 0x2f2c8
; copy capture chance to r7 for the following calculations
2f0a0: e1a07006 mov r7, r6
2f0a4: e5900010 ldr r0, [r0, #16]
; dex count again
2f0a8: e5900084 ldr r0, [r0, #132]
2f0ac: e3500000 cmp r0, #0
2f0b0: 0a000021 beq 0x2f13c
2f0b4: e3a01000 mov r1, #0
2f0b8: ebff4655 bl 0xa14
; 601+ - 2.5
2f0bc: e3500f96 cmp r0, #600
2f0c0: 83a00b0a movhi r0, #10240 ; 0x2800
2f0c4: 8a00000c bhi 0x2f0fc
; 451-600 - 2.0
2f0c8: e59f11cc ldr r1, [pc, #460] ; 0x2f29c (450)
2f0cc: e1500001 cmp r0, r1
2f0d0: 83a00a02 movhi r0, #8192 ; 0x2000
2f0d4: 8a000008 bhi 0x2f0fc
; 301-450 - 1.5
2f0d8: e3500f4b cmp r0, #300
2f0dc: 83a00b06 movhi r0, #6144 ; 0x1800
2f0e0: 8a000005 bhi 0x2f0fc
; 151-300 - 1.0
2f0e4: e3500096 cmp r0, #150
2f0e8: 83a00a01 movhi r0, #4096 ; 0x1000
2f0ec: 8a000002 bhi 0x2f0fc
; 31-150 - 0.5
2f0f0: e350001e cmp r0, #30
2f0f4: 83a00b02 movhi r0, #2048 ; 0x800
; 0-30 - skip
2f0f8: 9a00000f bls 0x2f13c
; cap capture rate at 255.0
2f0fc: e3570aff cmp r7, #1044480 ; 0xff000
2f100: c3a07aff movgt r7, #1044480 ; 0xff000
; multiply by bonus, round
2f104: e0c10097 smull r0, r1, r7, r0
2f108: e2900b02 adds r0, r0, #2048 ; 0x800
2f10c: e2a11000 adc r1, r1, #0
2f110: e1a00620 lsr r0, r0, #12
2f114: e1800a01 orr r0, r0, r1, lsl #20
; magic signed division by 6
2f118: e59f11ac ldr r1, [pc, #428] ; 0x2f2cc (0x2aaaaaab)
2f11c: e0c01091 smull r1, r0, r1, r0
2f120: e3a01c01 mov r1, #256
2f124: e0404fc0 sub r4, r0, r0, asr #31
; roll the dice
; it's a crit if rand(256) < the crit. capture chance
; the chance is truncated for the comparison
2f128: e59a0054 ldr r0, [r10, #84] ; pointer to rand state
2f12c: ebff444a bl 0x25c ; rand
2f130: e1500644 cmp r0, r4, asr #12
2f134: 33a00001 movcc r0, #1
2f138: 3a000000 bcc 0x2f140
2f13c: e1a00009 mov r0, r9 ; r9 is 0
; If the capture rate is >= 255.0, automatic success.
; Set shakes to 3 (or 1 in case of crit) and return success
2f140: e3560aff cmp r6, #1044480 ; 0xff000
2f144: e5c80000 strb r0, [r8] ; crit
2f148: ba000005 blt 0x2f164
2f14c: e3500000 cmp r0, #0
2f150: 13a00001 movne r0, #1
2f154: 03a00003 moveq r0, #3
2f158: e5c50000 strb r0, [r5] ; shakes
2f15c: e3a00001 mov r0, #1
2f160: eaffff4a b 0x2ee90 ; jump back to the top to return
; OH MY GOD. THE VFP INSTRUCTIONS. THEY'RE BACK
; convert capture chance to fp
2f164: e1a00646 asr r0, r6, #12
2f168: ee010a10 vmov s2, r0
2f16c: e1a00a06 lsl r0, r6, #20
2f170: ed9f0b56 vldr d0, [pc, #344] ; 0x2f2d0 (255.0f)
2f174: e1b00a20 lsrs r0, r0, #20
2f178: 1e020a10 vmovne s4, r0
2f17c: ed9fdb55 vldr d13, [pc, #340] ; 0x2f2d8 (4096.0f)
2f180: eeb81bc1 vcvt.f64.s32 d1, s2
2f184: ed9fbb55 vldr d11, [pc, #340] ; 0x2f2e0 (0.5f)
2f188: 1eb82bc2 vcvtne.f64.s32 d2, s4
2f18c: 1e222b09 vmulne.f64 d2, d2, d9 ; d9 is still 1/4096
2f190: 0eb02b48 vmoveq.f64 d2, d8 ; d8 is still 0
2f194: ee311b02 vadd.f64 d1, d1, d2
2f198: eeb41b48 vcmp.f64 d1, d8
2f19c: eef1fa10 vmrs APSR_nzcv, fpscr
2f1a0: 01a00009 moveq r0, r9
2f1a4: 0a000007 beq 0x2f1c8
; divide 255.0 by catch rate
2f1a8: ee802b01 vdiv.f64 d2, d0, d1
; convert back to fixed point
2f1ac: eeb42bc8 vcmpe.f64 d2, d8
2f1b0: eef1fa10 vmrs APSR_nzcv, fpscr
2f1b4: eeb00b4b vmov.f64 d0, d11
2f1b8: ce020b0d vmlagt.f64 d0, d2, d13
2f1bc: de120b0d vnmlsle.f64 d0, d2, d13
2f1c0: eebd0bc0 vcvt.s32.f64 s0, d0
2f1c4: ee100a10 vmov r0, s0
; convert back to floating point
2f1c8: e1a01640 asr r1, r0, #12
2f1cc: ee001a10 vmov s0, r1
2f1d0: e1a00a00 lsl r0, r0, #20
2f1d4: e1b00a20 lsrs r0, r0, #20
2f1d8: eeb81bc0 vcvt.f64.s32 d1, s0
2f1dc: 1e000a10 vmovne s0, r0
2f1e0: 1eb80bc0 vcvtne.f64.s32 d0, s0
2f1e4: 1e200b09 vmulne.f64 d0, d0, d9
2f1e8: 0eb00b48 vmoveq.f64 d0, d8
2f1ec: ee310b00 vadd.f64 d0, d1, d0
2f1f0: eeb70bc0 vcvt.f32.f64 s0, d0
; !!!
; call powf(x, 0.1875)
2f1f4: eddf0a3b vldr s1, [pc, #236] ; 0x2f2e8 (0.1875 = 3/16)
2f1f8: ebff460d bl 0xa34 ; powf
; convert back to fixed-point
2f1fc: eeb40aea vcmpe.f32 s0, s21
2f200: eef1fa10 vmrs APSR_nzcv, fpscr
2f204: ed9f1b39 vldr d1, [pc, #228] ; 0x2f2f0 (65536.0)
2f208: ce00aa0c vmlagt.f32 s20, s0, s24
2f20c: de10aa0c vnmlsle.f32 s20, s0, s24
2f210: eebd0aca vcvt.s32.f32 s0, s20
2f214: ee100a10 vmov r0, s0
; convert back to floating point
2f218: e1a01640 asr r1, r0, #12
2f21c: ee001a10 vmov s0, r1
2f220: e1a00a00 lsl r0, r0, #20
2f224: e1b00a20 lsrs r0, r0, #20
2f228: eeb82bc0 vcvt.f64.s32 d2, s0
2f22c: 1e000a10 vmovne s0, r0
2f230: 1eb80bc0 vcvtne.f64.s32 d0, s0
2f234: 1e200b09 vmulne.f64 d0, d0, d9
2f238: 0eb00b48 vmoveq.f64 d0, d8
2f23c: ee322b00 vadd.f64 d2, d2, d0
2f240: eeb42b48 vcmp.f64 d2, d8
2f244: eef1fa10 vmrs APSR_nzcv, fpscr
; (if zero, skip the next step)
2f248: 01a00009 moveq r0, r9
2f24c: 0a000006 beq 0x2f26c
; divide 65536.0 by our twisted, mutilated value
2f250: ee810b02 vdiv.f64 d0, d1, d2
; and convert back to fixed-point
2f254: eeb40bc8 vcmpe.f64 d0, d8
2f258: eef1fa10 vmrs APSR_nzcv, fpscr
2f25c: ce00bb0d vmlagt.f64 d11, d0, d13
2f260: de10bb0d vnmlsle.f64 d11, d0, d13
2f264: eebd0bcb vcvt.s32.f64 s0, d11
2f268: ee100a10 vmov r0, s0
; now we're pretty much done
; let's call this final value the shake chance
; Figure out how many shakes to attempt.
; One for crit.
; Four(!) otherwise.
2f26c: e5c59000 strb r9, [r5] ; shakes = 0
2f270: e3a04000 mov r4, #0
2f274: e1a06640 asr r6, r0, #12
2f278: e5d80000 ldrb r0, [r8]
2f27c: e3500000 cmp r0, #0
2f280: 13a07001 movne r7, #1
2f284: 03a07004 moveq r7, #4
; The top of this loop is waaaay up here on top of all
; these constants that we've been loading like crazy.
2f288: e3a01801 mov r1, #65536 ; 0x10000
2f28c: ea000019 b 0x2f2f8
; ignore the following lines
2f290: 3f000000
2f294: 00000000
2f298: bf000000
2f29c: 000001c2
2f2a0: 00000e66
2f2a4: 00000ccd
2f2a8: 00000b33
2f2ac: 000004cd
2f2b0: 45800000
2f2b4: 00000000
2f2b8: 00000000
2f2bc: 3f300000
2f2c0: 00000000
2f2c4: 00000000
2f2c8: 00000000
2f2cc: 2aaaaaab
2f2d0: 00000000
2f2d4: 406fe000
2f2d8: 00000000
2f2dc: 40b00000
2f2e0: 00000000
2f2e4: 3fe00000
2f2e8: 3e400000
2f2ec: 00000000
2f2f0: 00000000
2f2f4: 40f00000
; hello again
; if rand(65536) >= the shake chance, the pokemon breaks free
2f2f8: e59a0054 ldr r0, [r10, #84] ; load rand state
2f2fc: ebff43d6 bl 0x25c ; rand
2f300: e1500006 cmp r0, r6
2f304: e320f000 nop {0}
2f308: 2a000008 bcs 0x2f330 ; goto failure
2f30c: e5d50000 ldrb r0, [r5]
2f310: e2844001 add r4, r4, #1 ; increment counter
2f314: e3500003 cmp r0, #3 ; increment shakes
2f318: 32800001 addcc r0, r0, #1 ; ...but not past 3!
2f31c: 35c50000 strbcc r0, [r5]
2f320: e1540007 cmp r4, r7 ; if counter < max shakes
2f324: 3affffd7 bcc 0x2f288 ; loop
; note that we make up to four checks,
; but the returned shake count (r5)
; is capped at three
; whether or not fourth last check succeeded
; can be determined by whether the capture as a whole succeeded
; that is, four successful checks returns success (shakes=3)
; three successful checks and a failure returns failure (shakes=3)
2f328: e3a00001 mov r0, #1 ; return success
2f32c: eafffed7 b 0x2ee90
2f330: e3a00000 mov r0, #0 ; return failure
2f334: eafffed5 b 0x2ee90
; the end
; Ball bonus routine
; push a much more reasonable set of registers
2fa2c: e92d4010 push {r4, lr}
2fa30: e1a04003 mov r4, r3
2fa34: e59d0008 ldr r0, [sp, #8]
2fa38: e2400002 sub r0, r0, #2
2fa3c: e350000e cmp r0, #14
; jump table
2fa40: 379ff100 ldrcc pc, [pc, r0, lsl #2]
2fa44: ea00006c b 0x2fbfc
2fa48: 0002fa88 ; great
2fa4c: 0002fa80 ; ultra
2fa50: 0002fbfc ; poke
2fa54: 0002fbfc ; safari
2fa58: 0002fa90 ; net
2fa5c: 0002fac4 ; dive
2fa60: 0002fae0 ; nest
2fa64: 0002fb48 ; repeat
2fa68: 0002fb7c ; timer
2fa6c: 0002fbfc ; luxury
2fa70: 0002fbfc ; premier
2fa74: 0002fb98 ; dusk
2fa78: 0002fbfc ; heal
2fa7c: 0002fbec ; quick
; Great Ball
2fa80: e3a00b06 mov r0, #6144 ; 0x1800
2fa84: e8bd8010 pop {r4, pc}
; Ultra Ball
2fa88: e3a00a02 mov r0, #8192 ; 0x2000
2fa8c: e8bd8010 pop {r4, pc}
; Net Ball
2fa90: e3a0100a mov r1, #10 ; bug type
2fa94: e1a00003 mov r0, r3
2fa98: eb00ff50 bl 0x6f7e0
2fa9c: e3500000 cmp r0, #0
2faa0: e320f000 nop {0}
2faa4: 1a000032 bne 0x2fb74 ; ->3.0
2faa8: e3a01006 mov r1, #6 ; water type
2faac: e1a00004 mov r0, r4
2fab0: eb00ff4a bl 0x6f7e0
2fab4: e3500000 cmp r0, #0
2fab8: e320f000 nop {0}
2fabc: 1a00002c bne 0x2fb74 ; -> 3.0
2fac0: ea00004d b 0x2fbfc
; Dive Ball
2fac4: e5910004 ldr r0, [r1, #4]
2fac8: e5900010 ldr r0, [r0, #16]
2facc: e59000a8 ldr r0, [r0, #168]
2fad0: e3100001 tst r0, #1
2fad4: 03100901 tsteq r0, #16384 ; 0x4000
2fad8: 1a000041 bne 0x2fbe4 ; ->3.5
2fadc: ea000046 b 0x2fbfc
; Nest Ball
2fae0: e3a0100f mov r1, #15
2fae4: e1a00003 mov r0, r3
2fae8: eb0111ec bl 0x742a0
2faec: e6ff0070 uxth r0, r0
; if level is >= 30, forgeddaboudit
2faf0: e350001e cmp r0, #30
2faf4: 2a000040 bcs 0x2fbfc
; subtract level from 41
2faf8: e2600029 rsb r0, r0, #41
2fafc: e6ff0070 uxth r0, r0
2fb00: e3500028 cmp r0, #40
2fb04: 83a00028 movhi r0, #40
2fb08: 8a000002 bhi 0x2fb18
2fb0c: e3500000 cmp r0, #0
; more botched rounding / convert to fixed-point
2fb10: 0d9f0a3b vldreq s0, [pc, #236] ; 0x2fc04 (-0.5)
2fb14: 0a000004 beq 0x2fb2c
2fb18: e1a00600 lsl r0, r0, #12
2fb1c: ee000a10 vmov s0, r0
2fb20: eddf0a38 vldr s1, [pc, #224] ; 0x2fc08 (0.5)
2fb24: eeb80a40 vcvt.f32.u32 s0, s0
2fb28: ee300a20 vadd.f32 s0, s0, s1
; magic division by 10
2fb2c: e59f10d8 ldr r1, [pc, #216] ; 0x2fc0c (0x66666667)
2fb30: eebd0ac0 vcvt.s32.f32 s0, s0
2fb34: ee100a10 vmov r0, s0
2fb38: e0c01091 smull r1, r0, r1, r0
2fb3c: e1a01140 asr r1, r0, #2
2fb40: e0410fc0 sub r0, r1, r0, asr #31
2fb44: e8bd8010 pop {r4, pc}
; Repeat Ball
2fb48: e5910004 ldr r0, [r1, #4] ; get dex count
2fb4c: e5900010 ldr r0, [r0, #16]
2fb50: e5900084 ldr r0, [r0, #132]
2fb54: e3500000 cmp r0, #0 ; be sure it's non-zero
2fb58: 0a000027 beq 0x2fbfc
2fb5c: e1d310bc ldrh r1, [r3, #12] ; caught?
2fb60: e3a02000 mov r2, #0
2fb64: ebff43b4 bl 0xa3c
2fb68: e3500000 cmp r0, #0
2fb6c: e320f000 nop {0}
2fb70: 0a000021 beq 0x2fbfc
2fb74: e3a00a03 mov r0, #12288 ; 0x3000
2fb78: e8bd8010 pop {r4, pc}
; Timer Ball
2fb7c: e5910014 ldr r0, [r1, #20]
2fb80: e59f1088 ldr r1, [pc, #136] ; 0x2fc10 = 0x4cd
2fb84: e0000190 mul r0, r0, r1
2fb88: e2800a01 add r0, r0, #4096 ; 0x1000
2fb8c: e3500901 cmp r0, #16384 ; 0x4000
2fb90: c3a00901 movgt r0, #16384 ; 0x4000
2fb94: e8bd8010 pop {r4, pc}
; Dusk Ball
2fb98: e5910004 ldr r0, [r1, #4]
2fb9c: e5900010 ldr r0, [r0, #16]
2fba0: e2804004 add r4, r0, #4
2fba4: e3a00001 mov r0, #1
2fba8: ebff43a5 bl 0xa44
2fbac: e5d41007 ldrb r1, [r4, #7]
; if r1 = 3, 17, 19, 20, 60, or 59
; (OR/AS: 3, 14, 15, 41)
2fbb0: e3510003 cmp r1, #3
2fbb4: 13510011 cmpne r1, #17
2fbb8: 0a000009 beq 0x2fbe4 -> 3.5
2fbbc: e3510013 cmp r1, #19
2fbc0: 13510014 cmpne r1, #20
2fbc4: 0a000006 beq 0x2fbe4 -> 3.5
2fbc8: e351003c cmp r1, #60
2fbcc: 1351003b cmpne r1, #59
2fbd0: 0a000003 beq 0x2fbe4 -> 3.5
; or if r0 = 2, 3, or 4
2fbd4: e3500002 cmp r0, #2
2fbd8: 13500003 cmpne r0, #3
2fbdc: 13500004 cmpne r0, #4
2fbe0: 1a000005 bne 0x2fbfc
2fbe4: e3a00b0e mov r0, #14336 ; 0x3800
2fbe8: e8bd8010 pop {r4, pc}
; Quick Ball
2fbec: e5910014 ldr r0, [r1, #20]
2fbf0: e3500000 cmp r0, #0
2fbf4: 03a00a05 moveq r0, #20480 ; 0x5000
2fbf8: 0affffa1 beq 0x2fa84
; Fallback
2fbfc: e3a00a01 mov r0, #4096 ; 0x1000
2fc00: e8bd8010 pop {r4, pc}
2fc04: bf000000
2fc08: 3f000000
2fc0c: 66666667
2fc10: 000004cd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment