BitPatty / gct-generator

A gecko code practice file generator for everyone's favorite game: Super Mario Sunshine
https://gct.zint.ch
Apache License 2.0
7 stars 3 forks source link

New Cheat Loader #128

Open BitPatty opened 2 years ago

BitPatty commented 2 years ago

Potential continuation of https://github.com/BitPatty/gctGenerator/issues/126#issuecomment-1309372255

sup39 commented 2 years ago

For togglable codes, I think we can store the status of the code (e.g. activated/deactivated) in RAM, and use if/conditional branch to handle whether the original instruction or the replacing instructions should be executed.

Here is an example of the Fast Forward code.

  1. I update the status of the code (0/2/3) according to the button input in _gameLoop function, which is executed after controller input being read in TApplication::gameLoop()
  2. I create a _getQFSync function to execute the original instruction (li r3, 600) or other instructions to achieve fast forward according to the status of the code loaded from RAM
  3. I replace the original instructions with bl in _start, including the gameLoop and _getQFSync function. This is function is executed right after the save file is loaded to RAM
BitPatty commented 2 years ago

Yeah that makes sense. You think this could still be kept compatible with Gecko codes in the sense that it parses and applies Gecko codes?

pyorot commented 2 years ago

Togglable codes can be built in pure Gecko as well, with no manual additional state provision needed.

BitPatty commented 2 years ago

@pyorot Yes and we use those already, the discussion is about the portability of the codes to a custom loader that currently does not use Gecko

pyorot commented 2 years ago

My bad, I wasn’t aware they were in use since fast text has two buttons allotted to it and togglable OSD hasn’t been implemented for example. I’m curious where CC codetype is being used

sup39 commented 2 years ago

It should be possible to embed a Gecko code handler so that we can migrate from gct to gci without rewriting the existing codes. But I think eventually we may want to rewrite some of the codes to make them possible to activate and deactivate in a menu prompt.

sup39 commented 2 years ago

I figured out that it seems possible to make the Gecko code handler execute arbitrary Gecko code with a C0 code. In C0 code, r15 stores the pointer to the gecko code that is being handled, so we can set r15 to point to the gct file loaded from save file to make the handler execute it. There seems to be some problems to solve though since memory card access is performed on a thread other than the main thread.

QbeRoot commented 1 year ago

That seems like an implementation detail, I wouldn't rely on it working across different loaders. Opcodes 68 (Gosub) and 64 (Return) seem like they could help, but Gosub takes a signed 16-bit number of lines as offset, so it can only change the code execution address by up to 0x40000. That may be enough for Dolphin but iirc Nintendont runs Gecko codes in Wii MEM2, with addresses 0x90000000 and above. Sadly there doesn't seem to be a way to set the "next code address" directly.

Alternately, the F6 code can locate our codes if we start them with some recognizable lines, but it's Gecko 1.8 so we need to confirm that it works on Nintendont and Dolphin. If so, using F6000300 followed by the memory card codes address might even skip the search?

sup39 commented 1 year ago

The r15 trick seems to work on Nintendont and Dolphin, but yeah it might not be guaranteed to work on other platforms.

As for the F6 code, it seems that it only sets po but not the "next code address", so we might still need a way to set the "next code address" to po?

BitPatty commented 1 year ago

Nintendont runs Gecko codes in Wii MEM2

I thought so too, but apparently not anymore?

https://github.com/FIX94/Nintendont/blob/27606319cd9ab16231accd0968870ee67c0514d6/kernel/Patch.c#L4457-L4458 https://github.com/FIX94/Nintendont/blob/27606319cd9ab16231accd0968870ee67c0514d6/kernel/Patch.c#L3765-L3770

Gosub takes a signed 16-bit number of lines as offset, so it can only change the code execution address by up to 0x40000

That's lines not bits, shouldn't it be +0x1FFFC0?

Anyway, this could be a solution

  1. Store the code location in b1: 04001844 817F0000
  2. Gosub to store the next line in b0: 68000001 00000000 and skip the next instruction (which is (6))
  3. Ret to b1: 64200000 00000001
  4. Do the code
  5. Ret to b0: 64200000 00000000
  6. b0 should hold yet another jump to skip the next instruction (3): 68000001 00000001

So something like this

04001844 817F0000
68000001 00000000
68000001 00000001
64200000 00000001
....
64200000 00000000 ; after code

image

sup39 commented 1 year ago

Unfortunately, it seems that the location of b1 is different on Dolphin (seems to be 80001850). Since r15 trick with C0 seems to work on both Nintendont and Dolphin, I implemented GoSub (from GCT to GCI) and Return (from GCI to GCT) with C0.