diff --git a/3ds/source/picoc/pksm_api.cpp b/3ds/source/picoc/pksm_api.cpp index b6660a3a..86a6a1a6 100644 --- a/3ds/source/picoc/pksm_api.cpp +++ b/3ds/source/picoc/pksm_api.cpp @@ -1,6 +1,6 @@ /* * This file is part of PKSM - * Copyright (C) 2016-2022 Bernardo Giordano, Admiral Fish, piepie62 + * Copyright (C) 2016-2022 Bernardo Giordano, Admiral Fish, piepie62, FM1337 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -96,6 +96,21 @@ namespace return (void*)ret; } + void* bufToRet(const void* buf, size_t size) + { + void* ret = malloc(size); + if (ret) + { + std::memcpy(ret, buf, size); + } + return ret; + } + + u8* bufToRet(std::span buf) + { + return (u8*)bufToRet(buf.data(), buf.size_bytes()); + } + template [[noreturn]] void scriptFail(struct ParseState* Parser, const std::string& str, Ts... args) { @@ -2128,6 +2143,123 @@ void pkx_get_value( delete pkm; } +void pkx_update_party_data( + struct ParseState* Parser, struct Value* ReturnValue, struct Value** Param, int NumArgs) +{ + u8* data = (u8*)Param[0]->Val->Pointer; + pksm::Generation gen = pksm::Generation(Param[1]->Val->Integer); + + checkGen(Parser, gen); + + auto pkm = getPokemon(data, gen, true); + + if (!pkm) + { + scriptFail(Parser, "Not a Pokemon"); + } + + pkm->refreshChecksum(); + pkm->updatePartyData(); +} + +void sav_get_palpark( + struct ParseState* Parser, struct Value* ReturnValue, struct Value** Param, int NumArgs) +{ + u8** out = (u8**)Param[0]->Val->Pointer; + int* outSize = (int*)Param[1]->Val->Pointer; + + if (TitleLoader::save->generation() != pksm::Generation::FOUR) + { + Gui::warn("PalPark is only in Gen 4"); + ReturnValue->Val->Integer = 0; + *outSize = 0; + return; + } + + std::optional, 6>> mons = + (static_cast(*TitleLoader::save)).palPark(); + + if (!mons) + { + Gui::warn("No PalPark Pokemon Stored"); + ReturnValue->Val->Integer = 0; + *outSize = 0; + return; + } + + for (int i = 0; i < 6; i++) + { + out[i] = bufToRet((*mons)[i]->rawData()); + } + + *outSize = 6; + + ReturnValue->Val->Integer = 1; +} + +void sav_set_palpark( + struct ParseState* Parser, struct Value* ReturnValue, struct Value** Param, int NumArgs) +{ + u8** data = (u8**)Param[0]->Val->Pointer; + pksm::Generation* generations = (pksm::Generation*)Param[1]->Val->Pointer; + int inSize = Param[2]->Val->Integer; + + if (TitleLoader::save->generation() != pksm::Generation::FOUR) + { + Gui::warn("PalPark is only in Gen 4"); + ReturnValue->Val->Integer = 0; + return; + } + + if (inSize != 6) + { + Gui::warn("Please provide 6 Pokemon"); + ReturnValue->Val->Integer = 0; + return; + } + + std::array, 6> mons; + + std::array reasons = {pksm::Sav::BadTransferReason::OKAY, + pksm::Sav::BadTransferReason::OKAY, pksm::Sav::BadTransferReason::OKAY, + pksm::Sav::BadTransferReason::OKAY, pksm::Sav::BadTransferReason::OKAY, + pksm::Sav::BadTransferReason::OKAY}; + + for (int i = 0; i < 6; i++) + { + auto pkx = getPokemon(data[i], generations[i], true); + + mons[i] = std::unique_ptr{ + static_cast(TitleLoader::save->transfer(*pkx).release())}; + + reasons[i] = TitleLoader::save->invalidTransferReason(*pkx); + } + + for (int i = 0; i < 6; i++) + { + if (!mons[i]) + { + Gui::warn(std::vformat(i18n::localize("NO_TRANSFER_PATH_SINGLE"), + std::make_format_args( + (std::string)generations[i], (std::string)TitleLoader::save->generation()))); + ReturnValue->Val->Integer = 0; + return; + } + + if (reasons[i] != pksm::Sav::BadTransferReason::OKAY) + { + Gui::warn(i18n::localize("NO_TRANSFER_PATH") + '\n' + + i18n::badTransfer(Configuration::getInstance().language(), reasons[i])); + ReturnValue->Val->Integer = 0; + return; + } + } + + static_cast(*TitleLoader::save).palPark(mons); + + ReturnValue->Val->Integer = 1; +} + void sav_inject_wcx( struct ParseState* Parser, struct Value* ReturnValue, struct Value** Param, int NumArgs) { diff --git a/common/include/picoc/pksm_api.h b/common/include/picoc/pksm_api.h index 1ff4b6b9..fc6a36a4 100644 --- a/common/include/picoc/pksm_api.h +++ b/common/include/picoc/pksm_api.h @@ -169,6 +169,8 @@ void sav_get_int(struct ParseState*, struct Value*, struct Value**, int); void sav_set_int(struct ParseState*, struct Value*, struct Value**, int); void sav_get_string(struct ParseState*, struct Value*, struct Value**, int); void sav_set_string(struct ParseState*, struct Value*, struct Value**, int); +void sav_get_palpark(struct ParseState*, struct Value*, struct Value**, int); +void sav_set_palpark(struct ParseState*, struct Value*, struct Value**, int); // i/o stuff void current_directory(struct ParseState*, struct Value*, struct Value**, int); void read_directory(struct ParseState*, struct Value*, struct Value**, int); @@ -186,6 +188,7 @@ void pkx_generate(struct ParseState*, struct Value*, struct Value**, int); void pkx_is_valid(struct ParseState*, struct Value*, struct Value**, int); void pkx_set_value(struct ParseState*, struct Value*, struct Value**, int); void pkx_get_value(struct ParseState*, struct Value*, struct Value**, int); +void pkx_update_party_data(struct ParseState*, struct Value*, struct Value**, int); // random utilities void pksm_utf8_to_ucs2(struct ParseState*, struct Value*, struct Value**, int); void pksm_ucs2_to_utf8(struct ParseState*, struct Value*, struct Value**, int); diff --git a/common/source/picoc/library_pksm.c b/common/source/picoc/library_pksm.c index 081b5bdd..482e6704 100644 --- a/common/source/picoc/library_pksm.c +++ b/common/source/picoc/library_pksm.c @@ -48,6 +48,8 @@ struct LibraryFunction UnixFunctions[] = { sav_set_int, "void sav_set_int(int data, int off1, int off2);" }, { sav_get_string, "char* sav_get_string(int off1, int off2, unsigned int codepoints);" }, { sav_set_string, "void sav_set_string(char* string, int off1, int off2, unsigned int codepoints);" }, + { sav_get_palpark, "int sav_get_palpark(char** out, int* outSize);" }, + { sav_set_palpark, "int sav_set_palpark(char** data, int inSize);" }, // does it need to be char**? // pkm { pkx_encrypt, "void pkx_decrypt(char* data, enum Generation type, int isParty);" }, { pkx_decrypt, "void pkx_encrypt(char* data, enum Generation type, int isParty);" }, @@ -57,6 +59,7 @@ struct LibraryFunction UnixFunctions[] = { pkx_is_valid, "int pkx_is_valid(char* data, enum Generation gen);" }, { pkx_set_value, "void pkx_set_value(char* data, enum Generation gen, enum PKX_Field field, ...);" }, { pkx_get_value, "unsigned int pkx_get_value(char* data, enum Generation gen, enum PKX_Field field, ...);" }, + { pkx_update_party_data, "void pkx_update_party_data(char* data, enum Generation gen);"}, // io { current_directory, "char* current_directory(void);" }, { read_directory, "struct directory* read_directory(char* dir);" }, diff --git a/core b/core index 5c8ab504..3f94ced9 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 5c8ab504f4e19d7a30ee805af7568f6f92fb9ce4 +Subproject commit 3f94ced9ed97d202983d25cd750cd7b8cbbfa0dc