Created
December 14, 2017 10:49
-
-
Save oupo/9add0b15e46cd05ccbdb4981b0ef1bd1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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