Disney Dreamlight Valley [0100D39012C1A000]

  • Thread starter Thread starter morarin
  • Start date Start date
  • Views Views 33,974
  • Replies Replies 202
  • Likes Likes 34
Here it is for 1.23.0
[00# Mastercode Get Craft 0xB4BFF00 (Select First Item)]
040A0000 08CB4F04 F0014053
040A0000 08CB4F08 F9078262
040A0000 08CB4F0C AA0203F3
040A0000 08CB4F10 1706704E
040A0000 04E51044 14F98FB0

And this is an example code you could try.
[(ZL) Change Selected Crafting Recipe To DreamSnaps Decor Reward]
580F0000 0B4BFF00
580F1000 00000040
780F0000 00000018
640F1000 00000000 01DF2085
Thank you, patjenova. Your code helped me understand Khuong’s old crafting recipe code more correctly.

I need to correct my earlier understanding. I was mainly looking at the pointer-code part of Khuong’s old code, and I missed that the Master Code also had the part that saves the recipe pointer into a scratch slot. After reading your v1.23.0 code, I realized that Khuong’s old code was not simply a normal pointer chain. It was also using a hook-assisted saved pointer mechanism. So I think your code is best understood as a proper v1.23.0 update of Khuong’s old crafting recipe code.

Both versions use the same basic idea:

Code:
hook Meta.CraftWithRecipe$$GetRelevantInventory
save CraftingRecipeItemData* to a scratch slot
read that saved pointer with Atmosphère pointer code
edit recipe->result_->itemID_

The v1.23.0 master code is:

Code:
[00# Mastercode Get Craft 0xB4BFF00 (Select First Item)]
040A0000 08CB4F04 F0014053
040A0000 08CB4F08 F9078262
040A0000 08CB4F0C AA0203F3
040A0000 08CB4F10 1706704E
040A0000 04E51044 14F98FB0

Each `040A0000` line writes one 32-bit ARM64 instruction to `main + offset`.

So these lines:

Code:
040A0000 08CB4F04 F0014053
040A0000 08CB4F08 F9078262
040A0000 08CB4F0C AA0203F3
040A0000 08CB4F10 1706704E

write this small code cave:

Code:
0x7108CB4F04: ADRP X19, #0x710B4BF000
0x7108CB4F08: STR  X2, [X19,#0xF00]
0x7108CB4F0C: MOV  X19, X2
0x7108CB4F10: B    0x7104E51048

And this line:

Code:
040A0000 04E51044 14F98FB0

patches the original function at:

Code:
0x7104E51044

The original instruction there is:

Code:
0x7104E51044: MOV X19, X2

After the patch, it becomes:

Code:
0x7104E51044: B 0x7108CB4F04

So the game jumps to the code cave.

The hooked function is:

Code:
Meta.CraftWithRecipe$$GetRelevantInventory

In v1.23.0, the relevant argument is `recipeData`, which is a `CraftingRecipeItemData*`.

For an IL2CPP instance method on ARM64, the native register layout is usually like this:

Code:
X0 = this
X1 = first normal argument
X2 = second normal argument
X3 = MethodInfo

So in this case, `X2` appears to be:

Code:
CraftingRecipeItemData* recipeData

This also matches the original function. The game does:

Code:
MOV X19, X2

and later reads:

Code:
LDR X8, [X19,#0x48]

`CraftingRecipeItemData + 0x48` is `ingredients_`, so `X19` is being used as the recipe object.

Now the code cave:

Code:
ADRP X19, #0x710B4BF000

`ADRP` loads a 4KB page address into a register. Here it loads:

Code:
X19 = 0x710B4BF000

ARM64 often builds an address as `page + offset`, because a full 64-bit absolute address usually cannot be used directly in a normal load/store instruction.

Code:
STR X2, [X19,#0xF00]

This stores the 64-bit value in `X2` to:

Code:
0x710B4BF000 + 0xF00 = 0x710B4BFF00

In main-offset form:

Code:
0x710B4BFF00 = main + 0x0B4BFF00

So this line saves the current `CraftingRecipeItemData*` pointer to:

Code:
main + 0x0B4BFF00

Then:

Code:
MOV X19, X2

restores the original instruction that was replaced by the hook.

Finally:

Code:
B 0x7104E51048

returns to the original function, immediately after the replaced instruction.

So the code cave is basically:

Code:
*(u64 *)(main + 0x0B4BFF00) = recipeData;
X19 = recipeData;
return to the original function;

The segment table is important here:

Code:
Name      Start           End             Permission
.text     0x7100000000    0x7108CB5000    R-X
.rodata   0x7108CB5000    0x710966E958    R--
.data     0x710A4FC000    0x710B1014C0    RW-
.bss      0x710B1014C0    0x710B4BF138    RW-
Imports   0x710B4C0008    0x710B4C17A8    R--

The code cave is placed at:

Code:
0x7108CB4F04

This is inside the `.text` segment and before `.rodata` starts at:

Code:
0x7108CB5000

Since `.text` has execute permission, unused padding near the end of `.text` can be used as an ASM code cave.

The saved pointer slot is:

Code:
0x710B4BFF00

This is after `.bss` ends:

Code:
0x710B4BF138

and before Imports starts:

Code:
0x710B4C0008

So it is in the padding area after `.bss` and before Imports. More importantly, it is still in the same 4KB page as the end of `.bss`:

Code:
0x710B4BF000 - 0x710B4BFFFF

Since `.bss` is writable, this page is likely writable at runtime. That makes `0x710B4BFF00` suitable as a small 8-byte scratch slot for saving a pointer.

So the address usage is:

Code:
0x7108CB4F04  -> executable .text padding, used as ASM code cave
0x710B4BFF00  -> writable .bss-end padding, used as saved pointer storage

After the master code saves the recipe pointer, the example code can use it:

Code:
[(ZL) Change Selected Crafting Recipe To DreamSnaps Decor Reward]
580F0000 0B4BFF00
580F1000 00000040
780F0000 00000018
640F1000 00000000 01DF2085

Line by line:

Code:
580F0000 0B4BFF00

This loads a 64-bit pointer from:

Code:
main + 0x0B4BFF00

into Atmosphère Cheat VM register `R15`.

Because the master code saved `recipeData` there, this gives:

Code:
R15 = CraftingRecipeItemData*

Next:

Code:
580F1000 00000040

This dereferences:

Code:
R15 = *(u64 *)(R15 + 0x40)

`CraftingRecipeItemData + 0x40` is `result_`, so now:

Code:
R15 = ResultInstance*

Next:

Code:
780F0000 00000018

This adds `0x18`:

Code:
R15 = R15 + 0x18

`ResultInstance + 0x18` is `itemID_`, so now `R15` points to:

Code:
&result_->itemID_

Finally:

Code:
640F1000 00000000 01DF2085

writes the 32-bit value `0x01DF2085` to the address in `R15`.

So the pointer code is basically:

Code:
recipe = *(CraftingRecipeItemData **)(main + 0x0B4BFF00);
result = recipe->result_;       // +0x40
result->itemID_ = 0x01DF2085;   // +0x18

The object path is:

Code:
CraftingRecipeItemData + 0x40 -> result_
ResultInstance + 0x18 -> itemID_

This is the same basic design as Khuong’s old v1.8.6 code.

Khuong’s old code saved the recipe pointer to:

Code:
main + 0x0B9B0F08

and then read it from the crafting recipe code.

Your v1.23.0 code saves the recipe pointer to:

Code:
main + 0x0B4BFF00

and then reads it from the new pointer code.

So the mechanism is:

Code:
hook GetRelevantInventory
save CraftingRecipeItemData* to scratch slot
read saved pointer with Atmosphère pointer code
edit recipe->result_->itemID_

One small note: the posted example title says `(ZL)`, but the shown pointer-code lines do not include the usual button wrapper. If it should only run while holding ZL, it would normally need:

Code:
80000100
...
20000000

As far as I can tell, patjenova is one of the most active cheat-code contributors on GBAtemp. His codes often show techniques that seem to come from many years of studying, updating, and reverse engineering different cheat-code patterns. In that sense, his codes are probably much better learning material than my own codes, since I usually only make and share practical, game-specific codes for the games I personally play.
 
Thank you, patjenova. Your code helped me understand Khuong’s old crafting recipe code more correctly.

I need to correct my earlier understanding. I was mainly looking at the pointer-code part of Khuong’s old code, and I missed that the Master Code also had the part that saves the recipe pointer into a scratch slot. After reading your v1.23.0 code, I realized that Khuong’s old code was not simply a normal pointer chain. It was also using a hook-assisted saved pointer mechanism. So I think your code is best understood as a proper v1.23.0 update of Khuong’s old crafting recipe code.


As far as I can tell, patjenova is one of the most active cheat-code contributors on GBAtemp. His codes often show techniques that seem to come from many years of studying, updating, and reverse engineering different cheat-code patterns. In that sense, his codes are probably much better learning material than my own codes, since I usually only make and share practical, game-specific codes for the games I personally play.
dont be so hars on yourself. You did a great job with this game and came furter than most people did. But you are correct in a way that code making can only be achieved by learning codes.
 
Here it is for 1.23.0
[00# Mastercode Get Craft 0xB4BFF00 (Select First Item)]
040A0000 08CB4F04 F0014053
040A0000 08CB4F08 F9078262
040A0000 08CB4F0C AA0203F3
040A0000 08CB4F10 1706704E
040A0000 04E51044 14F98FB0

And this is an example code you could try.
[(ZL) Change Selected Crafting Recipe To DreamSnaps Decor Reward]
580F0000 0B4BFF00
580F1000 00000040
780F0000 00000018
640F1000 00000000 01DF2085
Thanks a bunch, patjenova. You're one of the greats! I took khuong's old pointer & searched it with breeze. Tons of results to try one by one. I then manually searched for where the new asm cheat would go (by copying and pasting a large chunk of the instructions from the old main file, and from the new main file into 2 notepad windows on my computer...then I searched & compared where the new asm instruction would go based on where it was in the old game this is very time consuming, but it's been the easiest method for me...) Brute force...lots of patience😂, too much tenacity.... I can sometimes get that stupid festive fish to inventory then the game crashes. I'm no good with pointer codes, but my result seems like it was probably way too many lines for what it needed to be. I'll be seeing what I can do with what you posted now. You're far better than I am, so I will probably have more success now using your code as a template. Awesome! Thanks for the assistance!
Post automatically merged:

I am not really a general cheat-code maker. I mostly like decorating games, so I learned some DDV cheat-code / IL2CPP / ASM basics to give myself more freedom in the game. I also learned in a similar way. For Fashion Dreamer, I studied and reproduced some of Thor Hammer’s cheats to understand how IL2CPP game cheats work. So I agree that reverse engineering other people’s cheats is a very useful way to learn.

About Khuong’s old crafting item code, I think it is useful to separate two things:

  • what the pointer code does
  • how Khuong originally found the pointer

The old v1.8.6 code is:

Code:
80000100
580F0000 0B9B0F08
580F1000 00000040
480D0000 00000000 00000018
640F01D0 00000000 07270E68
480D0000 00000000 0000001C
640F01D0 00000000 00000001
20000000

This is not ARM64 ASM. It is an Atmosphère Cheat VM pointer code.

Roughly, it does this:

Code:
if (ZL_is_pressed)
{
p = *(u64 *)(main + 0x0B9B0F08);
result = *(u64 *)(p + 0x40);

```
*(u32 *)(result + 0x18) = ITEMID;
*(u32 *)(result + 0x1C) = AMOUNT;
```

}

Here, R15 and R13 are Cheat VM virtual registers, not ARM64 X15/X13.

Since this code was made for v1.8.6, I checked it against the v1.8.6 dump.cs.

There are two possible structures to compare.

First, `CraftWithRecipe.Types.Request` in v1.8.6 has:

Code:
CraftWithRecipe.Types.Request
+0x18 = craftingRecipeItemID_
+0x1C = amountOfCrafting_

So if we only look at the final writes:

Code:
write +0x18 = ITEMID
write +0x1C = AMOUNT

then Request is still possible.

But the code does one more important thing before those writes:

Code:
580F1000 00000040

That means:

Code:
R15 = *(u64 *)(R15 + 0x40);

Now compare that with `CraftingRecipeItemData` in the v1.8.6 dump:

Code:
CraftingRecipeItemData
+0x18 = iD_
+0x20 = name_
+0x28 = displayName_
+0x30 = iconAddress_
+0x38 = prefabAddress_
+0x40 = result_
+0x48 = ingredients_
+0x50 = recipeType_

And `CraftingRecipeItemData.Types.ResultInstance` has:

Code:
ResultInstance
+0x18 = itemID_
+0x1C = amount_
+0x20 = state_

So the full pointer chain matches this very cleanly:

Code:
selected CraftingRecipeItemData
+0x40 -> result_

result_
+0x18 -> itemID_
+0x1C -> amount_

That is why I think the code is more likely modifying the selected recipe’s `ResultInstance`, not a temporary `CraftWithRecipe.Request`.

In pseudo-code:

Code:
selectedRecipe = *(CraftingRecipeItemData **)(main + 0x0B9B0F08);
result = selectedRecipe->result_;

result->itemID_ = ITEMID;
result->amount_ = AMOUNT;

Khuong’s comment also supports this:



That makes sense if the code changes the loaded `CraftingRecipeItemData.result_` object. Once changed, that recipe stays modified in memory until the game reloads the recipe data.

So for v1.23.0, I do not think the final offsets are the hard part. The same basic layout still seems to exist:

Code:
CraftingRecipeItemData + 0x40 -> result_
ResultInstance + 0x18 -> itemID_
ResultInstance + 0x1C -> amount_

The hard part is finding the new equivalent of:

Code:
main + 0x0B9B0F08 -> currently selected CraftingRecipeItemData*

That first pointer is what needs to be rediscovered.

I also do not know exactly how Khuong originally found it. He may have used memory search, pointer search, dump.cs/IDA, GDB, or a mix of those.

However, because the recipe stays changed until reload, I do not think a simple search like this is enough:

Code:
select recipe A
search result Item ID A
select recipe B
filter for result Item ID B

That assumes the same address changes from Item ID A to Item ID B. But I think each recipe has its own `ResultInstance`, and the thing that changes when selecting another recipe is probably the selected recipe pointer:

Code:
selectedRecipeSlot = recipeA;
selectedRecipeSlot = recipeB;

So the target should be the selected `CraftingRecipeItemData` pointer slot, not a changing `itemID_` value.

For actually adding holiday/event items like festive fish, I still think save editing is usually the easiest method. It is much easier than creating a new cheat code, and there is already a guide here:

Disney Dreamlight Valley: Adding Currencies and Items

But I completely understand wanting to study the cheat itself. Even if save editing is easier for this specific goal, reverse engineering Khuong’s code is still useful for learning how the game stores and accesses data at runtime.
Post automatically merged:


About the online chests, I had not really thought about that problem before because I usually play online. So I did not realize how annoying the blue moonstone chests could be for offline players. I have confirmed that they can be moved or removed in real time with an experimental Grid Edit expansion code I made. It allows normally restricted objects, including the blue moonstone chest, to be selected/moved/removed in Grid Edit mode. However, I have not released that code because it can be dangerous. More accurately, some parts of it can create save states where the game may no longer boot normally. The problem is not only removing objects, but bypassing too many placement / validity checks. That can allow objects to spawn or be placed in places where the game normally never expects them to exist. So for this specific problem, I still think save editing is the simpler and safer method.

I think the blue moonstone chest item is probably this one:

Code:
2010000064,ItemSpawning/MoonStoneChest,RecurringEvent.LootPresent1_DisplayName,RecurringEvent,FALSE,None,None

If you search the save for:

Code:
2010000064

you may find something like this. In my save, I found:

Code:
"220": {
"ItemSpawning": {
"RecurringEventItemID": 2010000064,
"NextOccurrence": "2026-07-04T00:00:00Z",
"EndDate": null,
"LastOccurrence": "2026-07-03T03:43:21.837559900Z"
}
}

I have not tested this specific save edit, but I suspect changing `NextOccurrence` to a far future date may stop the blue chest from spawning until that date.

For removing an already-spawned blue chest, I think the GridObject removal method I explained earlier in this thread should also work. If you can find the blue chest’s GridObject entry in the save, deleting that GridObject entry should remove the chest. Unfortunately, I cannot give an exact example from my current save because I disabled automatic spawned objects, including the blue moonstone chest, with my test code. So my save currently does not contain a blue chest GridObject entry to use as a sample.
Yeah, I've broken so many save files with my trial & error way of doing things that starting over, or reinstalling the game has become standard. Im more surprised when I DONT have to restart, and even if I do restart I don't care. I don't feel like I've lost anything that's impossible to get back. I have my save saved at the point just after I get all the tools & off I go! As a matter of fact, a couple times, I updated the scramblecoin figurine code wrong & somehow blocked myself from being able to use any other figurines than what you start with, but I finally fixed it...then started over. it's so similar to some of your other 'get all' codes that all I have to do is change a few numbers. Works great👍 !

Ill have to look at the save from my computer before it goes back on the switch. I wonder if it is something with the date, but that date eventually passes ev en on the switch when offline & the chests don't respawn. the night thorns don't even respawn for some reason, but I'm not complaining, I'm just curious as to why now. Happy accident maybe. Stopping a few things from respawning will likely be my next task, so thanks for the very detailed explanation on how one might go about that.

I never noticed the khuong's master code had anything in it for the item asm &pointer cheat. I always do away with the master codes in my games for a layout where only the off codes are the master, or they just function as the all-in-one off code. I use AI to help me understand why the pointer code was written how it was then "decrypt" it to a code I can search with breeze & take 200 years trying them one by one with the paired asm. I'll have to go back & look at those lines from the old code that I tossed aside because they didn't go with anything. I definitely need more knowledge when it comes to pointer codes. They're more confusing, so thanks for breaking it down like you did. That makes it a bit easier. Thanks for sharing so much of your process. It continues to be extremely helpful!
 
Last edited by annieraccoon,
  • Like
Reactions: patjenova

Site & Scene News

Popular threads in this forum