ref: c68e140551d9cfdded2f1d37cdcd3969e34f6c15
parent: ffd9c547836f1046655a07f9377cce8ea5804a6b
author: Jacob Moody <moody@posixcafe.org>
date: Sun May 14 22:23:11 EDT 2023
initial pokemon "decrypting"
--- a/gen3.c
+++ b/gen3.c
@@ -2,6 +2,38 @@
#include <libc.h>
#include "gen3.h"
+int poketab[24][4] = {
+ {0, 12, 36, 24},
+ {0, 12, 24, 36},
+ {0, 36, 12, 24},
+ {0, 36, 24, 12},
+ {0, 24, 12, 36},
+ {0, 24, 36, 12},
+ {12, 0, 36, 24},
+ {12, 0, 24, 36},
+ {12, 36, 0, 24},
+ {12, 36, 24, 0},
+ {12, 24, 0, 36},
+ {12, 24, 36, 0},
+ {36, 0, 12, 24},
+ {36, 0, 24, 12},
+ {36, 12, 0, 24},
+ {36, 12, 24, 0},
+ {36, 24, 0, 12},
+ {36, 24, 12, 0},
+ {24, 0, 12, 36},
+ {24, 0, 36, 12},
+ {24, 12, 0, 36},
+ {24, 12, 36, 0},
+ {24, 36, 0, 12},
+ {24, 36, 12, 0},
+};
+
+enum{
+ STrainer,
+ SInvent,
+};
+
typedef struct Save Save;
struct Save{
Section bank1[14];
@@ -8,6 +40,7 @@
Section bank2[14];
Section *active;
Trainer tr;
+ Invent inv;
};
Save save;
@@ -14,7 +47,39 @@
long getsection(Section*,uchar*);
long gettrainer(Trainer*,uchar*);
+long getinvent(Invent*,uchar*);
+long getpokedat(Pokedat*,uchar*);
+#define PUT4(p, u) (p)[3] = (u)>>24, (p)[2] = (u)>>16, (p)[1] = (u)>>8, (p)[0] = (u)
+
+static void
+cryptpokedat(uchar *b, u32int id, u32int personality)
+{
+ uchar key[4];
+ int i;
+
+ PUT4(key, id^personality);
+ for(i = 0; i < 12*4; i++)
+ b[i] = b[i] ^ key[i%4];
+}
+
+static Pokedat
+decryptpokemon(Pokemon *src)
+{
+ uchar buf[12*4];
+ Pokedat ret;
+ int *t;
+
+ t = poketab[src->personality % nelem(poketab)];
+ memcpy(buf + t[0], src->data, 12);
+ memcpy(buf + t[1], src->data + 12, 12);
+ memcpy(buf + t[2], src->data + 24, 12);
+ memcpy(buf + t[3], src->data + 36, 12);
+ cryptpokedat(buf, src->otid, src->personality);
+ assert(getpokedat(&ret, buf) == sizeof buf);
+ return ret;
+}
+
static char*
pkstr(uchar *p, uchar *e)
{
@@ -37,8 +102,9 @@
main(int argc, char **argv)
{
int fd;
- int i;
+ int i, j;
uchar buf[8192];
+ Pokedat pd;
ARGBEGIN{
default:
@@ -68,12 +134,23 @@
}
save.active = save.bank1[0].index > save.bank2[0].index ? save.bank1 : save.bank2;
for(i = 0; i < 14; i++){
- if(save.active[i].id != 0)
- continue;
- gettrainer(&save.tr, save.active[i].data);
- fprint(2, "%s\n", pkstr(save.tr.name, save.tr.name + 7));
- fprint(2, "%d %d %d\n", save.tr.hours, save.tr.min, save.tr.sec);
- fprint(2, "%d %d\n", save.tr.id, save.tr.secretid);
- fprint(2, "%d\n", save.tr.gamecode);
+ switch(save.active[i].id){
+ case STrainer:
+ gettrainer(&save.tr, save.active[i].data);
+ fprint(2, "%s\n", pkstr(save.tr.name, save.tr.name + 7));
+ fprint(2, "%d %d %d\n", save.tr.hours, save.tr.min, save.tr.sec);
+ fprint(2, "%d %d\n", save.tr.id, save.tr.secretid);
+ fprint(2, "%d\n", save.tr.gamecode);
+ break;
+ case SInvent:
+ getinvent(&save.inv, save.active[i].data + 0x34);
+ fprint(2, "tamsz: %d\n", save.inv.teamsz);
+ for(j = 0; j < save.inv.teamsz; j++){
+ fprint(2, "%s\n", pkstr(save.inv.team[j].name, save.inv.team[j].name + 10));
+ pd = decryptpokemon(save.inv.team+j);
+ fprint(2, "%d\n", pd.g.species);
+ }
+ break;
+ }
}
}
--- a/gen3dat.c
+++ b/gen3dat.c
@@ -130,6 +130,216 @@
}
long
+getblockg(Blockg *ret, uchar *data)
+{
+ long n;
+
+ n = 0;
+ ret->species = GET2(data+n);
+ n += 2;
+ ret->item = GET2(data+n);
+ n += 2;
+ ret->exp = GET4(data+n);
+ n += 4;
+ ret->ppbonus = data[n];
+ n += 1;
+ ret->friendship = data[n];
+ n += 1;
+ ret->magic = GET2(data+n);
+ n += 2;
+ return n;
+}
+
+long
+putblockg(uchar *dst, Blockg *src)
+{
+ long n;
+
+ n = 0;
+ PUT2(dst+n, src->species);
+ n += 2;
+ PUT2(dst+n, src->item);
+ n += 2;
+ PUT4(dst+n, src->exp);
+ n += 4;
+ dst[n] = src->ppbonus;
+ n += 1;
+ dst[n] = src->friendship;
+ n += 1;
+ PUT2(dst+n, src->magic);
+ n += 2;
+ return n;
+}
+
+long
+getblocka(Blocka *ret, uchar *data)
+{
+ long n;
+
+ n = 0;
+ ret->move1 = GET2(data+n);
+ n += 2;
+ ret->move2 = GET2(data+n);
+ n += 2;
+ ret->move3 = GET2(data+n);
+ n += 2;
+ ret->move4 = GET2(data+n);
+ n += 2;
+ memcpy(ret->pp, data+n, 4);
+ n += 4;
+ return n;
+}
+
+long
+putblocka(uchar *dst, Blocka *src)
+{
+ long n;
+
+ n = 0;
+ PUT2(dst+n, src->move1);
+ n += 2;
+ PUT2(dst+n, src->move2);
+ n += 2;
+ PUT2(dst+n, src->move3);
+ n += 2;
+ PUT2(dst+n, src->move4);
+ n += 2;
+ memcpy(dst+n, src->pp, 4);
+ n += 4;
+ return n;
+}
+
+long
+getblockm(Blockm *ret, uchar *data)
+{
+ long n;
+
+ n = 0;
+ ret->pokerus = data[n];
+ n += 1;
+ ret->met = data[n];
+ n += 1;
+ ret->origins = GET2(data+n);
+ n += 2;
+ ret->iv = GET4(data+n);
+ n += 4;
+ ret->ribbions = GET4(data+n);
+ n += 4;
+ return n;
+}
+
+long
+putblockm(uchar *dst, Blockm *src)
+{
+ long n;
+
+ n = 0;
+ dst[n] = src->pokerus;
+ n += 1;
+ dst[n] = src->met;
+ n += 1;
+ PUT2(dst+n, src->origins);
+ n += 2;
+ PUT4(dst+n, src->iv);
+ n += 4;
+ PUT4(dst+n, src->ribbions);
+ n += 4;
+ return n;
+}
+
+long
+getblocke(Blocke *ret, uchar *data)
+{
+ long n;
+
+ n = 0;
+ ret->hp = data[n];
+ n += 1;
+ ret->atk = data[n];
+ n += 1;
+ ret->def = data[n];
+ n += 1;
+ ret->spd = data[n];
+ n += 1;
+ ret->spatk = data[n];
+ n += 1;
+ ret->spdef = data[n];
+ n += 1;
+ ret->cool = data[n];
+ n += 1;
+ ret->beauty = data[n];
+ n += 1;
+ ret->cute = data[n];
+ n += 1;
+ ret->smart = data[n];
+ n += 1;
+ ret->tough = data[n];
+ n += 1;
+ ret->feel = data[n];
+ n += 1;
+ return n;
+}
+
+long
+putblocke(uchar *dst, Blocke *src)
+{
+ long n;
+
+ n = 0;
+ dst[n] = src->hp;
+ n += 1;
+ dst[n] = src->atk;
+ n += 1;
+ dst[n] = src->def;
+ n += 1;
+ dst[n] = src->spd;
+ n += 1;
+ dst[n] = src->spatk;
+ n += 1;
+ dst[n] = src->spdef;
+ n += 1;
+ dst[n] = src->cool;
+ n += 1;
+ dst[n] = src->beauty;
+ n += 1;
+ dst[n] = src->cute;
+ n += 1;
+ dst[n] = src->smart;
+ n += 1;
+ dst[n] = src->tough;
+ n += 1;
+ dst[n] = src->feel;
+ n += 1;
+ return n;
+}
+
+long
+getpokedat(Pokedat *ret, uchar *data)
+{
+ long n;
+
+ n = 0;
+ n += getblockg(&ret->g, data+n);
+ n += getblocka(&ret->a, data+n);
+ n += getblockm(&ret->m, data+n);
+ n += getblocke(&ret->e, data+n);
+ return n;
+}
+
+long
+putpokedat(uchar *dst, Pokedat *src)
+{
+ long n;
+
+ n = 0;
+ n += putblockg(dst+n, &src->g);
+ n += putblocka(dst+n, &src->a);
+ n += putblockm(dst+n, &src->m);
+ n += putblocke(dst+n, &src->e);
+ return n;
+}
+
+long
getpokemon(Pokemon *ret, uchar *data)
{
long n;
@@ -195,7 +405,16 @@
n = 0;
ret->teamsz = GET4(data+n);
n += 4;
- n += getpokemon(&ret->p1, data+n);
+ n += getpokemon(&ret->team[0], data+n);
+ n += getpokemon(&ret->team[1], data+n);
+ n += getpokemon(&ret->team[2], data+n);
+ n += getpokemon(&ret->team[3], data+n);
+ n += getpokemon(&ret->team[4], data+n);
+ n += getpokemon(&ret->team[5], data+n);
+ ret->money = GET4(data+n);
+ n += 4;
+ ret->coins = GET2(data+n);
+ n += 2;
return n;
}
@@ -207,7 +426,16 @@
n = 0;
PUT4(dst+n, src->teamsz);
n += 4;
- n += putpokemon(dst+n, &src->p1);
+ n += putpokemon(dst+n, &src->team[0]);
+ n += putpokemon(dst+n, &src->team[1]);
+ n += putpokemon(dst+n, &src->team[2]);
+ n += putpokemon(dst+n, &src->team[3]);
+ n += putpokemon(dst+n, &src->team[4]);
+ n += putpokemon(dst+n, &src->team[5]);
+ PUT4(dst+n, src->money);
+ n += 4;
+ PUT2(dst+n, src->coins);
+ n += 2;
return n;
}