Skip to content

Commit

Permalink
Add PalPark scripting APIs (#1453)
Browse files Browse the repository at this point in the history
* Added functions to pksm_api for refreshing party data and getting palpark mons.

Also added bufToRet

* Add sav_set_palpark function

* Format and fix palpark code

---------

Co-authored-by: Chris Feger <christopherfeger@yahoo.com>
  • Loading branch information
FM1337 and piepie62 authored Apr 10, 2024
1 parent 4496a01 commit 386edb7
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 2 deletions.
134 changes: 133 additions & 1 deletion 3ds/source/picoc/pksm_api.cpp
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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<const u8> buf)
{
return (u8*)bufToRet(buf.data(), buf.size_bytes());
}

template <typename... Ts>
[[noreturn]] void scriptFail(struct ParseState* Parser, const std::string& str, Ts... args)
{
Expand Down Expand Up @@ -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<std::array<std::unique_ptr<pksm::PK4>, 6>> mons =
(static_cast<pksm::Sav4&>(*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<std::unique_ptr<pksm::PK4>, 6> mons;

std::array<pksm::Sav::BadTransferReason, 6> 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<pksm::PK4>{
static_cast<pksm::PK4*>(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<pksm::Sav4&>(*TitleLoader::save).palPark(mons);

ReturnValue->Val->Integer = 1;
}

void sav_inject_wcx(
struct ParseState* Parser, struct Value* ReturnValue, struct Value** Param, int NumArgs)
{
Expand Down
3 changes: 3 additions & 0 deletions common/include/picoc/pksm_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions common/source/picoc/library_pksm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);" },
Expand All @@ -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);" },
Expand Down
2 changes: 1 addition & 1 deletion core

0 comments on commit 386edb7

Please sign in to comment.