Skip to content

PicoC Basics

Chris Feger edited this page Sep 29, 2019 · 12 revisions

This page details the basics of beginning with picoC PKSM scripts.

This is not a guide to programming in C. If you need a primer (or refresher) on C, see C References below.

Getting Started

Here is the simplest skeleton of a picoC PKSM script

#include <pksm.h> // PKSM provided virtual header giving access to scripting API
#include <stdlib.h>

int main(int argc, char **argv)
{
    // PKSM 7.0.1 and before
    unsigned char *saveData = (unsigned char *)atoi(argv[0]);
    // After PKSM 7.0.1
    unsigned char *saveData = (unsigned char *)argv[0];
    int saveLength = atoi(argv[1]);
    unsigned char version = *argv[2];

    // do work here...

    return 0;
}

Feel free to remove any of the variable declarations you don't need, or use different names for the variables.

main Arguments

  • argc is useless in scripts -- leave it in the parameters list for main but otherwise ignore it
  • argv
    • argv[0] pointer to save data, as an integer, passed as text (PKSM 7.0.1 and before)
    • argv[0] pointer to save data (After PKSM 7.0.1)
    • argv[1] save data length (int passed as text)
    • argv[2] save's game version (game's index number as found in a Pokémon's source/origin game field)
Game Version argv[2]
Diamond 10 10
Pearl 11 10*
Platinum 12 12
HeartGold 7 7
SoulSilver 8 7*
White 20 20
Black 21 21
White 2 22 22
Black 2 23 23
X 24 24
Y 25 25
Alpha Sapphire 26 26
Omega Ruby 27 27
Sun 30 30
Moon 31 31
Ultra Sun 32 32
Ultra Moon 33 33
Let's Go, Pikachu! 42 42
Let's Go, Eevee! 43 43

* - By content alone, Gen 4 saves from the same pair cannot be told apart from each other. This means that Pearl saves will have an argv[2] equal to 10 (same as Diamond) and SoulSilver will have an argv[2] equal to 7 (same as HeartGold).

General Enums and Structs

PKSM provides a few enums and structs to scripts, most of which have a narrow scope of use and are detailed alongside the function(s) they pair with. Below are the multi-use ones

Generation

enum Generation {
    GEN_FOUR,
    GEN_FIVE,
    GEN_SIX,
    GEN_SEVEN,
    GEN_LGPE
};

// example usage
int pokePick = gui_menu_6x5("Choose Honey Tree Pokémon", optNum, &treePokes[0], &pokes[0], GEN_FOUR);

When something depends on the generation being worked with (sprites, data structure, etc.), use one of these. The example usage code comes from the DPPT Honey Tree script, though there are other examples available in the repo.

Pouch

enum Pouch {
    NormalItem,
    KeyItem,
    TM,
    Mail,
    Medicine,
    Berry,
    Ball,
    Battle,
    Candy,
    ZCrystals
};

Using API functions that work with the player's bag requires using one of these to specify which pouch to work with.

Tips and Tricks

  • Avoid allocating arrays based a size stored in a variable (for instance char buffer[size];). Use something along the lines of char* buffer = malloc(size); instead and free the pointer after use.

Accessing Save Values

This is more of a basic C concept, but I think it's important enough to demonstrate explicitly.

// 1 byte value
char val = saveData[offset];
saveData[offset] = val;

// 2 byte values
short val = *(short *)(saveData + offset);
*(short *)(saveData + offset) = val;

// 4 byte values
int val = *(int *)(saveData + offset);
*(int *)(saveData + offset) = val;

All data types in these examples are signed, but unsigned works just as well (and might be needed instead depending on the data you're working with)

C References

Here is a list of references for C programming in general. Not all material will be applicable to PKSM scripts since picoC is a subset of C90.