I'm trying to REDUCE the exp multiplier and had a bit of success by using:
040C1550 1F45xxxx - although it was semi-successful, I have the feeling that I'm going about this all the wrong way (shifting bits?)
1F = multiply instruction?
44 = offset in memory to multiply with?
xxxx = unsigned 16-bit integer?
0x1F44XXXX = mulli r26,r4,0xXXXX. The 1F doesn't neatly map to "mulli"; the first 6 bits, 0x1C, are the op code for mulli. The next five bits are the first register operand, the next five bits are the second register operand, and the last 16 bits are the immediate.
You could get by using right-shifts to divide by powers of 2, but that will only get you .5, .25, .125, etc. Not very practical. You could use fixed point multiplies but that's pretty difficult for other people to customize.
I too am extremely interested in this, and I know quite a few other people who would be too. Unfortunately my USB Gecko broke.
Exactly how successful was your attempt? What value did you use?
I'm pretty sure it's just standard integer multiplication. We need some float multiplication.
Original codes:
$EXP multiplier [Thomas83Lin]
040C1550 1F44xxxx
**Ported from Unknown*
$AP multiplier [Thomas83Lin]
040C1554 1F65xxxx
**Ported from Unknown*
$SP multiplier [Thomas83Lin]
040C1558 1F86xxxx
**Ported from Unknown*
This code will do all three. I don't have this game and can't test it, but I'm reasonably sure it will work.
This code uses the red zone. The red zone is addressed by using "negative stack frames", i.e. -8(r1) and -4(r1). It allows you to avoid creating a stack frame if you don't need to, but you must be careful because the USB Gecko debugger will over-write this area if you step through it. Hence why it's a "red" zone.
Some important things to note about the PowerPC architecture. 1) Double-precision instructions can take single-precision operands, but the result is double-precision. That is why I can fmuls and then fctiwz and then stfd. 2) Single-precision instructions can take double-precision operands, but produce single-precision results. That is why I can lfd and then fsubs.
Spoiler for source:
hook 800C1558: 7CDC3378 mr r28,r6
# multipliers
bl _SKIP_DATA
.float 1.0 # EXP
.float 1.0 # AP
.float 1.0 # SP
_SKIP_DATA:
# load fregs
lfd f12,-32360(r2) # load magic float into f12, -32360(r2) varies for each game and region
stfd f12,-8(r1) # store magic float onto stack to create the 0x43300000
xoris r26,r4,0x8000 # load flipped-int
stw r26,-4(r1) # store flipped-int to stack
lfd f11,-8(r1) # load flipped-int into f11
fsubs f11,f11,f12 # normalize f11
xoris r27,r5,0x8000
stw r27,-4(r1)
lfd f10,-8(r1)
fsubs f10,f10,f12
xoris r28,r6,0x8000
stw r28,-4(r1)
lfd f9,-8(r1)
fsubs f9,f9,f12
# f11/f10/f9 have EXP/AP/SP
mflr r12
lfs f12,0(r12) # load EXP mul
fmuls f11,f11,f12 # scale EXP
lfs f12,4(r12) # load AP mul
fmuls f10,f10,f12 # scale AP
lfs f12,8(r12) # load SP mul
fmuls f9,f9,f12 # scale SP
# store scaled versions
fctiwz f11,f11 # convert from double to int
stfd f11,-8(r1) # store conversion
lwz r26,-4(r1) # load conversion
fctiwz f10,f10
stfd f10,-8(r1)
lwz r27,-4(r1)
fctiwz f9,f9
stfd f9,-8(r1)
lwz r28,-4(r1)
EXP/AP/SP float multiplier [dcx2]
C20C1558 00000012
48000011 3F800000
3F800000 3F800000
C9828198 D981FFF8
6C9A8000 9341FFFC
C961FFF8 ED6B6028
6CBB8000 9361FFFC
C941FFF8 ED4A6028
6CDC8000 9381FFFC
C921FFF8 ED296028
7D8802A6 C18C0000
ED6B0332 C18C0004
ED4A0332 C18C0008
ED290332 FD60581E
D961FFF8 8341FFFC
FD40501E D941FFF8
8361FFFC FD20481E
D921FFF8 8381FFFC
60000000 00000000
modified base on Thomas83lin/Unknown's work. The three 3F800000's at the beginning are the EXP, AP, and SP multipliers in single-precision floating-point format. 3F800000 = 1.0, 3F000000 = 0.5, 3F400000 = 0.75, 3FC00000 = 1.5 etc
EXP only multiplier [dcx2]
C20C1550 00000008
48000009 3F800000
C9828198 D981FFF8
6C9A8000 9341FFFC
C961FFF8 ED6B6028
7D8802A6 C18C0000
ED6B0332 FD60581E
D961FFF8 8341FFFC
60000000 00000000
Again with the 3F800000 = 1.0, 3F000000 = 0.5, 3F400000 = 0.75, 3FC00000 = 1.5 etc