• Welcome to Smashboards, the world's largest Super Smash Brothers community! Over 250,000 Smash Bros. fans from around the world have come to discuss these great games in over 19 million posts!

    You are currently viewing our boards as a visitor. Click here to sign up right now and start on your path in the Smash community!

In Progress Rainbow Puff Bow (color cycle)

rmn

Smash Rookie
Joined
Feb 15, 2016
Messages
15
Location
Alabama
Listed as in progress because I'd like to optimize the HSV->RGB conversion a bit if I can. It's a really long code as is, but it works.

Makes Puff's bow costume cycle through hue at a a given rate, with some constant saturation and value.


C206CB7C 0000003B
8138002C 88090007
2C00000F 408201C0
88090619 2C000002
408201B4 C029FFC0
4800018D 7C6802A6
C0430010 EC21102A
C042E3CC 48000149
D029FFC0 FD000890
C1230008 C143000C
C002E694 EC210024
FD600890 C0428048
48000125 C0029D80
FC210028 FC200A10
FC200828 ECE902B2
ED070072 FC200090
FC0B0840 41810014
FC203890 FC404090
C062A1C4 48000080
EC21002A FC0B0840
41810014 FC204090
FC403890 C062A1C4
48000064 EC21002A
FC0B0840 41810014
C022A1C4 FC403890
FC604090 48000048
EC21002A FC0B0840
41810014 C022A1C4
FC404090 FC603890
4800002C EC21002A
FC0B0840 41810014
FC204090 C042A1C4
FC603890 48000010
FC203890 C042A1C4
FC604090 EC0A3828
EC21002A EC42002A
EC63002A C0030014
EC210032 EC630032
C0030018 EC420032
FC20081E D821FFF8
8081FFFC FC40101E
D841FFF8 80A1FFFC
FC60181E D861FFF8
80C1FFFC 5484583E
50A42D74 7C843378
38690108 80630000
3CA00002 60A5DBF0
7C632A14 B0830000
48000054 EC211024
FD800890 C8028B00
FC21002A FC210028
FC016040 EC2C0828
4081000C C0029D80
FC20082A EC2100B2
4E800020 4E800021
C3300000 00000000
XXXXXXXX YYYYYYYY
ZZZZZZZZ 41F80000
427C0000 8001001C
60000000 00000000

Parameters (All as floating point):
XXXXXXXX: Saturation, in the range [0, 1]
YYYYYYYY: Value, in the range [0, 1]
ZZZZZZZZ: Hue rate, degrees per frame

I've been using 3F400000, 3F000000, 3DCCCCCD which seems to look all right. Experiment and find what looks good to you.

Thanks to @UnclePunch for the Press Down For A Random Bow Color code, which I referenced while making this.

I'm sure there's a more optimized way to implement the HSV->RGB conversion algorithm in ASM. I've taken a very basic approach here.
Code:
# Rainbow Puff Bow Experimental [rmn]
# Hue change speed in degrees per frame, value, and saturation
#  options are found in the data section at the end of the code.

# This code is long and unoptimized. Hasn't been tested
#  extensively so be cautious.
# Inject at 8006cb7c
# Original instruction: lwz r0, 0x1C(r1)
# By default saves hue to 0x20 of the player entity struct.
#  If you are using that space for something else, change
#  those two lines to point somewhere else. That location
#  defaults to 0, and the code expects a non-negative value
#  value when loading a float from that location so you may
#  have to initialize the memory you choose to use.

# r24 = player entity struct pointer
lwz  r9, 0x2c(r24)  # player data pointer
lbz  r0, 0x7(r9)
cmpwi  r0, 0xf  # check character ID
bne  done
lbz  r0, 0x619(r9)
cmpwi  r0, 2  # check costume ID
bne  done

# Calculate C and X terms.
# Reference used for HSV->RGB conversion:
#  https://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB
lfs   f1, -0x40(r9)  # load hue #####################
bl   constants
mflr   r3
lfs   f2, 0x10(r3)  # hue deg/frame
fadds   f1, f1, f2  # increment hue
lfs  f2, -0x1c34(r2) # 360
bl  float_mod  # keep hue in [0, 360]
stfs  f1, -0x40(r9)  # save hue #####################

fmr  f8, f1  # hue
lfs   f9, 8(r3)  # sat
lfs   f10, 0xC(r3)  # value

lfs  f0, -0x196C(r2) # 60
fdivs   f1, f1, f0  # Hue/60deg = H'
fmr  f11, f1

lfs  f2, -0x7fb8(r2) # 2
bl  float_mod  # H' mod 2
lfs  f0, -0x6280(r2) # 1
fsub  f1, f1, f0
fabs  f1, f1  # |H' mod 2  - 1|
fsub  f1, f0, f1  # 1 - |H' mod 2  - 1|

fmuls   f7, f9, f10  # Chroma
fmuls  f8, f7, f1  # X

find_region:  # get R1, G1, B1
fmr  f1, f0
fcmpo  cr0, f11, f1
bgt  gt1
fmr  f1, f7
fmr  f2, f8
lfs  f3, -0x5e3c(r2) # 0
b  region_found
gt1:
fadds  f1, f1, f0
fcmpo  cr0, f11, f1
bgt  gt2
fmr  f1, f8
fmr  f2, f7
lfs  f3, -0x5e3c(r2)
b  region_found
gt2:
fadds  f1, f1, f0
fcmpo  cr0, f11, f1
bgt  gt3
lfs  f1, -0x5e3c(r2)
fmr  f2, f7
fmr  f3, f8
b  region_found
gt3:
fadds  f1, f1, f0
fcmpo  cr0, f11, f1
bgt  gt4
lfs  f1, -0x5e3c(r2)
fmr  f2, f8
fmr  f3, f7
b  region_found
gt4:
fadds  f1, f1, f0
fcmpo  cr0, f11, f1
bgt  gt5
fmr  f1, f8
lfs  f2, -0x5e3c(r2)
fmr  f3, f7
b  region_found
gt5:
fmr  f1, f7
lfs  f2, -0x5e3c(r2)
fmr  f3, f8

region_found:
# Get R, G, B. Will fall in range [0, 1]
fsubs  f0, f10, f7  # m
fadds  f1, f1, f0  # R
fadds  f2, f2, f0  # G
fadds  f3, f3, f0  # B

# RGB565 format:
# R and B will range from 0 to 0x1F, G will range from 0 to 0x3F
lfs  f0, 0x14(r3)
fmuls  f1, f1, f0
fmuls  f3, f3, f0
lfs  f0, 0x18(r3)
fmuls  f2, f2, f0

# Convert R, G, B to integers
fctiwz  f1, f1
stfd  f1, -8(r1)
lwz  r4, -4(r1)  # R
fctiwz  f2, f2
stfd  f2, -8(r1)
lwz  r5, -4(r1)  # G
fctiwz  f3, f3
stfd  f3, -8(r1)
lwz  r6, -4(r1)  # B

# Build 16-bit color value
rlwinm  r4, r4, 11, 0, 31
rlwimi  r4, r5, 5, 21, 26
or  r4, r4, r6  # RGB565 value

# Overwrite the bow texture color in memory
addi  r3, r9, 0x108
lwz  r3, 0(r3)
lis  r5, 0x0002
ori  r5, r5, 0xdbf0
add  r3, r3, r5  # texture address
sth  r4, 0(r3)  # store new color
b  done

float_mod:
# f1 = f1 mod f2
# r3 = pointer to constants data block
# destroys f12 but that doesn't break anything here
# Expects positive values
fdivs  f1, f1, f2
fmr  f12, f1
lfd  f0, -0x7500(r2) # 43300000 00000000
fadd  f1, f1, f0  # round value in f1 to nearest integer
fsub  f1, f1, f0  # (only for positive values!)
fcmpo  cr0, f1, f12
fsubs  f1, f12, f1  # get remainder
ble  fm_rounded_down
fm_rounded_up:
lfs  f0, -0x6280(r2) # 1
fadd  f1, f0, f1  # correct sign
fm_rounded_down:
fmuls  f1, f1, f2  # get mod
blr

constants:
blrl
.long  0xc3300000 ; constant for fp rounding
.long  0x00000000
.long  0x3F400000 ; saturation = 0.75
.long  0x3F000000 ; value = 0.5
.long  0x3DCCCCCD ; hue degrees per frame = 0.1
.long  0x41F80000 ; 31, constant
.long  0x427C0000 ; 63, constant

done:
lwz   r0, 0x1C(r1) ;instruction replaced with injection
 
Last edited:
Top Bottom