Skip to content

Instantly share code, notes, and snippets.

@oupo
Created December 14, 2017 10:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oupo/9add0b15e46cd05ccbdb4981b0ef1bd1 to your computer and use it in GitHub Desktop.
Save oupo/9add0b15e46cd05ccbdb4981b0ef1bd1 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <cstdio>
#include <cstdint>
#include <ctime>
#include <vector>
#include "PokeRNG/Calc5GenSeed.hpp"
#include "PokeRNG/CalcOffset.hpp"
using namespace std;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int64_t s64;
struct AbstractRNG {
virtual int rand(int n) = 0;
};
struct LCG64bit : AbstractRNG {
u64 seed;
LCG64bit(u64 s) : seed(s) {}
int rand(int n) {
seed = seed * 0x5D588B656C078965 + 0x269EC3;
return (seed >> 32) * n >> 32;
}
};
struct LCG32bit : AbstractRNG {
u32 seed;
LCG32bit(u32 s) : seed(s) {}
int rand(int n) {
seed = seed * 0x41c64e6d + 0x6073;
return (seed >> 16) % n;
}
};
bool valid_seed(AbstractRNG &rng, double baseFreq, vector<double> expectedFreqs, double allowRatio = 1.015) {
for (double expected : expectedFreqs) {
double got = ((rng.rand(8192)) / 8192.0 * 0.25 + 1) * baseFreq;
double ratio;
if (expected < got) {
ratio = got / expected;
} else {
ratio = expected / got;
}
if (ratio >= allowRatio) {
return false;
}
}
return true;
}
u32 prev_seed(u32 seed) {
return seed * 0xEEB9EB65 + 0x0A3561A1;
}
bool good_seed(u32 seed) {
int i;
for (i = 0; i < 10; i ++) seed = prev_seed(seed);
for (; i < 40; i ++) {
u32 upper = seed >> 24;
u32 hour = (seed >> 16) & 0xff;
u32 frame = seed & 0xffff;
u32 second = (frame - 17) / 60 + 10;
if (12 * 24 + second - 256 <= upper && upper <= 12 * 24 + second + 60 - 256
&& hour < 24 && 0x0270 <= frame && frame <= 0x0400) {
return true;
}
seed = prev_seed(seed);
}
return false;
}
constexpr double C4 = 261.626;
constexpr double D4 = 293.665;
constexpr double E4 = 329.628;
constexpr double F4 = 349.228;
constexpr double G4 = 391.995;
constexpr double A4 = 440.000;
constexpr double B4flat = 466.164;
// 中音 (ホワイト1 + DSi)
int main1() {
vector<double> expected = { F4, F4, G4, F4, E4, G4, G4, G4, F4, E4, G4, F4, G4, E4, F4 };
double base = 325;
#pragma omp parallel for
for (long i = 946652400; i < 4102412400; i ++) {
PokeRNG::Parameters5Gen<PokeRNG::ROMType::W1JaDSi> param;
PokeRNG::Calc5GenSeed calc_seed;
PokeRNG::CalcOffset calc_offset;
param.set_mac_addr(0x00, 0x22, 0xaa, 0x38, 0x54, 0x68);
param.set_timer0(0x1233);
time_t time = i;
struct tm date;
localtime_r(&time, &date);
param.set_year(date.tm_year + 1900 - 2000);
param.set_month(date.tm_mon + 1);
param.set_day(date.tm_mday);
param.set_hour(date.tm_hour);
param.set_minute(date.tm_min);
param.set_second(date.tm_sec);
for (int key = 0; key < 0x100; key ++) {
if ((key & 0x30) == 0x30 || (key & 0xc0) == 0xc0) continue;
param.set_key(0x2fff ^ key);
PokeRNG::u64 seed = calc_seed(param);
calc_offset.bw1(seed, true, true);
LCG64bit lcg(calc_offset.get_seed());
int ofs = (int)calc_offset.get_offset();
for (int i = 0; i < 100; i ++) {
LCG64bit l = lcg;
if (valid_seed(l, base, expected, 1.02))
#pragma omp critical
{
printf("%04d/%02d/%02d %02d:%02d:%02d ", date.tm_year + 1900, date.tm_mon + 1, date.tm_mday, date.tm_hour, date.tm_min, date.tm_sec);
printf("key=%02x seed=%016lx %016lx f=%d (%d)\n", key, seed, lcg.seed, ofs + i, i);
}
lcg.rand(1);
}
}
}
return 0;
}
// 低音 (ブラック1 + DSLite)
int main2() {
vector<double> expected = { C4, D4, D4, D4, C4, C4, D4, C4, C4, D4 };
double base = 255;
#pragma omp parallel for
for (long i = 946652400; i < 4102412400; i ++) {
PokeRNG::Parameters5Gen<PokeRNG::ROMType::B1Ja> param;
PokeRNG::Calc5GenSeed calc_seed;
PokeRNG::CalcOffset calc_offset;
param.set_mac_addr(0x00, 0x21, 0x47, 0x72, 0x91, 0xb3);
time_t time = i;
struct tm date;
localtime_r(&time, &date);
param.set_year(date.tm_year + 1900 - 2000);
param.set_month(date.tm_mon + 1);
param.set_day(date.tm_mday);
param.set_hour(date.tm_hour);
param.set_minute(date.tm_min);
param.set_second(date.tm_sec);
int key = 0;
param.set_key(0x2fff ^ key);
PokeRNG::u64 seed = calc_seed(param);
calc_offset.bw1(seed, true, true);
LCG64bit lcg(calc_offset.get_seed());
int ofs = (int)calc_offset.get_offset();
for (int i = 0; i < 30; i ++) {
LCG64bit l = lcg;
if (valid_seed(l, base, expected, 1.015))
#pragma omp critical
{
printf("%04d/%02d/%02d %02d:%02d:%02d ", date.tm_year + 1900, date.tm_mon + 1, date.tm_mday, date.tm_hour, date.tm_min, date.tm_sec);
printf("key=%02x seed=%016lx %016lx f=%d (%d)\n", key, seed, lcg.seed, ofs + i, i);
}
lcg.rand(1);
}
}
return 0;
}
// 高音 (Pt)
int main3() {
vector<double> expected = { A4, A4, A4, B4flat, A4 };
double base = 400;
#pragma omp parallel for
for (s64 seed = 0; seed < 0x20000000; seed ++) {
LCG32bit lcg(seed);
if (valid_seed(lcg, base, expected, 1.008) && good_seed(seed)) {
#pragma omp critical
printf("%08x\n", (u32)seed);
}
}
return 0;
}
int main() {
return main2();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment