Extract RSBOX checksum logic to checksum class
Allocate half as much for gen3 save detect
Simplify some expressions for GC save loading (x - size + offset, when x==size)
plugin adds a reader -> reader checks if it is a non-PKHeX.Core save type (they'd implement their own savefile/etc type) -> returns a matching save object if so
basically bypasses the base PKHeX logic
path.getfilename will never return null unless you pass null, which we don't do
setchecksums' base method does the AllBlocks.SetChecksums. move the battle team set to right before the usage of SetChecksums
Disassociate pk4/pk6 backing byte[] when converting to pk5|pk7, as we no longer make a copy of the byte[] in the pkm's constructor.
Change UpdatePKM to include isParty, as we want it optional to update FormArgument too.
Change FormArgument saving to be handled by FormConverter; kinda not really good to have it there, but nothing else is handling FormArgument values.
Expand IFormArgument to have all FormArgument values exposed. "Maximum" is furfrou only.
PK6: Max is in the "FormArgument" u32, and the remain/elapsed is in party stats (hence the reverting when boxed)
PK7: u8 remain, u8 elapsed, u8 max, u8 unused.
PK8: assumedly the same as PK7, given the disassembly hints that it's the same as past games (even though Furfrou and Hoopa are not in SWSH).
## Issue
We want to discard-but-remember any slots that aren't a perfect fit, on the off chance that a better one exists later in the search space. If there's no better match, then we gotta go with what we got.
## Example:
Wurmple exists in area `X`, and also has a more rare slot for Silcoon, with the same level for both slots.
* We have a Silcoon that we've leveled up a few times.
Was our Silcoon originally a Wurmple, or was it caught as a Silcoon?
* To be sure, we have to check the EC/PID if the Wurmple wouldn't evolve into Cascoon instead.
* We don't want to wholly reject that Wurmple slot, as maybe the Met Level isn't within Silcoon's slot range.
---
Existing implementation would store "deferred" matches in a list; we only need to keep 1 of these matches around (less allocation!). We also want to differentiate between a "good" deferral and a "bad" deferral; I don't think this is necessary but it's currently used by Mystery Gift matching (implemented for the Eeveelution mystery gifts which matter for evolution moves).
The existing logic didn't use inheritance, and instead had static methods being reused across generations. Quite kludgy. Also, the existing logic was a pain to modify the master encounter yield methods, as one generation's quirks had to not impact all other generations that used the method.
---
The new implementation splits out the encounter yielding methods to be separate for each generation / subset. Now, things don't have to check `WasLink` for Gen7 origin, because Pokémon Link wasn't a thing in Gen7.
---
## Future
Maybe refactoring yielders into "GameCores" that expose yielding behaviors / properties, rather than the static logic. As more generations and side-gamegroups get added (thanks LGPE/GO/GameCube), all this switch stuff gets annoying to maintain instead of just overriding/inheritance.
## Conclusion
This shouldn't impact any legality results negatively; if you notice any regressions, report them! This should reduce false flags where we didn't defer-discard an encounter when we should have (wild area mons being confused with raids).
Retain a stringbuilder to mutate the string rather than finalizing temporary strings
yields some speed improvements (less gen0 string objects allocated)
Closes#2954 ; can set directly from propertygrid already, but might as well clean things up a little bit to match the disassembly logic.
Open the simple editor center parent rather than next-form-position
don't use FIPS compliant hashing methods explicitly, no real reason to. hash.Create() will select managed vs csp depending on the framework/core and reg flags.
add >net46 incremental hash logic for swsh
remove static sha256 instance (single threaded overkill)
Further improvements can be made if there's a way to have a union struct (4 u16s, lumped u64) that has a simple 4bit diagonal mirror operation on it. Can be at least twice as fast.
Benchmarking with optimizations shows about 80-90% of the prior time taken, so at least a 10% speed optimization
Rarely used, was fun to try and optimize a little more.
Eliminate bounds checks by accessing/setting the highest element, and only index twice instead of 6x.
Eliminate u16 casts by leaving as int type (same result)
Eliminate temp value caching and instead directly write to storage. (no more _0123).
End result looks neat too, since the >> 0's removed looks like a diagonal, like the nibble rotation :D
Add xmldoc
Remove linq from memecrypto code (speed lmao)
Hide some methods that shouldn't be called directly
Name variables better for accessor const's
GCI, DSV, DUC are already supported, so I've written the abstraction for those and seed the Handler list on startup.
Can add a new class with recognition via SaveUtil.Handlers.Add(myHandler);
AltForm & Form & Forme => Form
GenNumber & Generation => Generation
Extract out SpeciesForm interface, and re-add IGeneration
For those using PKHeX as a dependency, this should be a pretty straightforward manual replacement... GenNumber and AltForm should be quick find-replace`s.
Trees:
- Only retain the objects needed after calculation
- Reduce size of TreeCoordinates and remove allocation penalty (now a struct)
No more warnings for Release compilation :D
Move form-info logic from FormConverter to AltFormInfo; now FormConverter is entirely form=>string[]
Add a bunch of xmldoc
Make pogo no-end-date cmp agaisnt UTCnow rather than local now.
So I said that 0xF26B9151 was the first Max Lair Pokemon entry saved in my previous commit which turned out to be wrong and was in fact the Pokemon that is to be hinted by Peonia. Apologies for that mess up.
Handle all warnings
obviously the usage of null! could potentially be avoided if the object init wasn't such garbage, but here we are with years of old junk and lack of abstraction in the GUI project
Closes#3028
Thanks @CarlosofKalos !
Setting 9999 for both on Rattata; capturing the 10,000th didn't increment, but transferring the 10,000th did.
Co-Authored-By: Matt <17801814+sora10pls@users.noreply.github.com>
This format won't be supported cleanly, so let's just try to allow language detection to work as best as it can without storing metadata in the SK2 bytes.
Extract common abstract class for shared logic
Clean up property/field/method ordering to be consistent and logical (roughly: attributes, constructors, state management, retrievable values, static methods)
Apply default language OT name
Closes#3009
Make QRPK7 implement IEncounterable and remove hardcoded PKHeX strings
Let force hatching for WC3 eggs try to hatch from the savefile's language, then revert to english if failed to set an OT.
Use underscores for enum for ToString replacing with spaces
Don't flag empty-OT as SK2; Stadium0/1 use the "TRAINER" as rental, but leave it blank for SK2.
Don't set any terminators for an OT string if the string is empty; just wipe the buffer.
Readonly slots
Things could be expanded on to use interfaces and wrappers for a "SlotReference" and properties for readonly.
But that's kinda unnecessary
Detects the language of the currently loaded save file, and passes that info to the blank sav creator
Use a trainer name of "1337" instead of PKHeX for any Japanese save file, because Gen1/2(/3?) character tables don't have regular ascii chars.
Introducing a new PKM format: SK2
Split ICaughtData2 off of PK2 so it can be shared with SK2 when type-checks occur
Add conversion for PK2<->SK2
Split the split-buffer handling for GBPKM to GBPKML (what a name), so that I can reuse shared accessor logic for SK2.
Move Home8 location to Locations.cs for documentation
Move FestaFacility to correct folder
Remove unnecessary public modifier on interface method
Pass the program's Version to any loaded plugins, if they wanted to check compatibility...?
SWSH is the first common savefile type that has different revisions after official patches. We want to indicate in the Program Title which revision we're currently editing, because people still are not editing latest-format saves and complaining y no urshifu.
Use short descriptions to indicate revision (Base, IoA, CT), rather than magic numbers (v0/v1) or 1.X or 1.X.Y+, because GameFreak can't follow semver rules.
go away ranch platinum update, i might handle you another time
Was previously showing RaidArmor for pre-Armor saves, as the reference of a zero-length array was the same as the bools. Just sanity check since all block chunks have length.
Change Ability array to IReadOnlyList, add method to check ability index in personal data
Suppress some message warnings
Change EvolutionChain short-circuit for VC to jump from gen6 directly down to gen2. There aren't any notradeback 1 situations, so a notradeback1 will always start with g=1, so no need for the other if-continue.
Simplify pk5 conversion
The game also stores the Gender ID, Form ID, Encryption Constant, and Alcremie Sweet ID per block for each PKM's slot.
As for Sweet ID it is stored for all Types. However, since you obviously can't use Alcremie in non-Fairy Sparring they go unused. (They are the Int32 blocks you'll notice with a -1 value.)
Add SIZE_BOXSLOT and update usages
Make SIZE_STORED protected like SIZE_PARTY
probably need to redesign how slot metadata is presented within the savefile...
Closes#2961 ty @Kermalis !
Check egg encounter for state rather than re-deriving some properties on the fly
Only check memories if memories are exposed
Remove debug assert (not always true?)
* Added PokeWalker Courses, Watts, and Steps editing
* Use util method for getting bitflags
* Keep old cheat method
Change signature so that the default value passed is to unlock all; can pass 0 instead to lock all
* Pass reference to derived sav4-type object
Wev'e already type-tested once, capture the reference and pass it into the appropriate load/save methods.
* Add control anchoring for window resizing
Also widen the labels for localization (longer strings possibly)
Can't correlate the structure to the data it's reading, so don't modify the values until someone figures out how the data is stored & how it should be manipulated.
Closes#2941
Also clamp give all for TMs to 1 instead of whatever the giveall value is, like for prior games' HMs
reuse the "free space" bool; no real benefit in increasing the amount of abstraction (even though that's my current urge for legality)
FFFF and 0000 -> prefer 0000
FFFF and 0001 -> prefer 0001
...
FFFF and FFFE -> prefer FFFF
they shouldn't be desync'd (incremental); only the uninitialized case is important to handle.
Accessible in block editor, not as the usual trainer records.
Closes#2913 , ty @CanoeHope!
Co-Authored-By: canoehope <canoehope@users.noreply.github.com>
no change in species/form from the crownite ore one afaik; common for both games???
fix type of rigel encount so it shows up in block editor, with correct name (ty matt)
SCBlock doesn't have an absolute index; it was only used for tagging in dumps. Offset and Length weren't used.
Removing these 2 ints from the SCBlock object reduces alloc req by 8 bytes each; if we have 2,500 blocks in a save file, this reduces the memory footprint of a sav by 20KB. Nice side effect :D
Remove block dump comment from accessor; new logic in Meta8 for dumping DLC sizes does the same logic with less hassle.
If you edit in a number of 5 or greater as one of your streaks you'll get a crown mark next to that type in-game, and doing it for all should allow for you to get Mustard's uniform when you talk to the receptionist.
invert ability index favoring so that the first ability index is most favored
ability num:
-1=>0/1/2
0=>0/1,
1=>0
2 =>1
4=>2
Ability Type:
0,1,2=>0,1,2
3=>0/1
4=>0/1/2
Should probably get rid of AbilityNumber definition usage but it's so entwined in the trade/static definitions...
* New SWSH Block Data
Found these pretty useful blocks for IoA. I'll maybe look into Restricted Sparring data in the next week or so if no one else does by then.
Co-Authored-By: sciresm <sciresm@users.noreply.github.com>
Co-Authored-By: Matt <sora10pls@users.noreply.github.com>
Co-Authored-By: Archit Date <architdate@gmail.com>
Closes#2826
It doesn't find it in the SM table, but didn't return -1
rework logic flow to return when found, rather than after loop finishes.
Also fix display off-by-1 since we're not using zero indexing for our entry numbers.
Thanks @Ammako !
Closes#2840 -- access via Block Editor "Encount"
Tons of undecipherable junk in the roamer struct; looks like a mishmash of past gen code repurposed for their pseudo-stationary|roamer encounter.
ORAS has the same structure (same size/block), but the roamer portion isn't used
Closes#2697 ty @Ammako !
lazy slice check has flaws; just compare the major/minor counters in the save footer and check the uninitialized cases
nobody is gonna save the game 2^32 times, but check for the overflow case too!
first ff'd is preferred when the second is ff'd-1!
Closes#2740 ; we don't want to set display shiny if it's not shiny
we only want to set display-shiny if (!owned && shiny)
Co-Authored-By: canoehope <canoehope@users.noreply.github.com>
Because the Switch doesn't have a feature to internally store your B-day like the DS and 3DS does, you set it in-game by the "Fortune Girl" right in front of Wedgehurst's PokeCenter in month and day.
https://www.serebii.net/swordshield/birthdays.shtml
Ty @CanoeHope !
Closes#2677
To edit these values, use the Block Data editor and select the *Object Trainer Card
Co-Authored-By: CanoeHope <canoehope@users.noreply.github.com>
Now matches Interface declaration style (iAccessorGenGame), and is consistently named with the other accessors already using the same naming style
plus they are now ordered in the file tree :)
no functional change
Not done for Array types or Object types
muh reflection, such spooky
mark Offset as non-browsable so it doesn't show up in propertygrid if the block is being edited by a grid :)
I imagine a struct-type-sensitive array property grid edit could be done via Buffer.BlockCopy to a dest array, but there's so few Array blocks... so meh
Closes#2658 ty @CanoeHope !
Mostly just serves as documentation; with the amount of fields being editable increasing, hard-coded GUI might not be optimal here. I'm thinking something like a PropertyGrid based on the selected block which will pull up the Block object if the key matches... for fields, something like a dynamically populated list or something.
Use reflection to grab all const declarations (private and public), and grab the name of that const. Whenever that block is mentioned in our diff, use the name instead of the key.
Helps identify what changed / remove noise if you don't care about that block.
Record ID const declaration for reuse
Change 255->300 for streak max
Set record as well (ignore currently set value if modified via dropdown)
Closes#2649
Not sure if Money and BP can get a similar record-set treatment.
Apparently my copypaste of the class didn't delete all the old unused controls. Ha!
Move non-gui logic to core as separate classes, in case ppl wanted to reuse them in their own projects.
blank saves do not have the type metadata for the blocks that are spoofed, nor do they have all blocks spoofed.
I suspect things might get more difficult as more value-blocks are identified, which would throw a wrench into things. We'll figure that out at that time :)
Add a test to ensure that the blank save can be created correctly
Closes#2644
Blocks that use Bool1/2 toggle to the other state; evident when comparing between two different saves. The key doesn't change, only the Type is toggled.
Rather than storing a dictionary of keys, we can abuse the fact that the SCBlock[] is stored in order of ascending block key.
Binary Search doesn't require extra memory like a Dictionary would; also, we only need to find a few blocks.
blanks: {key,size}
fetch: get block by key (index isnt the same between patches, as blocks with different keys get added). The savefile stores them as a SortedDictionary (by key), hence the shifting.
All logic in PokeCrypto is separate from the rest of the PKHeX.Core
library; makes it easy to just rip this portion out and reuse in other
projects without needing the entirety of PKHeX.Core logic
optimize out the CheckEncrypted to the actual path, separate methods.
Only usages of this method were with hardcoded Format values, so no
impact
SCBlock is an input to the individual save blocks; changing the SCBlock
byte[] reference won't change the individual save block reference. Just
copy the data and keep the original reference instead.
Repro: trainer data editor, save-close window, then delete a slot.
Export save; reload. Changes to box data were using old byte[]
reference, and didn't get repointed. Works fine with latest commit now.
I think I wanted to avoid copyto since it's slower than just a reference
change; but that didn't work out perfectly :)
Hold alt when hitting activate all to dump instead
I've seen DenType=5 Event=2 for at least one raid so far... not sure if
the event/rare properties are accurate.
linq dump code I used for ez vis:
var sav = new SAV8SWSH(File.ReadAllBytes(@"D:\Kurt\Downloads\main
(7)"));
var blocks = sav.Blocks;
var raid = blocks.Raid;
raid.GetAllRaids().Dump();
Nothing for the PKM Editor; not sure how I want to handle the reused
FormDuration work value.
For the meantime, just use the Batch Editor for a targeted write.
Closes#2441
- Gender specific forms now set the correct flags
- Regular click on Check All doesn't set shiny flags
- Shift click on Check All sets shiny flags too.
Closes#2425 thanks @igniscitrinus !
Zukan5/6 was pushing 0 for the formBit, which was an incorrect value. I
probably should have abstracted things since gen5/6 don't behave the
same as gen7
rewrite the SetDisplayedFlag for more clarity, and to early-return
without checking displayed state if the flag is being cleared.
Two birds with one stone:
- sav4 doesn't use Data (instead uses General/Storage), so we need to
use the abstracted method calls instead of trying to do things manually.
- setting a blank pkm at a party slot will decrease the party count!
don't decrease things twice.
* Handle some nullable cases
Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization
* Handle bits more obviously without null
* Make SaveFile.BAK explicitly readonly again
* merge constructor methods to have readonly fields
* Inline some properties
* More nullable handling
* Rearrange box actions
define straightforward classes to not have any null properties
* Make extrabyte reference array immutable
* Move tooltip creation to designer
* Rearrange some logic to reduce nesting
* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum
* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case
* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable
* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator
* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever
* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)
* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
Extract Species Name logic to SpeciesName
Extract Language logic to Language
Remove FormConverter wrapper for string[] fetch
Rearrange some logic to more appropriate locations, update access
modifiers / types
Move some pkm array methods to arrayutil, make generic
PKX.GetVCLanguage was a dupe of _K12.GuessedLanguage() so just expose
the method
PKX is now back to pkm data manip only
dual bounds check -> single check via uint cast
pkx: keep array reference for reuse in next check
format return to second line to stick out more; lines of code are cheap
:)
split some methods with optional parameters=null
add more xmldoc
replace some magic numbers -> enum/const references
consolidate common array operations (span soon maybe?)
Increase abstraction for arbitrary slot get/set operations, and fracture
SAV4 behavior for each game type.
Adds: Undo/Redo of party slot changes
Fixes: Fixed Gen5 daycare slot 2 reading, and EXP reading
Fixes: Some slot color glitchiness
Fixed: Box layout editor now hides the flag label if no flags are
present
Fixed: Gen7 box flags are now shown (unknown purpose lol)
Changed: savefile objects are generally smaller (removed a few shared
offset fields)