Jump to content

FE: Awakening Hacking Topic


VincentASM
 Share

Recommended Posts

So i've come to the conclusion there is no way to trick the game into giving you map-specific characters. You cannot recruit validar with cheats :|

It's because of static.bin, right?

The character blocks only read character data from static.bin (which contains all the playable characters plus Dummy, two Risens, a merchant and maybe something I'm forgetting... I know you listed all the characters before) and the chapter-specific files. But if you're not in the specific chapter, you can't read from its chapter file.

However if you really want, you can modify static.bin itself, like how I added Phila to my party. Since Dummy the character isn't used (I think?), you can rewrite its contents to your liking, adding new PID, FID labels etc.

Of course, you can't save any changes in static.bin, but you can just keep applying the cheats each time you reload your save.

Link to comment
Share on other sites

  • Replies 877
  • Created
  • Last Reply

Top Posters In This Topic

It's because of static.bin, right?

The character blocks only read character data from static.bin (which contains all the playable characters plus Dummy, two Risens, a merchant and maybe something I'm forgetting... I know you listed all the characters before) and the chapter-specific files. But if you're not in the specific chapter, you can't read from its chapter file.

However if you really want, you can modify static.bin itself, like how I added Phila to my party. Since Dummy the character isn't used (I think?), you can rewrite its contents to your liking, adding new PID, FID labels etc.

Of course, you can't save any changes in static.bin, but you can just keep applying the cheats each time you reload your save.

So, just like how I modified MU x MU to be added instead of replacing Chrom... we just look at the nightmare module as a base to modify it?

Also, Vincent, your crack reel video is getting notes on my tumblr.

Edited by shadowofchaos
Link to comment
Share on other sites

So, just like how I modified MU x MU to be added instead of replacing Chrom... we just look at the nightmare module as a base to modify it?

Also, Vincent, your crack reel video is getting notes on my tumblr.

Kinda. I think m0rt is working on a AR code generator that will enable easy editing of that part of the RAM.

But what I'm talking about is a bit more complex than just editing values slightly. What I'm doing is adding labels beyond the preset ones in static.bin so I can add characters not normally in that file.

Unfortunately, there's not enough space in static.bin to add new characters via traditional means, but since there's a character called Dummy that isn't used, you can fill its space with anything you want, even new labels.

For example, to "add" Phila, I wrote the PID, FID, MPID and MPID_H labels for Phila in Dummy, then changed all of Flavia's pointers to point to the new labels for Phila.

You could do the same thing for Validar or any other character, within reason.

Even better, you don't have to worry about corrupting your save files since the changes aren't permanent even when you save.

Haha, I must confess I don't use tumblr much, but I assume the video is getting some exposure? I did try to fill it with as much in-jokes as I could think of XD

Edited by VincentASM
Link to comment
Share on other sites

I believe I found my character table, thanks to m0rt's lovely explanation on how to find it (Search "48 53 44 41 72 63 00 01 ?? ?? ?? ?? 39 00 00 00").

For me it begins at 01398598ish

Took a screenshot. Now to figure out how these supports are laid out. Is this where you went to change the Support Rank for MUxMU, SoC?

I believe I'm looking at Male Avatar, but I can't tell where the S-support to Tharja is. I'm assuming 643D3A15 is the Male Avatar since it's the first character table entry.

I wanna know how these values work. Help? :)

EDIT: Turns out I was reading it wrong. Gonna redo a pic later

So far I know these values for a fact

643D3A15 - Avatar Male
753D3A15 - Avatar Female
993D3A15 - Chrom
A43D3A15 - Lissa

Changing the Support data in the Character Table changes the potential rank I guess?

Edited by Jacien
Link to comment
Share on other sites

Hello, I recently joined on this site and was trying RAM hacking for FE. I need help with on how to get the first slot player all the skills just like how SWD did.

I've tried multiple times and it hasn't been working. I want to give everyone all the skills and making a code for each player would be too time consuming. Can anyone help me with this?

Edited by bobsung92
Link to comment
Share on other sites

So I've been playing around with the support tables and trying to read it.

I see that Male Avatar's support table is organized by males then females (basically grouping all the As then Bs), and Female Avatar's Support table goes females then males.

So I'm trying to get a grasp on changing the values and what they mean.

For example, Sumia for Chrom was 03080D12, which apparently means S-rank achieved, cause when I gave it to Lissa, it made Chrom married to Lissa at the same time. And when I gave Sumia Lissa's 040A1263, it made Sumia's S rank disappear entirely.

Also saving and reloading just reverts things to how they were before. Do changes not stay permanent, or do I need to change the partner too? Gonna try.

Just random notes to pick up when I'm back from work.

040A1263 (at A, no S)

050A1016 (at A, gray S)

03080D12 (at S ChromXSumia, works with others)

643D3A15 - Avatar Male
753D3A15 - Avatar Female
993D3A15 - Chrom
A43D3A15 - Lissa (A rank -040A1263)
063E3A15 - Sumia (S rank - 03080D12)

01398CEC 120D0803 (ChromXLissa)

Now what throws me off I that I can change my Male Avatar's Support to S-rank Chrom, but I don't see Tharja with an S-rank in his table. I'll dig through later.

Edited by Jacien
Link to comment
Share on other sites

This adds all skills to the entire current roster:

This code is slightly bugged, see a few posts later for a fixed/upgraded version.
[spoiler=code]

Seriously, look two posts down. not hard.


There's a stupid trick in there to skip blocks that don't appear to be player-characters (if a block has NO skills, it gets skipped).
It loops over 0x40 blocks, which generally should be your entire roster.

Outline of code if someone needs to modify the offsets/use it as a framework for doing something to all roster blocks:
[spoiler=pseudocode]
outer loop, 0x110 stride

check skill block at 0134b928 == 0

check skill block at 0134b92c == 0

check skill block at 0134b930 == 0

write flag

pop (D0)

check flag != ffffffff

write skill blocks

pop (D0)

check flag == ffffffff

clear flag

end (D2)


Also trying to overwrite the class pointer block in the roster table, but it doesn't seem to be taking.

I have succesfully forced MU♀, Lucina and Morgan♂ into manakete class, In the sense that they can attack properly.

The sprites do not update for some reason, that may be cached somewhere else.

Also, the results are fairly hilarious (it defaults to Nowi's torso model for any manakete except Nah, which is interesting as well).

I'll try to get some pictures up.

Edited by Rilne
Link to comment
Share on other sites

So I've been playing around with the support tables and trying to read it.

I see that Male Avatar's support table is organized by males then females (basically grouping all the As then Bs), and Female Avatar's Support table goes females then males.

So I'm trying to get a grasp on changing the values and what they mean.

For example, Sumia for Chrom was 03080D12, which apparently means S-rank achieved, cause when I gave it to Lissa, it made Chrom married to Lissa at the same time. And when I gave Sumia Lissa's 040A1263, it made Sumia's S rank disappear entirely.

Also saving and reloading just reverts things to how they were before. Do changes not stay permanent, or do I need to change the partner too? Gonna try.

Just random notes to pick up when I'm back from work.

Now what throws me off I that I can change my Male Avatar's Support to S-rank Chrom, but I don't see Tharja with an S-rank in his table. I'll dig through later.

Nothing in that part of the RAM is saved. What that part is is a file called static.bin that the game loads from the ROM each time you startup the game.

If you want to save time, grab the character editor from the front page, because it lets you view all the supports easily. Just load up static.bin from the ROM and everything should line up.

However, static.bin in the RAM has different pointers, so the character editor doesn't work for it. But the structure is the same.

03080D12 means support points C: 3 / B: 8 / A: 13 / S: 18

Why it becomes an automatic S rank is because the pair have been accumulating support points past A (notice how max-support characters can still earn hearts when paired up) and when you apply the new support points criteria, these accumulated points are enough for a S Rank.

Link to comment
Share on other sites

Previous code has a bug, found it while reworking it with search preamble to find roster block.

New code: (with fancy search function so it doesn't matter where your character block is)

[spoiler=code]

D3000000 01330000
C0000000 00180000
50000000 00000110
50000004 000000C8
50000008 00000000
5000000C 00000000
C0000000 00000000
D0000000 00000000
DC000000 00000010
D1000000 00000000
C0000000 00000040
50000018 00000000
5000001C 00000000
50000020 00000000
00000010 FFFFFFFF
D0000000 00000000
60000010 FFFFFFFF
00000018 FFFFFFFF
0000001C FFFFFFFF
00000020 FFFFFFFF
D0000000 00000000
50000010 FFFFFFFF
00000010 00000000
D0000000 00000000
DC000000 00000110
D2000000 00000000

Since this starts low and looks over a wide area, it takes alot longer than if you know your starting offset.
But it should be plug-and-play for any dlc/region combination.
If anyone wants just the search preamble:
[spoiler=preamble]
D3000000 01330000
C0000000 00180000
50000000 00000110
50000004 000000C8
50000008 00000000
5000000C 00000000
C0000000 00000000
D0000000 00000000
DC000000 00000010
D1000000 00000000

After the end of this block, the current offset will be the start of the first character roster block.
(This was adapted from duke_srg on the gbatemp forums)

Hopefully this is helpful to someone.

Link to comment
Share on other sites

Previous code has a bug, found it while reworking it with search preamble to find roster block.

New code: (with fancy search function so it doesn't matter where your character block is)

[spoiler=code]

D3000000 01330000

C0000000 00180000

50000000 00000110

50000004 000000C8

50000008 00000000

5000000C 00000000

C0000000 00000000

D0000000 00000000

DC000000 00000010

D1000000 00000000

C0000000 00000040

50000018 00000000

5000001C 00000000

50000020 00000000

00000010 FFFFFFFF

D0000000 00000000

60000010 FFFFFFFF

00000018 FFFFFFFF

0000001C FFFFFFFF

00000020 FFFFFFFF

D0000000 00000000

50000010 FFFFFFFF

00000010 00000000

D0000000 00000000

DC000000 00000110

D2000000 00000000

Since this starts low and looks over a wide area, it takes alot longer than if you know your starting offset.

But it should be plug-and-play for any dlc/region combination.

If anyone wants just the search preamble:

[spoiler=preamble]

D3000000 01330000

C0000000 00180000

50000000 00000110

50000004 000000C8

50000008 00000000

5000000C 00000000

C0000000 00000000

D0000000 00000000

DC000000 00000010

D1000000 00000000

After the end of this block, the current offset will be the start of the first character roster block.

(This was adapted from duke_srg on the gbatemp forums)

Hopefully this is helpful to someone.

I thought the co--- *reads thread again*

...OH, the *CODE HACKS* codetypes don't work.

So search codes work via loops.

Well, I'm an idiot.

Time to make better codes instead of direct writes then.

I get the explanation in the link... but there's no 50000000 codetype in the doc.

http://doc.kodewerx.org/hacking_nds.html

Can you offer more of an explanation?

Because from what I understand from what you linked:

D3000000 16800000
C0000000 00180000
50000000 DF070000
50000004 04000000
5000000C 00000000
DC000000 FFFFFFDF
00000000 E8030000
00000004 63000000
C0000000 00000000
D0000000 00000000
DC000000 00000004
D1000000 00000000
Explanation:

string 1 - set search start offset

string 2 - set area length to search, in units (i.e. if search in 32-bit word increments, divide area size in bytes by four. in most cases data is aligned to 4 bytes on 3DS)

string 3 - check if word at offset+0 = 0x7DF, skip to D0000000 if not

string 4 - check if word at offset+4 = 0x4, skip to D0000000 if not

string 5 - check if word at offset+0x0C = 0, skip to D0000000 if not

string 6 - set offset = offset - 21, i.e. the actual data to change offset relative to the found signature (needed in case of negative offset only)

string 7 - set word at offset = 0x3E8

string 8 - set word at offset+4 = 0x63

string 9 - set loop counter to zero - exit loop if patch is needed only at one offset

string 10 - end of if checks

string 11 - offset = offset +4 - iterate the next offset

string 12 - end of loop

50000000 DF070000

For your code:

50000000 00000110

Wouldn't it be 50000000 10010000 instead?

Just looking via observations.

I haven't tested anything yet.

Edited by shadowofchaos
Link to comment
Share on other sites

So, I linked it more as credit for initial work.

That version does the edit in the search loop.

Mine exits the loop with the offset set to right after the target fragment,

And lets the next block act on it (basically so the search block is separable from what you actually want to do at the target)

[spoiler=pseudocode]

set offset to start of search range
outer loop, 0x10 stride
check 0x0 == 10010000 (00000110)
check 0x4 == C8000000 (000000C8)
check 0x8 == 00000000
check 0xc == 00000000
set loop count 0 (break)
pop (D0)
stride 0x10
end (D1)
outer loop, 0x110 stride
check skill block at 00000018 == 0
check skill block at 0000001c == 0
check skill block at 00000020 == 0
write flag (ffffffff) to 00000010
pop (D0)
check flag != ffffffff
write skill blocks
pop (D0)
check flag == ffffffff
clear flag
end (D2)

The second block is similar to the previous one I posted, but addressed from the start of each character block (since the search block drops us right at it).
Also has a typo fixed in it.
The search block would be better as some sort of straight asm/C, but I don't know the ARM ISA, and I don't want to get a toolchain set up when I have this nice web qr-generator.
The 5XXXXXXX YYYYYYYY code type is the 'equal to' block. It only executes following code lines (until a pop, ie. D0/1/2) if the value at offset+XXXXXXXX == YYYYYYYY. There's also variants for !=, > and <. Very useful for dropping in loops to protect against stupid things like overrunning a variable length structure/skipping over dummy values/etc.
Hopefully my pseudocode helps explain the preamble better, if not, ask me again.
ninja edit: the 10010000 vs. 00000110 is a little-endian vs. big-endian gotcha.
The value we dump from memory is 10010000, but the value of that (as a 32-bit int) is 0x00000110.
The codes are expecting a big-endian (ie. highest byte first, how a human would read the value) value.
The ram dump is little-endian because the ARM architecture is little-endian.
I actually missed that initially when working on this and it was never finding the target, then facepalmed and fixed it to what's here.
Edited by Rilne
Link to comment
Share on other sites

So, I know I'm popping in here, and I apologize: I've no right to be here whole the pros do their thing.

But I'm curious: is there a way to figure out Growth Rate now?

Like, if I recall, an example would be Praim, as his haven't been decided. (Or found? Or figured out? I'm not sure how rates for the others were found)

Link to comment
Share on other sites

See here (I don't know how to do the fancy linked quotes on here), that data is likely in the static character block table, whereas the one I'm messing with is the roster table (holds most of the variable data, the character block table should have what you're looking for).

That said, I'm unsure how some of the children's values are calculated (class pools, stat caps, etc), It would make sense to cache the values in the roster, but I can't seem to pin down those in there. It could be computed based on the known (static) parent and the pointer to the other parent, but it seems silly to not just compute it once and save it.

Link to comment
Share on other sites

Okaaaay, got it. Pseudocode makes it clearer.

I derped.

I somehow just skipped over the conditionals while looking through the documentation.

...and I just got reminded of one of the most basic lessons of CS. Painfully.

"LOOK AT THE DOC (carefully)".

Yeah, I was confused as I remember the RAM dump being little endian and the initial explanation from that link.

Thank you.

I remember screwing up a 32-bit write codetype when this RAM hacking capability first came out because I wrote in little endian as it was in the memory dump.

Link to comment
Share on other sites

Figured that The Lunatic Club could use your help. Here's an observation from there:

The site support tables are being inconsistent with my ingame results again.

In Prologue, Avatar-M fights with Chrom as a pair up partner 5 times, and also gets a bunch of support points from standing next to Chrom whilst killing stuff during the water trick. Yet, at the end of Chapter 1, I don't have a C support option. Once again I'm left pondering the support leeching theory since Frederick is standing next to them all the time. Chrom also somehow doesn't get C Frederick despite fighting with him 6 times in Prologue as well.

In Chapter 1, Avatar is off killing stuff on a fort with Fred whilst Chrom is pulling weakened units with Sully, so they aren't building any there, but it really shouldn't matter. I can get to C Chrom Sully just by doing the 4 battles thing easily in C1, same for AvatarxFrederick. :\

EDIT: And I know the support table thing doesn't correspond to "battles fought" in 1 to 1, I read the last post Tables made on the subject. I mean that Avatar-M and Chrom should be capping out at 12 battle points easily in Prologue, which gives them 3 total support points, which should be enough for a C support.

The tl;dr is - do the support values change for Lunatic and/or Lunatic+?

Link to comment
Share on other sites

For clarification, I don't think the actual "Support Points needed to advance a level of support" value change so much as the way the support point gaining seems to change in some manner or other, much in the same manner that EXP gain has a decay on Lunatic(+). I have some videos I've given to Tables and Kaoz and Czar in the past but none of them were able to figure out what caused the issue. I can pretty easily just go record a Prologue to end of Chapter 1 thing as well just to demonstrate the results too.

Edited by Irysa
Link to comment
Share on other sites

So, I know I'm popping in here, and I apologize: I've no right to be here whole the pros do their thing.

But I'm curious: is there a way to figure out Growth Rate now?

Like, if I recall, an example would be Praim, as his haven't been decided. (Or found? Or figured out? I'm not sure how rates for the others were found)

Yes and no.

Like in the previous game, growth rates are encrypted and cannot be read using traditional means. But there is a way to decipher them somewhat.

Unfortunately, at the moment, certain growth rates (mainly super high ones) can't be resolved because of lack of data, from guidebooks or otherwise.

Here are Priam's growths anyway:

PRIAM    >70    60    10    40    30    50    40    10
Link to comment
Share on other sites

Yay, so I'm home from work now. Catching up on the thread since I posted.

Being able to see everything in order using the Nightmare thingy is nice. Now I understand how it works, I suppose.

What I'm seeing in the Support table isn't what rank they've reached. It's what their highest possible rank and at what speed it fills up. When I gave Lissa the "fast S-rank" attribute, it made it so the support points she accrued went beyond the "fast S-rank" limit, which is why the S-rank lit up.

And what I finally realized is using codes to modify RAM written by Static.bin is temporary. When the game loads up, it loads up static.bin forcing what should exist by default. Static.bin will never change due to using AR codes, it can only be hard changed (which is what you did to add in Phila, right?)

I just did a test by removing the S-rank between my Female Avatar and Stahl before going into the Paralogue, and I got a pink-haired Morgan with no parent pointers. Exactly what I thought would happen. Morgan has Pink Hair in the View Card of an Avatar's Logbook if you haven't recruited him yet. That's his hard-coded default (in vanilla, not Future Past DLC)

Now two questions about Character Blocks:

I believe SWD mentioned Support Points are stored in Character Blocks? Anybody know how they work?

And also how do the parent pointers work? I compared two different dumps for Noire and they are different, so it's not static. I remember when I tried the Avatar swap with SpotPass to change hair color, the Avatar still had the kids listed under him.

I'm assuming they point to the mother, (or father for Female Morgan) and see who is the partner, then the family descriptor gets added to all 3 members. This also seems to enable the family support conversations, because my Avatar/Stahl cannot support with Male Morgan due to no parent pointer link.

Link to comment
Share on other sites

I think we need to clarify character block and the active units (which has your hp, stats, support points, etc.).

I modified the support table for MU x MU.

Where the points are stored, are where the HP and such for character slots.

So if I load the save (resetting) without codes... the points are still there... it just has no data to say who those points are for.

To see how it works, get two characters in slot 1 and slot 2 on a skirmish.

Dump memory.

Use a seed of trust.

Dump memory.

The support points (Above the block of FFs for the next character) should increase by 1.

Edited by shadowofchaos
Link to comment
Share on other sites

I guess I wasn't clear on what I was asking about regarding support points.

I know the accrued point totals are part of the active roster blocks. I was wondering on how to read them in the block, and is there any particular order are they are in?

Someone mentioned that it's after the Weapon Rank. So using my usual example, is it part of that string of 12s right after it?

E1PMwml.png

Link to comment
Share on other sites

Okay cool. Maybe sometime later I can try to figure how the bytes for each unit or something. If it's two bytes maybe "1212" is the max? IDK.

Anyway, so I decided to play around with converting an imported Logbook character to a main Female Avatar using the proper Character Pointer. (A8853915 is my Male Avatar, E0873915 is my Female Avatar).

Someone else mentioned they did the same thing, when they loaded up their save file, it seemed to make the Female Avatar the main character. I figured out how it works.

Basically if you have two "main" Avatars, when you load the game, it looks whichever one comes first in the party roster, and it thinks that is your story Avatar. So everything reflects that. Roster Entry 000, Cutscenes, Story Recap, Dialog, etc. However, the StreetPass data is unaffected.

You can manipulate this by moving which Avatar you want to be the lead before the other, save the game, reset, load the save and save again.

Even if the "converted" Avatar is the main character, her dying isn't an instant Game Over, and least what I tested. I think the avatar being the one for instant Game Over is tied to the StreetPass data.

And it's neat having a female "main" Avatar too, cause she can then do Support Convos. But since I've already recruited Female Morgan, the Paralogue doesn't "re unlock" when she S-ranks. Also, she doesn't have supports available to the 2nd gen units.

I have a theory regarding the latter. When you recruit a 2nd gen unit, the game writes into static.bin the Support values for your Avatar to be able to Support the 2nd gen unit. If you haven't recruited them yet, that value is blank. So my female Avatar isn't able to support them because she wasn't there when they were recruited. I guess?

Regardless, now I wanna figure out how I can make the Parent Pointer work how I want it too. If I create a Male Morgan by overriding a Logbook character, I'd want to point the parent pointer to my Female Avatar.

Or maybe, if there's a way to undo the flag that the Paralogue for Morgan was unlocked? So I could do it again with the other Avatar and recruit a second Morgan?

So many things I wanna do, and all I cared about was red hair lol. I also drank too much atm.

Edited by Jacien
Link to comment
Share on other sites

Okay cool. Maybe sometime later I can try to figure how the bytes for each unit or something. If it's two bytes maybe "1212" is the max? IDK.

Anyway, so I decided to play around with converting an imported Logbook character to a main Female Avatar using the proper Character Pointer. (A8853915 is my Male Avatar, [/size]E0873915 is my Female Avatar).[/size]

Someone else mentioned they did the same thing, when they loaded up their save file, it seemed to make the Female Avatar the main character. I figured out how it works.[/size]

Basically if you have two "main" Avatars, when you load the game, it looks whichever one comes first in the party roster, and it thinks that is your story Avatar. So everything reflects that. Roster Entry 000, Cutscenes, Story Recap, Dialog, Str, etc. However, the StreetPass data is unaffected.

You can manipulate this by moving which Avatar you want to be the lead before the other, save the game, reset, load the save and save again.

Even if the "converted" Avatar is the main character, her dying isn't an instant Game Over, and least what I tested. I think the avatar being the one for instant Game Over is tied to the StreetPass data.

And it's neat having a female "main" Avatar too, cause she can then do Support Convos. But since I've already recruited Female Morgan, the Paralogue doesn't "re unlock" when she S-ranks. Also, she doesn't have supports available to the 2nd gen units.

I have a theory regarding the latter. When you recruit a 2nd gen unit, the game writes into static.bin the Support values for your Avatar to be able to Support the 2nd gen unit. If you haven't recruited them yet, that value is blank. So my female Avatar isn't able to support them because she wasn't there when they were recruited. I guess?

Regardless, now I wanna figure out how I can make the Parent Pointer work how I want it too. If I create a Male Morgan by overriding a Logbook character, I'd want to point the parent pointer to my Female Avatar.

Or maybe, if there's a way to undo the flag that the Paralogue for Morgan was unlocked? So I could do it again with the other Avatar and recruit a second Morgan?

So many things I wanna do, and all I cared about was red hair lol. I also drank too much atm.

Even if you switch them around though, FeMU's Morgan takes priority.

That's what happened to mine.

I wonder if it's two different chapters.

Like they're clones. And it has a different "Chapter value".

And if we can trigger that by just going into a Skirmish and then manipulating the value as it loaded.

Just as you can do with the GBA FE's.

Link to comment
Share on other sites

Please accept my apologies for if this question has been asked before, I must have missed it while browsing the forest.

With this method, would it be possible to recruit Mustafa? I always felt that he should've been a recruitable unit. (Replace his character pointer number with a current member of your guild?) I don't know much about 3DS ROM Hacking, I'm more of a "casual" GBA/DS/GC/Wii guy. Probably should hop on the 3DS Rom Hacking boat with all the stuff you guys are finding out. Huge thanks to all of you!

Edited by TohruAdachi
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...