shithub: pse

Download patch

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;
 }