Trying to find a good insertion point for an event that doesn't really have any numbers associated with it, and isn't really triggered by anything other than normal game function - the opening "course overview" cutscene that plays at the beginning of each race. The eventual idea is that I want to prevent the player from being able to skip this cutscene. I'm guessing I can either nop out the function that skips it, or maybe find a way of preventing input while the scene is active.
The trouble is I'm unsure how to find the insertion point for something like this. It's not an item, it doesn't really have to do with regular gameplay. I tried putting a breakpoint on my controller to see if I could maybe figure out how the instruction is being executed when you skip the cutscene, but nothing I tried seemed to provide anything that made sense. How would I go about finding the right insertion point?
Apologies if this has already been answered elsewhere, but I haven’t been able to find any documentation on this. What exactly does the “condition” box do inside Dolphin’s breakpoint menu?
This code will "stop time" with a press of a button, quite literally. In other words, when this code is enabled, "everything" will "freeze", EXCEPT YOU - Items, CPUs, objects, timer,, UI animations and other elements will completely freeze/stop, EXCEPT FOR YOUR KART! You will be able to control your kart and throw stationary items while everything is frozen, since CPUs will be frozen you can abuse them by placing items in front of them or hitting or bumping them then unfreezing time, all actions done while frozen will be done after unfreezing. It is hard to explain, it is better to watch the demonstration video of the code by clicking here (poor showcase video). Press the set activator, the code will enable, press it again, the code will disable.
Unfortunately, this code is incomplete, there are elements I wanted to implement that I couldn't find or had issues and I have no more time or interest to look into these. These elements are:
Freeze FIB Anim (One that freezes it at the current rotation rather than forcing a specific one)
Freeze Character Anim That is In Play (Freezing character animation while one is playing, for CPUs)
Freeze Object Animation (Some objects are still animated, even though they are frozen)
Freeze Course Texture Animation (Found but instead of freezing it was currently, breaks it as if there was no anim present)
Freeze Explosion (So explosions are frozen during stop)
Better Freeze Items (Unfortunately, it doesn't seem like this game has a main calc function that handles multiple item stuff, including the explosion as well, so it's done in a bad way)
Freeze Kart Animation (Karts are still animated during stop)
No Engine Sound (One that changes live. Actually forgot to look into this)
This code is a recreation of Fosfour5933's Mario Kart 7 Stop Item Hack. I also made my own version of this code in Mario Kart 8 Deluxe just like how I did here for Wii, which is awesome and I could find all elements I wanted (pretty much like Fosfour's code), unlike here in Mario Kart Wii (but I didn't have enough interest and time to look into it all, so instead of fully abandoning it, I'm releasing as how it is). This may or may not be my last MKW code. Thank you for everything.
Credits to JoshuaMK for Kill Lakitu address, 1superchip for Remote Object Freeze address and Vega for POW Check address.
li r3, 0x1 # First valid flag entry
li r4, 0x89 # One above the last valid flag entry
lis r12, utilRandom@ha
ori r12, r12, utilRandom@l
mtlr r12
blrl # Call utilRandom to randomize the country byte
slwi r0, r3, 0x18 # Shift the byte 24 bits to the left
oris r0, r0, 0x0001 # Set the city to 1 in order for it to appear
stw r0, 0x7C (sp) # Store for later use
addi r3, sp, 0x80
lis r4, flagString@ha
ori r4, r4, flagString@l # Load flag string for printf call
addi r5, r4, 0x63
li r4, 0x7
rlwinm r6, r0, 8, 24, 31
crclr 6
lis r12, snprintf@ha
ori r12, r12, snprintf@l
mtlr r12
blrl # Call snprintf
lis r12, menuData@ha
lwz r12, menuData@l (r12)
cmpwi r12, 0
beq end
lwz r12, 0 (r12)
cmpwi r12, 0
beq end
lwz r12, 0x25C (r12)
cmpwi r12, 0
beq end # Three checks are needed as all three will cause null pointers due to the C0 codetype executing before they're setup
addi r3, r12, 0x1C8
addi r4, sp, 0x80
lis r12, iconPaneExists@ha
ori r12, r12, iconPaneExists@l
mtlr r12
blrl # Call the pane function
cmpwi r3, 0
beq end # Exit if no flag can be found, we only want to write valid countries
lwz r11, 0x7C (sp) # Load the country value we stored earlier
lis r12, flagLoc@ha
stw r11, flagLoc@l(r12) # Overwrite any previously set country
end:
lmw r3, 0x8 (sp) # Pop the stack
addi sp, sp, 0x88
mtlr r12
#blr # (Uncomment if not compiling with PyiiASMH)
lwz r12, 0x0020(r12) # Load Word from 1st Level Pointer
slwi r3, r3, 2 # Shift the bits of r3 by 2 to the left. This is the same as multiplying by 0x4.
lwzx r12, r12, r3 # Load into 2nd Level Pointer
lwz r12, 0x0010(r12) # Load into 3rd Level Pointer
lwz r12, 0x0010(r12) # Load into 4th Level Pointer
lfs f1, 0x0024(r12) # Load the speed value
fabs f1, f1 # Handle negatives
fctiw f1, f1 # Convert to int
stfd f1, 0x10(r1)
lwz r12, 0x14(r1) # Load the speed value as an int
lis r5, 0x7370
ori r5, r5, 0x6565 # Load part of the digit string
lwz r6, -0x28(r30)
cmplw r5, r6 # Check if the loaded texture is related to the digits
bne end
li r5, 0x30
lbz r6, -0x21(r30)
digitLoop:
addi r5, r5, 1
cmplwi r5, 0x33
bgt end # Exit the code as we're not dealing with the digits
cmplw r5, r6
bne digitLoop # Loop if the texture name doesn't match
li r8, 100
divw r9, r12, r8
cmplwi r5, 0x33
beq showHundred
mulli r9, r9, 100
sub r10, r12, r9
li r8, 10
divw r9, r10, r8
cmplwi r5, 0x32
beq showTens
mulli r9, r9, 10
sub r9, r10, r9
b skipHide # Don't hide the ones digit, it's always shown
showHundred:
cmplwi r12, 0x63 # Hide the hundreds digit if your speed is below 100
bgt skipHide
b hideDigit
showTens:
cmplwi r12, 0x9 # Hide the tens digit if your speed is below 10
bgt skipHide
hideDigit:
li r9, 0xa
skipHide:
mulli r9, r9, 0x860
add r4, r4, r9
end:
popStack
ASM 2: Update block color based on speed and status effects
Code:
#Inject at 0x80084628 PAL
#Inject at 0x80084588 NTSC-U
#Inject at 0x80084548 NTSC-J
#Inject at 0x80084688 NTSC-K
.set colorEVA, 0x80001610
.set region, '' # Specify which region to compile for
.if (region == 'P' || region == 'p') # RMCP
.set RaceData, 0x809BD728
.set PlayerHolder, 0x809C18F8
.elseif (region == 'E' || region == 'e' || region == 'U' || region == 'u') # RMCE
.set RaceData, 0x809B8F68
.set PlayerHolder, 0x809BD110
.elseif (region == 'J' || region == 'j') # RMCJ
.set RaceData, 0x809BC788
.set PlayerHolder, 0x809C0958
.elseif (region == 'K' || region == 'k') # RMCK
.set RaceData, 0x809ABD68
.set PlayerHolder, 0x809AFF38
.else # Invalid Region
.abort
.endif
lwz r12, 0x0020 (r12) # Load Word from 1st Level Pointer
slwi r14, r14, 2 # Shift the bits of r14 by 2 to the left. This is the same as multiplying by 0x4.
lwzx r12, r12, r14 # Load into 2nd Level Pointer
lwz r12, 0x0010(r12) # Load into 3rd Level Pointer
lwz r18, 0x0010(r12) # Load into PlayerSub10
lwz r19, 0x001c(r12) # Load into PlayerSub1c
lfs f1, 0x0024 (r18) # Load the speed value
fabs f1, f1 # Handle negatives
fctiw f1, f1 # Convert to int
stfd f1, 0x10(r1)
lwz r20, 0x14(r1) # Load the speed value as an int
lis r14, 0x645f
ori r14, r14, 0x626c # Load part of the block string
lwz r15, 0xC0(r28)
cmplw r14, r15 # Check if the loaded texture is related to the blocks
bne end
li r14, 0x30
lbz r15, 0xc9(r28)
blockLoop:
addi r14, r14, 1
cmplwi r14, 0x37
bgt end # Exit the code as we're not dealing with the blocks
cmplw r14, r15
bne blockLoop # Loop if the texture name doesn't match
bl storeColors # Do the bl trick to store the colors and load them later on
lwz r14, 0xc(r19)
andis. r14, r14, 0x0800
addi r16, r16, 0x40
bne beginCycling # Point towards Bullet Bill color set and begin cycling colors
lwz r14, 0x8(r19)
andis. r14, r14, 0x8000
subi r16, r16, 0x20
bne beginCycling # Point towards Star color set and begin cycling colors
lwz r14, 0x8(r19)
andi. r14, r14, 0x10
subi r16, r16, 0x20
bne beginCycling # Start cycling regular colors if we're in a cannon...
lhz r14, 0x148(r18)
cmplwi r14, 0
bgt beginCycling # ...or if we have offroad invincibility
li r14, 11 # Load normal behavior otherwise
divw r14, r20, r14
subi r15, r15, 0x30
cmplw r14, r15 # Double Dash lights up one block around every 11 units. Here we compare the current block relative to the speed and grey it out if we aren't going fast enough.
blt greyBlock
mulli r15, r15, 0x4
lwzx r17, r16, r15 # Load color based on current speed
b storeColor
greyBlock:
lwz r17, 0(r16)
b storeColor
beginCycling:
lis r14, colorEVA@ha
ori r14, r14, colorEVA@l
subi r15, r15, 0x30
lbzx r17, r14, r15
cmplwi r17, 0
bne validColor
mr r17, r15 # Required as the cycles will start at the wrong color due to blank EVA
validColor:
addi r21, r14, 0x8
lbzx r22, r21, r15
xori r22, r22, 1
stbx r22, r21, r15 # Store the bit for later use
lbz r23, 0(r14)
cmplwi r23, 1 # Required for "four frame" behavior
bge colorFreeze
cmplwi r22, 0x1 # Double Dash only updates the color every second frame, so we compare against the bit we flipped
bne colorFreeze
subi r17, r17, 1
cmplwi r17, 0
bgt colorFreeze # Reset to the end of the colors if we hit 0
li r17, 7
colorFreeze:
cmplwi r17, 0x7 # Check if we're loading the final color in the set...
bne fourFrameSkip
cmplw r17, r15 # ...and if we're referencing the final block, if not skip the "four frame" behavior
bne fourFrameSkip
lbz r22, 0x0(r14)
addi r22, r22, 1
cmplwi r22, 4 # Double Dash will also delay color updates for four frames if said two conditions above are met, so we make a counter and reset it once the four frames have finished
blt fourFrameStore
li r22, 0
fourFrameStore:
stb r22, 0(r14)
fourFrameSkip:
stbx r17, r14, r15 # Store value for later use
mulli r17, r17, 0x4
lwzx r17, r16, r17 # Load up the color based on the current value
mr r14, r3
bl get_data0 # Use the bl trick throughout to grab the string data we need
mr r4, r3
bl get_data1
mr r5, r3
bl get_data2
mr r6, r3
bl get_data3
mr r7, r3
mr r3, r14
lis r12, ControlLoader__Load@h
ori r12, r12, ControlLoader__Load@l # Call a function to load the speedometer control instead of the ghost message control
mtlr r12
blrl
b end
Posted here should other people want to look at it. Extracted from v93 of the payload.
Originally wanting to convert the entire code into C2 format, I gave up due to the length and difficulty with reading the code. Some parts are in C2 whilst most parts are written in 06 format.
This only contains the actual frameskip related code. There were other parts related to debugging, but I removed them as I think it's pointless to include here and further increased the code length (It's also not even usable; Despite being downloaded and hooked by the Wiimmfi payload, a value is read that prevents the code from being executed. Another thing is that it's also similar, if not the same as the version used in CTGP to monitor performance. I would add comparison images, but I've lost this part of the code along with images of me using it.)
Technically supersedes this version as most internal systems will now run at full speed under 30 FPS with this code, but I'll post it here as I don't like the way I've converted and I don't want to port it as a result.
This code uses addresses 0x80001614 through 0x8000166B. Ensure no other codes read or write to these addresses