• Login
  • Register
  • Dolphin Forums
  • Home
  • FAQ
  • Download
  • Wiki
  • Code


Dolphin, the GameCube and Wii emulator - Forums › Dolphin Site › dolphin-emu.org articles v
1 2 3 Next »

Game Modification: 60 FPS Hacks and Patches
View New Posts | View Today's Posts

Pages (84): « Previous 1 ... 28 29 30 31 32 ... 84 Next »
Jump to page 
Thread Rating:
  • 3 Vote(s) - 5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Thread Modes
Game Modification: 60 FPS Hacks and Patches
10-19-2016, 03:06 PM (This post was last modified: 10-19-2016, 03:49 PM by Meowmaritus. Edit Reason: forrrrrmatting )
#291
Meowmaritus Offline
Zelda Enthusiast
***
Posts: 111
Threads: 0
Joined: Oct 2016
Here's a kind of clunky but useful Gecko ASM code I just made and haven't tested (lol)

It uses r16, r17, r18, r19, and CTR (doesn't interfere with Zelda games at least)

C2JJJJJJ 00000008
7E0902A6 3E20LLLL
6231MMMM 82310000
3A40YYYY 7E719396
7E7391D6 7E738850
2C130000 40820014
3E20WWWW 6231ZZZZ
7E2903A6 4E800421
7E0903A6 00000000


JJJJJJ = The offset (relative to 0x80000000) to insert this code.
LLLL = Upper 16 bits of address to modulo the value of
MMMM = Lower 16 bits of address to modulo the value of
WWWW = Upper 16 bits (first half) of target function to execute if modulo result is 0
ZZZZ = Lower 16 bits (second half) of target function to execute if modulo result is 0
YYYY = The value to modulo the value at 0xLLLLMMMM by

So, to sum it all up:

1. Load the value at 0xLLLLMMMM
2. Mod that value by 0xYYYY (get the remainder after dividing it by 0xYYYY)
3. If there is no remainder (0xYYYY is a factor of the value at 0xLLLLMMMM), then put 0xWWWWZZZZ into the CTR and branch to the CTR (runs the function located at 0xWWWWZZZZ)


Anyways yeah I'm gonna use this code to run a few things every other frame (like updating the pause menu cursor)

Also don't ask how I decided on the letters for the code.

Oh and here's the ASM source of the code:
Spoiler: (Show Spoiler)

mfctr r16

lis r17, 0xLLLL
ori r17, r17, 0xMMMM
lwz r17, 0 (r17)

li r18, 0xYYYY

divwu r19, r17, r18 #r19 = quotient
mullw r19, r19, r18 #r19 = quotient * divisor
subf r19, r19, r17 #r19 = remainder

cmpwi r19, 0

bne- 0x14
lis r17, 0xWWWW
ori r17, r17, 0xZZZZ
mtctr r17
bctrl

mtctr r16


Edit 2: Forgot to make a change in the gecko code.
Find
Reply
10-19-2016, 03:18 PM (This post was last modified: 10-19-2016, 03:22 PM by Zerowalker.)
#292
Zerowalker Offline
Member
***
Posts: 208
Threads: 19
Joined: Jan 2016
Wow, now that was complex, and you just had to use Modulo, my archenemy from programming school, never understood that think!
But so which part actually does the "skip" in ASM?


Looking at the code:

mfctr r16
lis r17,1
ori r17,r17,0
lwz r17,0(r17)
li r18,0
divwu r19,r17,r18
mullw r19,r19,r18
sub r19,r17,r19
cmpwi r19,0
bne- 0x14
li r17,0
oris r17,r17,1
mtctr r17
bctrl
mtctr r16

I can only guess it's bne- 0x14.

though no idea why it's 0x14 (as no value changes it from the ones you use right?).

And do you really need that much code?
Shouldn't there be something like "plus 1 on value every run, if value is dividable by 2, runt, else skip" etc?

(Math is Not my thing, so don't expect much out of me in this regard).

EDIT:

Oh wait, maybe bne- 0x14 just jump relative to it's own position?

EDIT 2:

Okay that seems to be the case, will see if i can make something out of this;d
Find
Reply
10-19-2016, 03:42 PM
#293
Meowmaritus Offline
Zelda Enthusiast
***
Posts: 111
Threads: 0
Joined: Oct 2016
(10-19-2016, 01:55 PM)Zerowalker Wrote: Oh okay i see, but isn't that really a weird roundabout way to get to addresses?
Why not just access them directly, why does it need to have an offset like that? (or at least why does it have the possibility?).

Also, is it possible to use "If blabla then blr"?

Yeah there's a ton of different methods of doing conditional branching, but here are some practical, simple ones that these games tend to use:
1. Compare 2 values:
cmpw r1, r2 #compares r1 to r2, (A = r1, B = r2)
compwi r1, 7 #compares r1 to 7 (A = r1, B = 7)

2. Conditional BLR:

Useful ones:
beqlr #blr if A = B
bnelr #blr if A != B
bltlr #blr if A < B
bgtlr #blr if A > B
blelr #blr if A <= B
bgelr #blr if A >= B

Pointless ones:
bnllr #blr if A isn't less than B (greater than or equal to)
bnglr #blr if A isn't greater than B (less than or equal to)


Also, here's how you actually decide on one of these without looking at a long list:

  1. First letter: "b"
  2. If it's a conditional branch, add a condition abbreviation from this list:
    • "lt" - less than
    • "le" - less than or equal
    • "eq" - equal
    • "ge" - greater than or equal
    • "gt" - greater than
    • "nl" - not less than
    • "ne" = not equal
    • "ng" = not greater than
    • "so" = summary overflow (I don't know what this does)
    • "ns" = not summary overflow (I don't know what this does)
    • "un" = unordered (I don't know what this does)
    • "nu" = not unordered (I don't know what this does)
  3. To branch to a special register add its abbreviation:
    • "CTR" - Loop counter register (often holds addresses)
    • "LR" - Link Register
  4. If you want to set the LR to come back to later (with a blr), then add the lowercase letter L: "l"
  5. If you didn't specify a special register in step 3:
    • If you want to branch to an offset relative to the current one, then just specify it
    • If you want to branch to an absolute offset not relative in any way: add "a" at the end and then specify the absolute address.
Find
Reply
10-19-2016, 04:04 PM (This post was last modified: 10-19-2016, 07:23 PM by Zerowalker.)
#294
Zerowalker Offline
Member
***
Posts: 208
Threads: 19
Joined: Jan 2016
Ah now that's interesting, i knew about the conditional branches, but i didn't know about how the abbreviation worked and that you could use the special register ones.

Hmm, i am thinking how one could just do the thing i said before, just having a counter and divide it, and if it's dividable by 2 then it's true.
Though i can't figure out how one even makes a counter, as the values are stored at the register, and you have to set the values before you start adding to them.
And if you always have to set the start value, it won't work as a counter as it will just reset each time.

And also won't the Game randomly use some registers, making the one you want to use be worthless at some point?

EDIT:

Okay after staring blind at it i finally understand that that's what you are doing, looking if it's even or odd.

I tried messing around but i can't seem to get it to work without crashing the game.

mfctr r16
lis r17, 0x8160
ori r17,r17,19452
lwz r17,0x4bfc(r17)
li r18,2
divwu r19,r17,r18
mullw r19,r19,r18
sub r19,r17,r19
cmpwi r19,0
bne- 0x14
li r17,0
oris r17,r17,0
mtctr r17
blr
mtctr r16

not really sure what values i am supposed to use for the divider (YYYY), i just set it to 2 as i guess that works?

EDIT 2:

Okay i got it working Kinda, but it still crashes, but it happens after the code has been run and another "blr" is being ran.
It jumps to somewhere with no RAM or something, and then it goes awry.

EDIT 3:

Totally blind again, didn't see you wrote the ASM code in a spoiler....
Find
Reply
10-19-2016, 07:09 PM
#295
Meowmaritus Offline
Zelda Enthusiast
***
Posts: 111
Threads: 0
Joined: Oct 2016
(10-19-2016, 04:04 PM)Zerowalker Wrote: Ah now that's interesting, i knew about the conditional branches, but i didn't know about how the abbreviation worked and that you could use the special register ones.

Hmm, i am thinking how one could just do the thing i said before, just having a counter and divide it, and if it's dividable by 2 then it's true.
Though i can't figure out how one even makes a counter, as the values are stored at the register, and you have to set the values before you start adding to them.
And if you always have to set the start value, it won't work as a counter as it will just reset each time.

And also won't the Game randomly use some registers, making the one you want to use be worthless at some point?

EDIT:

Okay after staring blind at it i finally understand that that's what you are doing, looking if it's even or odd.

I tried messing around but i can't seem to get it to work without crashing the game.

mfctr r16
lis r17, 0x8160
ori r17,r17,19452
lwz r17,0x4bfc(r17)
li r18,2
divwu r19,r17,r18
mullw r19,r19,r18
sub r19,r17,r19
cmpwi r19,0
bne- 0x14
li r17,0
oris r17,r17,0
mtctr r17
blr
mtctr r16

not really sure what values i am supposed to use for the divider (YYYY), i just set it to 2 as i guess that works?

EDIT 2:

Okay i got it working Kinda, but it still crashes, but it happens after the code has been run and another "blr" is being ran.
It jumps to somewhere with no RAM or something, and then it goes awry.

I'm about to go, so I can't give you a really helpful long explanation, but you can use mflr rA to move LR to register A and mtlr rA to move register A to LR
(and remember that LR is the thing it goes to when you do BLR)
So you'll have to store and reload it or something. If you step through it you can see the LR value in the register window on Dolphin debugger.
Find
Reply
10-19-2016, 07:46 PM (This post was last modified: 10-19-2016, 07:57 PM by Zerowalker.)
#296
Zerowalker Offline
Member
***
Posts: 208
Threads: 19
Joined: Jan 2016
(10-19-2016, 07:09 PM)Meowmaritus Wrote: I'm about to go, so I can't give you a really helpful long explanation, but you can use mflr rA to move LR to register A and mtlr rA to move register A to LR
(and remember that LR is the thing it goes to when you do BLR)
So you'll have to store and reload it or something. If you step through it you can see the LR value in the register window on Dolphin debugger.

Hmm, so LR is like a Register but can act as a return address as well.
Seems very hard to keep track on a counter if one has to set and reset all over the place in order for it to stay.

I tried setting a value in a unused memory, but it seems some kind of allocator will remove it quickly enough.

Luckily in my case, Pikmin seems to have a framecounter which is perfect for this, so i probably don't have to worry about the counting partSmile
Now i just need to figure out why the hell i get crashes with your code, cause the code seems to do what it's supposed to do, but it will fail.
Which is weird cause if i use blr (on that function, to completely skip everything there) it works fine, it just skips that effect.
But running it every other frame doesn't seem to work for some reason, i am guessing it's some blr register thingy, i don't really get how that all works.

Really much appreciate your help, this is fascinating;D

EDIT:

Okay solved it, i forgot to add the function in the place where i put the code.
Now i seems to have been able to play some effects at half speed, it's one of the things that scales with framerate in this gameSmile
Find
Reply
10-20-2016, 06:28 AM (This post was last modified: 10-20-2016, 06:32 AM by Brandondorf9999.)
#297
Brandondorf9999 Offline
Member
***
Posts: 111
Threads: 5
Joined: Sep 2013
Could someone try to make the wii NTSC and PAL versions of Planet 51 run at 60fps? It's the game based on the movie. It was developed by Pyro Studios and was released in 2009 by Sega.
Find
Reply
10-20-2016, 08:17 AM (This post was last modified: 10-20-2016, 08:22 AM by Meowmaritus.)
#298
Meowmaritus Offline
Zelda Enthusiast
***
Posts: 111
Threads: 0
Joined: Oct 2016
(10-19-2016, 04:04 PM)Zerowalker Wrote: -snip-

li r17,0
oris r17,r17,0
mtctr r17

-snip-

Just to clarify, you don't need to mess with CTR like i did if you arent going to branch to CTR afterward.
If you're just gonna do BLR then you can get rid of some of the code (also I noticed what I believe is a mistake in loading r17 and fixed that here):


#Set r17 to 0x81604BFC
lis r17, 0x8160
ori r17,r17,0x4BFC

#Load the Value at (0x81604BFC + 0) into r17
lwz r17,0 (r17) #You want to put 0 here because its relative to r17; Putting 0x4BFC here also will read from the location 0x4BFC bytes after 0x81604BFC)

#Divide r17 by 2 and put the remainder (which is 0 for even numbers and 1 for odd numbers) into r19
li r18,2
divwu r19,r17,r18
mullw r19,r19,r18
sub r19,r17,r19

#Compare the remainder with 0
cmpwi r19,0

#If the result is not equal to 0, then branch to the address 0x8 bytes after this one (Note that each address in PPC is 0x4 bytes long
#so this goes 2 instructions down, to the nop instruction below)
bne- 0x8
blr
nop #Literally does nothing aside from giving us somewhere to branch to if r19 is not equal to zero



Edit: I never did explain why I used beq- instead of just beq. The + or - has something to do with the default direction it branches or something, according to some resources I've looked at (I actually don't know what it does in practice). I just use beq- because Wind Waker does that and it seems to work fine.
Find
Reply
10-20-2016, 09:15 AM (This post was last modified: 10-20-2016, 09:50 AM by Zerowalker.)
#299
Zerowalker Offline
Member
***
Posts: 208
Threads: 19
Joined: Jan 2016
Ah, well i actually got that part working,
and it does just as you are saying (1 and 0), which is awesome.

Though sadly the framecounter isn't Perfectin the sense that it counts at a certain place, and i think that part of the code Maybe needs to be kinda skipped or something at times to prevent too fast playback of cutscenes (Though probably there is a better way, if i just can find out where it calls for the next frame data, cause it needs to happen at some function).

I think i will try to write a simple C# program that will handle the memory address and offset branching things for me, a converter so i can make them easier.
Cause it's kinda a bother to manually write two parts of the memory address, and also if i want to branch a certain offset (jump) i need to calculate how much for how many lines.

Though i am really starting to get a grasp of this, the instructions, i am amazed that i even understand them at all.
I also have copied some notes of what you said on some of them, very usefulSmile

EDIT:

This will save me some seconds haha xD
[Image: 2016-10-20_01-49-29kzp3v.png]
Find
Reply
10-20-2016, 10:06 AM
#300
retroben Offline
N64 Code Hunter
****
Posts: 328
Threads: 21
Joined: Jul 2015
I just had a thought since Twilight Princess has a frame skipper (dword 80502648 00000001),it may probably have an address that draws every frame when less than 60fps such as running half speed when at the normal 30fps and showing all frames.
Though this idea is from my Banjo-Kazooie/Tooie codes that cause the fps and speed to be identical to how fast the VI/s would be,like 30fps causing 30VI/s speed but actually still running at 60VI/s of refresh rate,preventing any frames from being skipped.
The Banjo codes modify 03 E0 00 08 into 03 E0 00 04 so that won't do much from how different the ASM is.

[color=#ccccff].spf06 15 tenalP[/color]
Shield TV Pro (stock/non-rooted OTA 6.3)

Acer Aspire E 15 E5-575G-59EE

CPU: i5-6200U 2.3-2.8Ghz _ GPU: Nvidia GeForce 940MX 2GB (GDDR5) VRAM
Hyundai 8GB DDR4 Dual-channel SDRAM _ 1000GB HDD
New; CPU: Intel i9 9900KF_ GPU: Nvidia RTX 2060 Super | ◕‿◕
Find
Reply
« Next Oldest | Next Newest »
Pages (84): « Previous 1 ... 28 29 30 31 32 ... 84 Next »
Jump to page 


  • View a Printable Version
  • Subscribe to this thread
Forum Jump:


Users browsing this thread:



Powered By MyBB | Theme by Fragma

Linear Mode
Threaded Mode