Appl new code style on whole code base

Use a similar code style to bemanitools though reduce indentation
to 2 spaces. Also some other tweaks to be more similar to google
style.
This commit is contained in:
icex2
2021-03-19 15:52:34 +01:00
parent b493b4983a
commit eafb2909d1
322 changed files with 30291 additions and 25084 deletions
+27 -27
View File
@@ -4,46 +4,46 @@
#define ENC_DEC_INIT_SEED 0xEBADA1
struct asset_f2_usb_rank* asset_f2_usb_rank_new(void)
struct asset_f2_usb_rank *asset_f2_usb_rank_new(void)
{
// TODO
return malloc(sizeof(struct asset_f2_usb_rank));
// TODO
return malloc(sizeof(struct asset_f2_usb_rank));
}
void asset_f2_usb_rank_finalize(struct asset_f2_usb_rank* rank)
void asset_f2_usb_rank_finalize(struct asset_f2_usb_rank *rank)
{
/* don't include the checksum field */
/*
rank->header.adler32 = util_adler32_calc(rank->header.adler_seed,
&rank->header.adler_seed,
sizeof(struct f2_profile_rank) - sizeof(uint32_t));
*/
/* don't include the checksum field */
/*
rank->header.adler32 = util_adler32_calc(rank->header.adler_seed,
&rank->header.adler_seed,
sizeof(struct f2_profile_rank) - sizeof(uint32_t));
*/
}
char* asset_f2_usb_rank_to_string(const struct asset_f2_usb_rank* rank)
char *asset_f2_usb_rank_to_string(const struct asset_f2_usb_rank *rank)
{
// TODO
return "";
// TODO
return "";
}
void asset_f2_usb_rank_decrypt(uint8_t* buf, size_t len)
void asset_f2_usb_rank_decrypt(uint8_t *buf, size_t len)
{
uint32_t seed = ENC_DEC_INIT_SEED;
uint32_t seed = ENC_DEC_INIT_SEED;
for (int i = 0; i < len; i++){
uint8_t smbuff = buf[i];
buf[i] ^= (seed >> 8) & 0xff ;
seed = 0x68993 * (smbuff + seed) + 0x4FDCF;
}
for (int i = 0; i < len; i++) {
uint8_t smbuff = buf[i];
buf[i] ^= (seed >> 8) & 0xff;
seed = 0x68993 * (smbuff + seed) + 0x4FDCF;
}
}
void asset_f2_usb_rank_encrypt(uint8_t* buf, size_t len)
void asset_f2_usb_rank_encrypt(uint8_t *buf, size_t len)
{
uint32_t seed = ENC_DEC_INIT_SEED;
uint32_t seed = ENC_DEC_INIT_SEED;
for (size_t i = 0; i < len; i++){
uint8_t smbuff = buf[i] ^ ((seed >> 8) & 0xff);
buf[i] = smbuff ;
seed = 0x68993 * (smbuff + seed) + 0x4FDCF;
}
for (size_t i = 0; i < len; i++) {
uint8_t smbuff = buf[i] ^ ((seed >> 8) & 0xff);
buf[i] = smbuff;
seed = 0x68993 * (smbuff + seed) + 0x4FDCF;
}
}
+6 -6
View File
@@ -4,18 +4,18 @@
#include <stdint.h>
struct asset_f2_usb_rank {
// TODO
// TODO
} __attribute__((__packed__));
struct asset_f2_usb_rank* asset_f2_usb_rank_new(void);
struct asset_f2_usb_rank *asset_f2_usb_rank_new(void);
// update checksum and prepare profile to get encrypted
void asset_f2_usb_rank_finalize(struct asset_f2_usb_rank* rank);
void asset_f2_usb_rank_finalize(struct asset_f2_usb_rank *rank);
char* asset_f2_usb_rank_to_string(const struct asset_f2_usb_rank* rank);
char *asset_f2_usb_rank_to_string(const struct asset_f2_usb_rank *rank);
void asset_f2_usb_rank_decrypt(uint8_t* buf, size_t len);
void asset_f2_usb_rank_decrypt(uint8_t *buf, size_t len);
void asset_f2_usb_rank_encrypt(uint8_t* buf, size_t len);
void asset_f2_usb_rank_encrypt(uint8_t *buf, size_t len);
#endif
+26 -25
View File
@@ -4,44 +4,45 @@
#define ENC_DEC_INIT_SEED 0xEBADA1
struct asset_f2_usb_save* asset_f2_usb_save_new(void)
struct asset_f2_usb_save *asset_f2_usb_save_new(void)
{
// TODO
return malloc(sizeof(struct asset_f2_usb_save));
// TODO
return malloc(sizeof(struct asset_f2_usb_save));
}
void asset_f2_usb_save_finalize(struct asset_f2_usb_save* save)
void asset_f2_usb_save_finalize(struct asset_f2_usb_save *save)
{
/* don't include the checksum field */
save->header.adler32 = util_adler32_calc(save->header.adler_seed,
&save->header.adler_seed,
sizeof(struct asset_f2_usb_save) - sizeof(uint32_t));
/* don't include the checksum field */
save->header.adler32 = util_adler32_calc(
save->header.adler_seed,
&save->header.adler_seed,
sizeof(struct asset_f2_usb_save) - sizeof(uint32_t));
}
char* asset_f2_usb_save_to_string(const struct asset_f2_usb_save* save)
char *asset_f2_usb_save_to_string(const struct asset_f2_usb_save *save)
{
// TODO
return "";
// TODO
return "";
}
void asset_f2_usb_save_decrypt(uint8_t* buf, size_t len)
void asset_f2_usb_save_decrypt(uint8_t *buf, size_t len)
{
uint32_t seed = ENC_DEC_INIT_SEED;
uint32_t seed = ENC_DEC_INIT_SEED;
for (int i = 0; i < len; i++){
uint8_t smbuff = buf[i];
buf[i] ^= (seed >> 8) & 0xff ;
seed = 0x68993 * (smbuff + seed) + 0x4FDCF;
}
for (int i = 0; i < len; i++) {
uint8_t smbuff = buf[i];
buf[i] ^= (seed >> 8) & 0xff;
seed = 0x68993 * (smbuff + seed) + 0x4FDCF;
}
}
void asset_f2_usb_save_encrypt(uint8_t* buf, size_t len)
void asset_f2_usb_save_encrypt(uint8_t *buf, size_t len)
{
uint32_t seed = ENC_DEC_INIT_SEED;
uint32_t seed = ENC_DEC_INIT_SEED;
for (size_t i = 0; i < len; i++){
uint8_t smbuff = buf[i] ^ (seed >> 8) & 0xff;
buf[i] = smbuff ;
seed = 0x68993 * (smbuff + seed) + 0x4FDCF;
}
for (size_t i = 0; i < len; i++) {
uint8_t smbuff = buf[i] ^ (seed >> 8) & 0xff;
buf[i] = smbuff;
seed = 0x68993 * (smbuff + seed) + 0x4FDCF;
}
}
+73 -73
View File
@@ -5,101 +5,101 @@
#include <stdlib.h>
struct asset_f2_usb_save_machine_stats {
uint32_t beginner_mode_play_count;
uint32_t maniac_mode_play_count;
uint32_t unkn;
uint32_t unkn2;
uint32_t battle_mode_play_count;
uint32_t mission_zone_play_count;
uint32_t skill_zone_play_count;
uint32_t coop_mission_play_count;
uint32_t beginner_mode_play_count;
uint32_t maniac_mode_play_count;
uint32_t unkn;
uint32_t unkn2;
uint32_t battle_mode_play_count;
uint32_t mission_zone_play_count;
uint32_t skill_zone_play_count;
uint32_t coop_mission_play_count;
} __attribute__((__packed__));
struct asset_f2_usb_save_machine_info {
/* NULL terminated */
char version[8];
/* NULL terminated */
char cpu[128];
/* NULL terminated */
char motherboard[128];
/* NULL terminated */
char gfxcard[128];
/* NULL terminated */
char hdd[32];
uint32_t total_ram_bytes;
uint32_t haspkey_id;
/* NULL terminated */
char version[8];
/* NULL terminated */
char cpu[128];
/* NULL terminated */
char motherboard[128];
/* NULL terminated */
char gfxcard[128];
/* NULL terminated */
char hdd[32];
uint32_t total_ram_bytes;
uint32_t haspkey_id;
} __attribute__((__packed__));
struct asset_f2_usb_save_header {
uint32_t adler32;
uint32_t adler_seed;
/* NULL terminated */
char player_id[8];
uint32_t region;
uint32_t avatar_id;
uint32_t level;
float total_calories;
float total_v02;
uint64_t num_running_steps;
uint64_t num_games_played;
uint64_t exp;
uint64_t arcade_score;
uint32_t num_missions_completed;
uint32_t num_coop_missions_completed;
uint32_t battle_count_wins;
uint32_t battle_count_loses;
uint32_t battle_count_draws;
/* TODO: modifier stuff? */
uint64_t unlock;
uint32_t unlock_seed;
uint32_t adler32;
uint32_t adler_seed;
/* NULL terminated */
char player_id[8];
uint32_t region;
uint32_t avatar_id;
uint32_t level;
float total_calories;
float total_v02;
uint64_t num_running_steps;
uint64_t num_games_played;
uint64_t exp;
uint64_t arcade_score;
uint32_t num_missions_completed;
uint32_t num_coop_missions_completed;
uint32_t battle_count_wins;
uint32_t battle_count_loses;
uint32_t battle_count_draws;
/* TODO: modifier stuff? */
uint64_t unlock;
uint32_t unlock_seed;
} __attribute__((__packed__));
struct asset_f2_usb_save_machine_highscore_entry {
uint32_t song_id;
uint8_t difficulty;
uint8_t mode;
uint8_t grade;
uint8_t clear_state;
uint32_t score_total;
uint32_t play_count;
uint32_t unkn;
/* NULL terminated */
char player_id[8];
uint32_t unkn2;
uint32_t null_padding;
uint32_t song_id;
uint8_t difficulty;
uint8_t mode;
uint8_t grade;
uint8_t clear_state;
uint32_t score_total;
uint32_t play_count;
uint32_t unkn;
/* NULL terminated */
char player_id[8];
uint32_t unkn2;
uint32_t null_padding;
} __attribute__((__packed__));
struct asset_f2_usb_save_highscore_entry {
uint32_t song_id;
uint8_t difficulty;
uint8_t mode;
uint8_t grade;
uint8_t clear_and_unlock_state;
uint32_t score_total;
uint32_t play_count;
uint32_t null_padding;
uint32_t song_id;
uint8_t difficulty;
uint8_t mode;
uint8_t grade;
uint8_t clear_and_unlock_state;
uint32_t score_total;
uint32_t play_count;
uint32_t null_padding;
} __attribute__((__packed__));
struct asset_f2_usb_save {
/* start offset: 0x00 */
struct asset_f2_usb_save_header header;
/* start offset: 0x120 */
struct asset_f2_usb_save_machine_info machine_info;
struct asset_f2_usb_save_machine_stats machine_stats;
/* start offset: 0x2F0 */
/* start offset: 0x00 */
struct asset_f2_usb_save_header header;
/* start offset: 0x120 */
struct asset_f2_usb_save_machine_info machine_info;
struct asset_f2_usb_save_machine_stats machine_stats;
/* start offset: 0x2F0 */
// TODO continue
// TODO continue
} __attribute__((__packed__));
struct asset_f2_usb_save* asset_f2_usb_save_new(void);
struct asset_f2_usb_save *asset_f2_usb_save_new(void);
// update checksum and prepare profile to get encrypted
void asset_f2_usb_save_finalize(struct asset_f2_usb_save* save);
void asset_f2_usb_save_finalize(struct asset_f2_usb_save *save);
char* asset_f2_usb_save_to_string(const struct asset_f2_usb_save* save);
char *asset_f2_usb_save_to_string(const struct asset_f2_usb_save *save);
void asset_f2_usb_save_decrypt(uint8_t* buf, size_t len);
void asset_f2_usb_save_decrypt(uint8_t *buf, size_t len);
void asset_f2_usb_save_encrypt(uint8_t* buf, size_t len);
void asset_f2_usb_save_encrypt(uint8_t *buf, size_t len);
#endif
+70 -60
View File
@@ -7,90 +7,100 @@
#include "util.h"
struct asset_f2_usb_rank* asset_f2_util_rank_usb_load_from_file(const char* path, bool encrypted)
struct asset_f2_usb_rank *
asset_f2_util_rank_usb_load_from_file(const char *path, bool encrypted)
{
struct asset_f2_usb_rank* rank;
size_t size;
struct asset_f2_usb_rank *rank;
size_t size;
if (!util_file_load(path, (void**) &rank, &size, false)) {
log_error("Loading f2 rank file %s failed", path);
return NULL;
}
if (!util_file_load(path, (void **) &rank, &size, false)) {
log_error("Loading f2 rank file %s failed", path);
return NULL;
}
if (size != sizeof(struct asset_f2_usb_rank)) {
log_error("Invalid size of f2 rank file %s: %d != %d", path, size,
sizeof(struct asset_f2_usb_rank));
free(rank);
return NULL;
}
if (size != sizeof(struct asset_f2_usb_rank)) {
log_error(
"Invalid size of f2 rank file %s: %d != %d",
path,
size,
sizeof(struct asset_f2_usb_rank));
free(rank);
return NULL;
}
if (encrypted) {
asset_f2_usb_rank_decrypt((uint8_t*) rank, size);
}
if (encrypted) {
asset_f2_usb_rank_decrypt((uint8_t *) rank, size);
}
return rank;
return rank;
}
bool asset_f2_util_rank_usb_save_to_file(const char* path, const struct asset_f2_usb_rank* rank, bool encrypt)
bool asset_f2_util_rank_usb_save_to_file(
const char *path, const struct asset_f2_usb_rank *rank, bool encrypt)
{
struct asset_f2_usb_rank rank_enc;
struct asset_f2_usb_rank rank_enc;
memcpy(&rank_enc, rank, sizeof(struct asset_f2_usb_rank));
memcpy(&rank_enc, rank, sizeof(struct asset_f2_usb_rank));
if (encrypt) {
asset_f2_usb_rank_encrypt((uint8_t*) &rank_enc,
sizeof(struct asset_f2_usb_rank));
}
if (encrypt) {
asset_f2_usb_rank_encrypt(
(uint8_t *) &rank_enc, sizeof(struct asset_f2_usb_rank));
}
if (!util_file_save(path, (void**) &rank_enc,
sizeof(struct asset_f2_usb_rank))) {
log_error("Storing f2 rank data to %s failed", path);
return false;
}
if (!util_file_save(
path, (void **) &rank_enc, sizeof(struct asset_f2_usb_rank))) {
log_error("Storing f2 rank data to %s failed", path);
return false;
}
return true;
return true;
}
struct asset_f2_usb_save* asset_f2_util_usb_save_load_from_file(const char* path, bool encrypted)
struct asset_f2_usb_save *
asset_f2_util_usb_save_load_from_file(const char *path, bool encrypted)
{
struct asset_f2_usb_save* save;
size_t size;
struct asset_f2_usb_save *save;
size_t size;
if (!util_file_load(path, (void**) &save, &size, false)) {
log_error("Loading f2 save file %s failed", path);
return NULL;
}
if (!util_file_load(path, (void **) &save, &size, false)) {
log_error("Loading f2 save file %s failed", path);
return NULL;
}
if (size != sizeof(struct asset_f2_usb_save)) {
log_error("Invalid size of f2 save file %s: %d != %d", path, size,
sizeof(struct asset_f2_usb_save));
free(save);
return NULL;
}
if (size != sizeof(struct asset_f2_usb_save)) {
log_error(
"Invalid size of f2 save file %s: %d != %d",
path,
size,
sizeof(struct asset_f2_usb_save));
free(save);
return NULL;
}
if (encrypted) {
asset_f2_usb_save_decrypt((uint8_t*) save, size);
}
if (encrypted) {
asset_f2_usb_save_decrypt((uint8_t *) save, size);
}
return save;
return save;
}
bool asset_f2_util_usb_save_save_to_file(const char* path, const struct asset_f2_usb_save* save, bool encrypt)
bool asset_f2_util_usb_save_save_to_file(
const char *path, const struct asset_f2_usb_save *save, bool encrypt)
{
struct asset_f2_usb_save save_enc;
struct asset_f2_usb_save save_enc;
memcpy(&save_enc, save, sizeof(struct asset_f2_usb_save));
memcpy(&save_enc, save, sizeof(struct asset_f2_usb_save));
if (encrypt) {
asset_f2_usb_save_encrypt((uint8_t*) &save_enc,
sizeof(struct asset_f2_usb_save));
}
if (encrypt) {
asset_f2_usb_save_encrypt(
(uint8_t *) &save_enc, sizeof(struct asset_f2_usb_save));
}
if (!util_file_save(path, (const void*) &save_enc,
sizeof(struct asset_f2_usb_save))) {
log_error("Storing f2 save data to %s failed", path);
return false;
}
if (!util_file_save(
path, (const void *) &save_enc, sizeof(struct asset_f2_usb_save))) {
log_error("Storing f2 save data to %s failed", path);
return false;
}
return true;
return true;
}
+8 -4
View File
@@ -7,15 +7,19 @@
#include "usb-save.h"
// load from file and decrypt, returns decrypted struct
struct asset_f2_usb_rank* asset_f2_util_usb_rank_load_from_file(const char* path, bool encrypted);
struct asset_f2_usb_rank *
asset_f2_util_usb_rank_load_from_file(const char *path, bool encrypted);
// takes decrypted rank data, encrypts it and writes it to file
bool asset_f2_util_usb_rank_save_to_file(const char* path, const struct asset_f2_usb_rank* rank, bool encrypt);
bool asset_f2_util_usb_rank_save_to_file(
const char *path, const struct asset_f2_usb_rank *rank, bool encrypt);
// load from file and decrypt, returns decrypted struct
struct asset_f2_usb_save* asset_f2_util_usb_save_load_from_file(const char* path, bool encrypted);
struct asset_f2_usb_save *
asset_f2_util_usb_save_load_from_file(const char *path, bool encrypted);
// takes decrypted save data, encrypts it and writes it to file
bool asset_f2_util_usb_save_save_to_file(const char* path, const struct asset_f2_usb_save* save, bool encrypt);
bool asset_f2_util_usb_save_save_to_file(
const char *path, const struct asset_f2_usb_save *save, bool encrypt);
#endif
+13 -14
View File
@@ -2,31 +2,30 @@
#include "usb-rank.h"
struct asset_fex_usb_rank* asset_fex_usb_rank_new(void)
struct asset_fex_usb_rank *asset_fex_usb_rank_new(void)
{
return malloc(sizeof(struct asset_fex_usb_rank));
return malloc(sizeof(struct asset_fex_usb_rank));
}
void asset_fex_usb_rank_finalize(struct asset_fex_usb_rank* rank)
void asset_fex_usb_rank_finalize(struct asset_fex_usb_rank *rank)
{
}
char* asset_fex_usb_rank_to_string(const struct asset_fex_usb_rank* rank)
char *asset_fex_usb_rank_to_string(const struct asset_fex_usb_rank *rank)
{
return malloc(0);
return malloc(0);
}
void asset_fex_usb_rank_decrypt(uint8_t* buf, size_t len)
void asset_fex_usb_rank_decrypt(uint8_t *buf, size_t len)
{
for (size_t a = len - 1; a > 0; --a) {
buf[a] = (buf[a] ^ buf[a - 1]) + ((a * 1234567) >> 8);
}
for (size_t a = len - 1; a > 0; --a) {
buf[a] = (buf[a] ^ buf[a - 1]) + ((a * 1234567) >> 8);
}
}
void asset_fex_usb_rank_encrypt(uint8_t* buf, size_t len)
void asset_fex_usb_rank_encrypt(uint8_t *buf, size_t len)
{
for (size_t a = 1; a < len; ++a) {
buf[a] = (buf[a] - ((a * 1234567) >> 8)) ^ buf[a - 1];
}
for (size_t a = 1; a < len; ++a) {
buf[a] = (buf[a] - ((a * 1234567) >> 8)) ^ buf[a - 1];
}
}
+9 -9
View File
@@ -5,24 +5,24 @@
#include <stdlib.h>
struct asset_fex_usb_rank_header {
uint32_t adler32;
/* NULL terminated */
char player_id[8];
uint32_t adler32;
/* NULL terminated */
char player_id[8];
} __attribute__((__packed__));
struct asset_fex_usb_rank {
struct asset_fex_usb_rank_header header;
struct asset_fex_usb_rank_header header;
} __attribute__((__packed__));
struct asset_fex_usb_rank* asset_fex_usb_rank_new(void);
struct asset_fex_usb_rank *asset_fex_usb_rank_new(void);
// update checksum and prepare profile to get encrypted
void asset_fex_usb_rank_finalize(struct asset_fex_usb_rank* rank);
void asset_fex_usb_rank_finalize(struct asset_fex_usb_rank *rank);
char* asset_fex_usb_rank_to_string(const struct asset_fex_usb_rank* rank);
char *asset_fex_usb_rank_to_string(const struct asset_fex_usb_rank *rank);
void asset_fex_usb_rank_decrypt(uint8_t* buf, size_t len);
void asset_fex_usb_rank_decrypt(uint8_t *buf, size_t len);
void asset_fex_usb_rank_encrypt(uint8_t* buf, size_t len);
void asset_fex_usb_rank_encrypt(uint8_t *buf, size_t len);
#endif
+257 -278
View File
@@ -7,333 +7,312 @@
#include "usb-save.h"
static char* fex_profile_save_header_to_string(
const struct asset_fex_usb_save_header* header)
static char *fex_profile_save_header_to_string(
const struct asset_fex_usb_save_header *header)
{
char* buffer;
char *buffer;
buffer = (char*) util_xmalloc(256);
memset(buffer, 0, 256);
buffer = (char *) util_xmalloc(256);
memset(buffer, 0, 256);
util_str_format(buffer, 256,
"-------------- header --------------\n"
"adler32: %X\n"
"usb_serial: %s\n"
"dongle_serial: %X\n",
header->adler32,
header->usb_serial,
header->dongle_serial);
util_str_format(
buffer,
256,
"-------------- header --------------\n"
"adler32: %X\n"
"usb_serial: %s\n"
"dongle_serial: %X\n",
header->adler32,
header->usb_serial,
header->dongle_serial);
return buffer;
return buffer;
}
static char* fex_profile_save_player_to_string(
const struct asset_fex_usb_save_player* player)
static char *fex_profile_save_player_to_string(
const struct asset_fex_usb_save_player *player)
{
char* buffer;
char *buffer;
buffer = (char*) util_xmalloc(1024);
memset(buffer, 0, 1024);
buffer = (char *) util_xmalloc(1024);
memset(buffer, 0, 1024);
util_str_format(buffer, 1024,
"-------------- player --------------\n"
"unkn: %X\n"
"unkn2: %X\n"
"avatar_id: %d\n"
"player_lvl: %d\n"
"unkn3: %X\n"
"player_id: %s\n"
"unkn4: %X\n"
"unkn5: %X\n"
"unkn6: %X\n"
"unkn7: %X\n"
"unkn8: %X\n"
"unkn9: %X\n"
"unkn10: %X\n"
"unkn11: %X\n"
"unkn12: %X\n"
"unkn13: %X\n"
"unkn14: %X\n"
"unkn15: %X\n"
"total_step: %d\n"
"play_count: %d\n"
"exp: %d\n"
"num_quest_world_passed: %d\n"
"unkn16: %X\n"
"arcade_score: %d\n"
"num_battle_wins: %d\n"
"num_battle_loss: %d\n"
"num_battle_draw: %d\n",
player->unkn,
player->unkn2,
player->avatar_id,
player->player_lvl,
player->unkn3,
player->player_id,
player->unkn4,
player->unkn5,
player->unkn6,
player->unkn7,
player->unkn8,
player->unkn9,
player->unkn10,
player->unkn11,
player->unkn12,
player->unkn13,
player->unkn14,
player->unkn15,
player->total_step,
player->play_count,
player->exp,
player->num_quest_world_passed,
player->unkn16,
player->arcade_score,
player->num_battle_wins,
player->num_battle_loss,
player->num_battle_draw);
util_str_format(
buffer,
1024,
"-------------- player --------------\n"
"unkn: %X\n"
"unkn2: %X\n"
"avatar_id: %d\n"
"player_lvl: %d\n"
"unkn3: %X\n"
"player_id: %s\n"
"unkn4: %X\n"
"unkn5: %X\n"
"unkn6: %X\n"
"unkn7: %X\n"
"unkn8: %X\n"
"unkn9: %X\n"
"unkn10: %X\n"
"unkn11: %X\n"
"unkn12: %X\n"
"unkn13: %X\n"
"unkn14: %X\n"
"unkn15: %X\n"
"total_step: %d\n"
"play_count: %d\n"
"exp: %d\n"
"num_quest_world_passed: %d\n"
"unkn16: %X\n"
"arcade_score: %d\n"
"num_battle_wins: %d\n"
"num_battle_loss: %d\n"
"num_battle_draw: %d\n",
player->unkn,
player->unkn2,
player->avatar_id,
player->player_lvl,
player->unkn3,
player->player_id,
player->unkn4,
player->unkn5,
player->unkn6,
player->unkn7,
player->unkn8,
player->unkn9,
player->unkn10,
player->unkn11,
player->unkn12,
player->unkn13,
player->unkn14,
player->unkn15,
player->total_step,
player->play_count,
player->exp,
player->num_quest_world_passed,
player->unkn16,
player->arcade_score,
player->num_battle_wins,
player->num_battle_loss,
player->num_battle_draw);
return buffer;
return buffer;
}
static char* fex_profile_save_mods_to_string(
const struct asset_fex_usb_save_player_mods* mods)
static char *fex_profile_save_mods_to_string(
const struct asset_fex_usb_save_player_mods *mods)
{
char* buffer;
char *buffer;
buffer = (char*) util_xmalloc(128);
memset(buffer, 0, 128);
buffer = (char *) util_xmalloc(128);
memset(buffer, 0, 128);
util_str_format(buffer, 128,
"-------------- modifiers --------------\n"
"modifiers: %X\n"
"half_speed_mod: %X\n"
"noteskin: %X\n",
mods->modifiers,
mods->half_speed_mod,
mods->noteskin);
util_str_format(
buffer,
128,
"-------------- modifiers --------------\n"
"modifiers: %X\n"
"half_speed_mod: %X\n"
"noteskin: %X\n",
mods->modifiers,
mods->half_speed_mod,
mods->noteskin);
return buffer;
return buffer;
}
static char* fex_profile_save_mod_unlocks_to_string(
const struct asset_fex_usb_save_mod_unlocks* unlocks)
static char *fex_profile_save_mod_unlocks_to_string(
const struct asset_fex_usb_save_mod_unlocks *unlocks)
{
char* merged;
char* buffer;
char* tmp;
const size_t buf_size = 512;
char *merged;
char *buffer;
char *tmp;
const size_t buf_size = 512;
merged = (char*) util_xmalloc(buf_size);
memset(merged, 0, buf_size);
merged = (char *) util_xmalloc(buf_size);
memset(merged, 0, buf_size);
buffer = (char*) util_xmalloc(buf_size);
memset(buffer, 0, buf_size);
buffer = (char *) util_xmalloc(buf_size);
memset(buffer, 0, buf_size);
util_str_format(buffer, buf_size,
"-------------- mod unlocks --------------\n" );
util_str_format(
buffer, buf_size, "-------------- mod unlocks --------------\n");
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
for (uint32_t i = 0; i < 0x12; i++) {
util_str_format(buffer, buf_size, "unkn0[%d]: %d\n", i, unlocks->unkn0[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < 0x12; i++) {
util_str_format(buffer, buf_size,
"unkn0[%d]: %d\n",
i,
unlocks->unkn0[i]);
util_str_format(buffer, buf_size, "display_va: %d\n", unlocks->display_va);
tmp = util_str_merge(merged, buffer);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
free(merged);
merged = tmp;
}
util_str_format(buffer, buf_size,
"display_va: %d\n",
unlocks->display_va);
for (uint32_t i = 0; i < 0x0D; i++) {
util_str_format(buffer, buf_size, "unkn1[%d]: %d\n", i, unlocks->unkn1[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < 0x0D; i++) {
util_str_format(buffer, buf_size,
"unkn1[%d]: %d\n",
i,
unlocks->unkn1[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < 0x10; i++) {
util_str_format(buffer, buf_size,
"noteskins[%d]: %d\n",
i,
unlocks->noteskins[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < 0x04; i++) {
util_str_format(buffer, buf_size,
"unkn2[%d]: %d\n",
i,
unlocks->unkn2[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < 0x03; i++) {
util_str_format(buffer, buf_size,
"path[%d]: %d\n",
i,
unlocks->path[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < 0x06; i++) {
util_str_format(buffer, buf_size,
"unkn3[%d]: %d\n",
i,
unlocks->unkn3[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
util_str_format(buffer, buf_size,
"xj: %d\n",
unlocks->xj);
for (uint32_t i = 0; i < 0x10; i++) {
util_str_format(
buffer, buf_size, "noteskins[%d]: %d\n", i, unlocks->noteskins[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < 0x02; i++) {
util_str_format(buffer, buf_size,
"system[%d]: %d\n",
i,
unlocks->system[i]);
for (uint32_t i = 0; i < 0x04; i++) {
util_str_format(buffer, buf_size, "unkn2[%d]: %d\n", i, unlocks->unkn2[i]);
tmp = util_str_merge(merged, buffer);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < 0x08; i++) {
util_str_format(buffer, buf_size,
"rush[%d]: %d\n",
i,
unlocks->rush[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < 0x1A; i++) {
util_str_format(buffer, buf_size,
"unkn4[%d]: %d\n",
i,
unlocks->unkn4[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
return merged;
}
static char* fex_profile_save_mission_state_to_string(
const struct asset_fex_usb_save_mission_state* state)
{
char* buffer;
buffer = (char*) util_xmalloc(128);
memset(buffer, 0, 128);
util_str_format(buffer, 128,
"-------------- mission state --------------\n"
"quest_world_location: %X\n"
"skill_up_zone_location: %X\n",
state->quest_world_location,
state->skill_up_zone_location);
return buffer;
}
struct asset_fex_usb_save* asset_fex_usb_save_new(void)
{
return malloc(sizeof(struct asset_fex_usb_save));
}
void asset_fex_usb_save_finalize(struct asset_fex_usb_save* save)
{
}
char* asset_fex_usb_save_to_string(const struct asset_fex_usb_save* save)
{
char* header;
char* player;
char* mods;
char* unlocks;
char* mission_state;
char* merged;
char* merged2;
header = fex_profile_save_header_to_string(&save->header);
player = fex_profile_save_player_to_string(&save->player);
mods = fex_profile_save_mods_to_string(&save->mods);
unlocks = fex_profile_save_mod_unlocks_to_string(&save->mod_unlocks);
mission_state = fex_profile_save_mission_state_to_string(&save->mission_state);
merged = util_str_merge(header, player);
merged2 = util_str_merge(merged, mods);
free(merged);
merged = util_str_merge(merged2, unlocks);
free(merged2);
merged2 = util_str_merge(merged, mission_state);
merged = tmp;
}
for (uint32_t i = 0; i < 0x03; i++) {
util_str_format(buffer, buf_size, "path[%d]: %d\n", i, unlocks->path[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
free(header);
free(player);
free(mods);
free(unlocks);
free(mission_state);
for (uint32_t i = 0; i < 0x06; i++) {
util_str_format(buffer, buf_size, "unkn3[%d]: %d\n", i, unlocks->unkn3[i]);
return merged2;
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
util_str_format(buffer, buf_size, "xj: %d\n", unlocks->xj);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
for (uint32_t i = 0; i < 0x02; i++) {
util_str_format(
buffer, buf_size, "system[%d]: %d\n", i, unlocks->system[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < 0x08; i++) {
util_str_format(buffer, buf_size, "rush[%d]: %d\n", i, unlocks->rush[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < 0x1A; i++) {
util_str_format(buffer, buf_size, "unkn4[%d]: %d\n", i, unlocks->unkn4[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
return merged;
}
void asset_fex_usb_save_decrypt(uint8_t* buf, size_t len)
static char *fex_profile_save_mission_state_to_string(
const struct asset_fex_usb_save_mission_state *state)
{
for (size_t a = len - 1; a > 0; --a) {
buf[a] = (buf[a] ^ buf[a - 1]) + ((a * 1234567) >> 8);
}
char *buffer;
buffer = (char *) util_xmalloc(128);
memset(buffer, 0, 128);
util_str_format(
buffer,
128,
"-------------- mission state --------------\n"
"quest_world_location: %X\n"
"skill_up_zone_location: %X\n",
state->quest_world_location,
state->skill_up_zone_location);
return buffer;
}
void asset_fex_usb_save_encrypt(uint8_t* buf, size_t len)
struct asset_fex_usb_save *asset_fex_usb_save_new(void)
{
for (size_t a = 1; a < len; ++a) {
buf[a] = (buf[a] - ((a * 1234567) >> 8)) ^ buf[a - 1];
}
return malloc(sizeof(struct asset_fex_usb_save));
}
void asset_fex_usb_save_finalize(struct asset_fex_usb_save *save)
{
}
char *asset_fex_usb_save_to_string(const struct asset_fex_usb_save *save)
{
char *header;
char *player;
char *mods;
char *unlocks;
char *mission_state;
char *merged;
char *merged2;
header = fex_profile_save_header_to_string(&save->header);
player = fex_profile_save_player_to_string(&save->player);
mods = fex_profile_save_mods_to_string(&save->mods);
unlocks = fex_profile_save_mod_unlocks_to_string(&save->mod_unlocks);
mission_state =
fex_profile_save_mission_state_to_string(&save->mission_state);
merged = util_str_merge(header, player);
merged2 = util_str_merge(merged, mods);
free(merged);
merged = util_str_merge(merged2, unlocks);
free(merged2);
merged2 = util_str_merge(merged, mission_state);
free(merged);
free(header);
free(player);
free(mods);
free(unlocks);
free(mission_state);
return merged2;
}
void asset_fex_usb_save_decrypt(uint8_t *buf, size_t len)
{
for (size_t a = len - 1; a > 0; --a) {
buf[a] = (buf[a] ^ buf[a - 1]) + ((a * 1234567) >> 8);
}
}
void asset_fex_usb_save_encrypt(uint8_t *buf, size_t len)
{
for (size_t a = 1; a < len; ++a) {
buf[a] = (buf[a] - ((a * 1234567) >> 8)) ^ buf[a - 1];
}
}
+152 -152
View File
@@ -5,187 +5,187 @@
#include <stdlib.h>
enum asset_fex_usb_save_noteskins {
ASSET_FEX_USB_SAVE_SKIN_DEFAULT = 0x00,
ASSET_FEX_USB_SAVE_SKIN_HANAFUDA = 0x01,
ASSET_FEX_USB_SAVE_SKIN_CLASSIC = 0x02,
ASSET_FEX_USB_SAVE_SKIN_CANDY = 0x03,
ASSET_FEX_USB_SAVE_SKIN_PORING = 0x04,
ASSET_FEX_USB_SAVE_SKIN_MUSICAL_NOTES = 0x05,
ASSET_FEX_USB_SAVE_SKIN_CANON_D = 0x06,
ASSET_FEX_USB_SAVE_SKIN_PLAYING_CARDS = 0x07,
ASSET_FEX_USB_SAVE_SKIN_NX = 0x08,
ASSET_FEX_USB_SAVE_SKIN_DIGNITY = 0x09,
ASSET_FEX_USB_SAVE_SKIN_HORSE_HEAD = 0x0A,
ASSET_FEX_USB_SAVE_SKIN_DOG = 0x0B,
ASSET_FEX_USB_SAVE_SKIN_GIRL = 0x0C,
ASSET_FEX_USB_SAVE_SKIN_FIRE = 0x0D,
ASSET_FEX_USB_SAVE_SKIN_ICE = 0x0E,
ASSET_FEX_USB_SAVE_SKIN_WIND = 0x0F,
ASSET_FEX_USB_SAVE_SKIN_RED_DP = 0x10,
ASSET_FEX_USB_SAVE_SKIN_BLUE_DP = 0x11,
ASSET_FEX_USB_SAVE_SKIN_YELLOW_DP = 0x12,
ASSET_FEX_USB_SAVE_SKIN_NXA = 0x13,
ASSET_FEX_USB_SAVE_SKIN_NX2 = 0x14,
ASSET_FEX_USB_SAVE_SKIN_ELECTRIC_FIESTA = 0x15,
ASSET_FEX_USB_SAVE_SKIN_DRUM = 0x16,
ASSET_FEX_USB_SAVE_SKIN_BULLET = 0x17,
ASSET_FEX_USB_SAVE_SKIN_BLUE_DRUM = 0x18,
ASSET_FEX_USB_SAVE_SKIN_RED_DRUM = 0x19,
ASSET_FEX_USB_SAVE_SKIN_YELLOW_DRUM = 0x1A,
ASSET_FEX_USB_SAVE_SKIN_WORLD_CUP = 0x1B,
ASSET_FEX_USB_SAVE_SKIN_PREX3 = 0x1C,
ASSET_FEX_USB_SAVE_SKIN_FIESTA_BASIC = 0x1D,
ASSET_FEX_USB_SAVE_SKIN_DEFAULT = 0x00,
ASSET_FEX_USB_SAVE_SKIN_HANAFUDA = 0x01,
ASSET_FEX_USB_SAVE_SKIN_CLASSIC = 0x02,
ASSET_FEX_USB_SAVE_SKIN_CANDY = 0x03,
ASSET_FEX_USB_SAVE_SKIN_PORING = 0x04,
ASSET_FEX_USB_SAVE_SKIN_MUSICAL_NOTES = 0x05,
ASSET_FEX_USB_SAVE_SKIN_CANON_D = 0x06,
ASSET_FEX_USB_SAVE_SKIN_PLAYING_CARDS = 0x07,
ASSET_FEX_USB_SAVE_SKIN_NX = 0x08,
ASSET_FEX_USB_SAVE_SKIN_DIGNITY = 0x09,
ASSET_FEX_USB_SAVE_SKIN_HORSE_HEAD = 0x0A,
ASSET_FEX_USB_SAVE_SKIN_DOG = 0x0B,
ASSET_FEX_USB_SAVE_SKIN_GIRL = 0x0C,
ASSET_FEX_USB_SAVE_SKIN_FIRE = 0x0D,
ASSET_FEX_USB_SAVE_SKIN_ICE = 0x0E,
ASSET_FEX_USB_SAVE_SKIN_WIND = 0x0F,
ASSET_FEX_USB_SAVE_SKIN_RED_DP = 0x10,
ASSET_FEX_USB_SAVE_SKIN_BLUE_DP = 0x11,
ASSET_FEX_USB_SAVE_SKIN_YELLOW_DP = 0x12,
ASSET_FEX_USB_SAVE_SKIN_NXA = 0x13,
ASSET_FEX_USB_SAVE_SKIN_NX2 = 0x14,
ASSET_FEX_USB_SAVE_SKIN_ELECTRIC_FIESTA = 0x15,
ASSET_FEX_USB_SAVE_SKIN_DRUM = 0x16,
ASSET_FEX_USB_SAVE_SKIN_BULLET = 0x17,
ASSET_FEX_USB_SAVE_SKIN_BLUE_DRUM = 0x18,
ASSET_FEX_USB_SAVE_SKIN_RED_DRUM = 0x19,
ASSET_FEX_USB_SAVE_SKIN_YELLOW_DRUM = 0x1A,
ASSET_FEX_USB_SAVE_SKIN_WORLD_CUP = 0x1B,
ASSET_FEX_USB_SAVE_SKIN_PREX3 = 0x1C,
ASSET_FEX_USB_SAVE_SKIN_FIESTA_BASIC = 0x1D,
};
struct asset_fex_usb_save_header {
/* 0x00 */
uint32_t adler32;
/* 0x04: NULL terminated */
char usb_serial[0x40];
/* 0x44: Deprecated from old games */
uint32_t dongle_serial;
/* 0x00 */
uint32_t adler32;
/* 0x04: NULL terminated */
char usb_serial[0x40];
/* 0x44: Deprecated from old games */
uint32_t dongle_serial;
} __attribute__((__packed__));
struct asset_fex_usb_save_player {
/* 0x48 */
uint32_t unkn;
/* 0x4C */
uint32_t unkn2;
/* 0x50 */
uint8_t avatar_id;
/* 0x51: Range: 0x00 - 0x21 */
uint8_t player_lvl;
/* 0x52: PumBi sets it to 0xC4 */
uint16_t unkn3;
/* 0x54: NULL terminated */
char player_id[8];
/* 0x5C */
uint32_t unkn4;
/* 0x60 */
uint32_t unkn5;
/* 0x64: Each time you save, it inc. by 6... */
uint32_t unkn6;
/* 0x68 */
uint32_t unkn7;
/* 0x6C */
uint32_t unkn8;
/* 0x70 */
uint32_t unkn9;
/* 0x74 */
uint32_t unkn10;
/* 0x78 */
uint32_t unkn11;
/* 0x7C */
uint32_t unkn12;
/* 0x80 */
uint32_t unkn13;
/* 0x84 */
uint32_t unkn14;
/* 0x88 */
uint32_t unkn15;
/* 0x8C */
uint32_t total_step;
/* 0x90 */
uint32_t play_count;
/* 0x94 */
uint32_t exp;
/* 0x98 */
uint32_t num_quest_world_passed;
/* 0x9C */
uint32_t unkn16;
/* 0xA0 */
uint32_t arcade_score;
/* 0xA8 */
uint32_t num_battle_wins;
/* 0xAC */
uint32_t num_battle_loss;
/* 0xB0 */
uint32_t num_battle_draw;
/* 0x48 */
uint32_t unkn;
/* 0x4C */
uint32_t unkn2;
/* 0x50 */
uint8_t avatar_id;
/* 0x51: Range: 0x00 - 0x21 */
uint8_t player_lvl;
/* 0x52: PumBi sets it to 0xC4 */
uint16_t unkn3;
/* 0x54: NULL terminated */
char player_id[8];
/* 0x5C */
uint32_t unkn4;
/* 0x60 */
uint32_t unkn5;
/* 0x64: Each time you save, it inc. by 6... */
uint32_t unkn6;
/* 0x68 */
uint32_t unkn7;
/* 0x6C */
uint32_t unkn8;
/* 0x70 */
uint32_t unkn9;
/* 0x74 */
uint32_t unkn10;
/* 0x78 */
uint32_t unkn11;
/* 0x7C */
uint32_t unkn12;
/* 0x80 */
uint32_t unkn13;
/* 0x84 */
uint32_t unkn14;
/* 0x88 */
uint32_t unkn15;
/* 0x8C */
uint32_t total_step;
/* 0x90 */
uint32_t play_count;
/* 0x94 */
uint32_t exp;
/* 0x98 */
uint32_t num_quest_world_passed;
/* 0x9C */
uint32_t unkn16;
/* 0xA0 */
uint32_t arcade_score;
/* 0xA8 */
uint32_t num_battle_wins;
/* 0xAC */
uint32_t num_battle_loss;
/* 0xB0 */
uint32_t num_battle_draw;
} __attribute__((__packed__));
struct asset_fex_usb_save_player_mods {
/* 0xB4: The first set of saved modifiers (see MOD_1 below) */
uint32_t modifiers;
/* 0xB8: If the +0.5x mod is enabled (boolean) */
uint32_t half_speed_mod;
/* 0xBC: Which noteskin is currently selected (see NOTE_S below) */
uint32_t noteskin;
/* 0xB4: The first set of saved modifiers (see MOD_1 below) */
uint32_t modifiers;
/* 0xB8: If the +0.5x mod is enabled (boolean) */
uint32_t half_speed_mod;
/* 0xBC: Which noteskin is currently selected (see NOTE_S below) */
uint32_t noteskin;
} __attribute__((__packed__));
struct asset_fex_usb_save_mod_unlocks {
/* 0xC0: Unknown Unlocks Area */
uint8_t unkn0[0x12];
/* 0xD2: Boolean for unlocking VA Mod. */
uint8_t display_va;
/* 0xD3: Unknown Unlocks Area */
uint8_t unkn1[0x0D];
/* 0xE0: Array of bools - Which Noteskins are Unlocked. */
uint8_t noteskins[0x10];
/* 0xF0: Unknown Unlocks Area */
uint8_t unkn2[0x04];
/* 0xF4: Array of bools - Which Path Mods are Unlocked. */
uint8_t path[0x03];
/* 0xF7: Unknown Unlocks Area */
uint8_t unkn3[0x06];
/* 0xFE: Boolean for unlocking XJ */
uint8_t xj;
/* 0x100: Array of bools - Which System Mods are Unlocked. */
uint8_t system[0x02];
/* 0x102: Array of bools - Which Rush/NOT Modes are Unlocked. */
uint8_t rush[0x08];
/* 0x10A: Unknown Unlocks Area */
uint8_t unkn4[0x1A];
/* 0xC0: Unknown Unlocks Area */
uint8_t unkn0[0x12];
/* 0xD2: Boolean for unlocking VA Mod. */
uint8_t display_va;
/* 0xD3: Unknown Unlocks Area */
uint8_t unkn1[0x0D];
/* 0xE0: Array of bools - Which Noteskins are Unlocked. */
uint8_t noteskins[0x10];
/* 0xF0: Unknown Unlocks Area */
uint8_t unkn2[0x04];
/* 0xF4: Array of bools - Which Path Mods are Unlocked. */
uint8_t path[0x03];
/* 0xF7: Unknown Unlocks Area */
uint8_t unkn3[0x06];
/* 0xFE: Boolean for unlocking XJ */
uint8_t xj;
/* 0x100: Array of bools - Which System Mods are Unlocked. */
uint8_t system[0x02];
/* 0x102: Array of bools - Which Rush/NOT Modes are Unlocked. */
uint8_t rush[0x08];
/* 0x10A: Unknown Unlocks Area */
uint8_t unkn4[0x1A];
} __attribute__((__packed__));
struct asset_fex_usb_save_mission_state {
/* 0x124 */
uint32_t quest_world_location;
/* 0x128 */
uint32_t skill_up_zone_location;
/* 0x124 */
uint32_t quest_world_location;
/* 0x128 */
uint32_t skill_up_zone_location;
} __attribute__((__packed__));
struct asset_fex_usb_save {
struct asset_fex_usb_save_header header;
struct asset_fex_usb_save_player player;
struct asset_fex_usb_save_player_mods mods;
struct asset_fex_usb_save_mod_unlocks mod_unlocks;
struct asset_fex_usb_save_mission_state mission_state;
struct asset_fex_usb_save_header header;
struct asset_fex_usb_save_player player;
struct asset_fex_usb_save_player_mods mods;
struct asset_fex_usb_save_mod_unlocks mod_unlocks;
struct asset_fex_usb_save_mission_state mission_state;
/* Not verified, yet. just notes from old tools */
/* Not verified, yet. just notes from old tools */
/* 0x17AD (0x0A): Quest world inventory */
/* 0x17B7: ??? */
/* 0x17B8 (0x1C): Quest world warp unlocks */
/* 0x17AD (0x0A): Quest world inventory */
/* 0x17B7: ??? */
/* 0x17B8 (0x1C): Quest world warp unlocks */
/* 0x17AC (0x11): QW inventory */
/* 0x17AC (0x11): QW inventory */
/* 0x17D4 or 0x17D5 ? (0x14): favorites channel */
/* 0x2E48 - 0x1A5EF: step chart blacklist */
/* 0x2E48 - 0x1A5EF: step chart unlocks = blacklist */
/* 0x17D4 or 0x17D5 ? (0x14): favorites channel */
/* 0x2E48 - 0x1A5EF: step chart blacklist */
/* 0x2E48 - 0x1A5EF: step chart unlocks = blacklist */
/* pumbi stepcharts */
/* 0x6047: pumbi stepchart 1009 Level S15 */
/* 0x6083 */
/* 0x60AB */
/* 0x647F */
/* 0x64BB */
/* 0x64CF */
/* 0x650B */
/* 0x6533 */
/* 0x655B */
/* 0x65AB */
/* 0x660F */
/* pumbi stepcharts */
/* 0x6047: pumbi stepchart 1009 Level S15 */
/* 0x6083 */
/* 0x60AB */
/* 0x647F */
/* 0x64BB */
/* 0x64CF */
/* 0x650B */
/* 0x6533 */
/* 0x655B */
/* 0x65AB */
/* 0x660F */
} __attribute__((__packed__));
struct asset_fex_usb_save* asset_fex_usb_save_new(void);
struct asset_fex_usb_save *asset_fex_usb_save_new(void);
// update checksum and prepare profile to get encrypted
void asset_fex_usb_save_finalize(struct asset_fex_usb_save* save);
void asset_fex_usb_save_finalize(struct asset_fex_usb_save *save);
char* asset_fex_usb_save_to_string(const struct asset_fex_usb_save* save);
char *asset_fex_usb_save_to_string(const struct asset_fex_usb_save *save);
void asset_fex_usb_save_decrypt(uint8_t* buf, size_t len);
void asset_fex_usb_save_decrypt(uint8_t *buf, size_t len);
void asset_fex_usb_save_encrypt(uint8_t* buf, size_t len);
void asset_fex_usb_save_encrypt(uint8_t *buf, size_t len);
#endif
+64 -64
View File
@@ -7,94 +7,94 @@
#include "util.h"
struct asset_fex_usb_rank* asset_fex_usb_rank_load_from_file(const char* path,
bool encrypted)
struct asset_fex_usb_rank *
asset_fex_usb_rank_load_from_file(const char *path, bool encrypted)
{
struct asset_fex_usb_rank* rank;
size_t size;
struct asset_fex_usb_rank *rank;
size_t size;
if (!util_file_load(path, (void**) &rank, &size, false)) {
log_error("Loading fex rank file %s failed", path);
return NULL;
}
if (!util_file_load(path, (void **) &rank, &size, false)) {
log_error("Loading fex rank file %s failed", path);
return NULL;
}
// if (size != sizeof(struct fex_profile_rank)) {
// log_error("Invalid size of fex rank file %s: %d != %d", path, size,
// sizeof(struct fex_profile_rank));
// free(rank);
// return NULL;
// }
// if (size != sizeof(struct fex_profile_rank)) {
// log_error("Invalid size of fex rank file %s: %d != %d", path, size,
// sizeof(struct fex_profile_rank));
// free(rank);
// return NULL;
// }
if (encrypted) {
asset_fex_usb_rank_decrypt((uint8_t*) rank, size);
}
if (encrypted) {
asset_fex_usb_rank_decrypt((uint8_t *) rank, size);
}
return rank;
return rank;
}
bool asset_fex_usb_rank_save_to_file(const char* path,
const struct asset_fex_usb_rank* rank, bool encrypt)
bool asset_fex_usb_rank_save_to_file(
const char *path, const struct asset_fex_usb_rank *rank, bool encrypt)
{
struct asset_fex_usb_rank rank_enc;
struct asset_fex_usb_rank rank_enc;
memcpy(&rank_enc, rank, sizeof(struct asset_fex_usb_rank));
memcpy(&rank_enc, rank, sizeof(struct asset_fex_usb_rank));
if (encrypt) {
asset_fex_usb_rank_encrypt((uint8_t*) &rank_enc,
sizeof(struct asset_fex_usb_rank));
}
if (encrypt) {
asset_fex_usb_rank_encrypt(
(uint8_t *) &rank_enc, sizeof(struct asset_fex_usb_rank));
}
if (!util_file_save(path, (void**) &rank_enc,
sizeof(struct asset_fex_usb_rank))) {
log_error("Storing fex rank data to %s failed", path);
return false;
}
if (!util_file_save(
path, (void **) &rank_enc, sizeof(struct asset_fex_usb_rank))) {
log_error("Storing fex rank data to %s failed", path);
return false;
}
return true;
return true;
}
struct asset_fex_usb_save* asset_fex_usb_save_load_from_file(const char* path,
bool encrypted)
struct asset_fex_usb_save *
asset_fex_usb_save_load_from_file(const char *path, bool encrypted)
{
struct asset_fex_usb_save* save;
size_t size;
struct asset_fex_usb_save *save;
size_t size;
if (!util_file_load(path, (void**) &save, &size, false)) {
log_error("Loading fex save file %s failed", path);
return NULL;
}
if (!util_file_load(path, (void **) &save, &size, false)) {
log_error("Loading fex save file %s failed", path);
return NULL;
}
// if (size != sizeof(struct fex_profile_save)) {
// log_error("Invalid size of fex save file %s: %d != %d", path, size,
// sizeof(struct fex_profile_save));
// free(save);
// return NULL;
// }
// if (size != sizeof(struct fex_profile_save)) {
// log_error("Invalid size of fex save file %s: %d != %d", path, size,
// sizeof(struct fex_profile_save));
// free(save);
// return NULL;
// }
if (encrypted) {
asset_fex_usb_save_decrypt((uint8_t*) save, size);
}
if (encrypted) {
asset_fex_usb_save_decrypt((uint8_t *) save, size);
}
return save;
return save;
}
bool asset_fex_usb_save_save_to_file(const char* path,
const struct asset_fex_usb_save* save, bool encrypt)
bool asset_fex_usb_save_save_to_file(
const char *path, const struct asset_fex_usb_save *save, bool encrypt)
{
struct asset_fex_usb_save save_enc;
struct asset_fex_usb_save save_enc;
memcpy(&save_enc, save, sizeof(struct asset_fex_usb_save));
memcpy(&save_enc, save, sizeof(struct asset_fex_usb_save));
if (encrypt) {
asset_fex_usb_save_encrypt((uint8_t*) &save_enc,
sizeof(struct asset_fex_usb_save));
}
if (encrypt) {
asset_fex_usb_save_encrypt(
(uint8_t *) &save_enc, sizeof(struct asset_fex_usb_save));
}
if (!util_file_save(path, (const void*) &save_enc,
sizeof(struct asset_fex_usb_save))) {
log_error("Storing fex save data to %s failed", path);
return false;
}
if (!util_file_save(
path, (const void *) &save_enc, sizeof(struct asset_fex_usb_save))) {
log_error("Storing fex save data to %s failed", path);
return false;
}
return true;
return true;
}
+8 -4
View File
@@ -7,15 +7,19 @@
#include "usb-save.h"
// load from file and decrypt, returns decrypted struct
struct asset_fex_usb_rank* asset_fex_usb_rank_load_from_file(const char* path, bool encrypted);
struct asset_fex_usb_rank *
asset_fex_usb_rank_load_from_file(const char *path, bool encrypted);
// takes decrypted rank data, encrypts it and writes it to file
bool asset_fex_usb_rank_save_to_file(const char* path, const struct asset_fex_usb_rank* rank, bool encrypt);
bool asset_fex_usb_rank_save_to_file(
const char *path, const struct asset_fex_usb_rank *rank, bool encrypt);
// load from file and decrypt, returns decrypted struct
struct asset_fex_usb_save* asset_fex_usb_save_load_from_file(const char* path, bool encrypted);
struct asset_fex_usb_save *
asset_fex_usb_save_load_from_file(const char *path, bool encrypted);
// takes decrypted save data, encrypts it and writes it to file
bool asset_fex_usb_save_save_to_file(const char* path, const struct asset_fex_usb_save* save, bool encrypt);
bool asset_fex_usb_save_save_to_file(
const char *path, const struct asset_fex_usb_save *save, bool encrypt);
#endif
+132 -128
View File
@@ -9,146 +9,150 @@
#include "util/str.h"
int main(int argc, char** argv)
int main(int argc, char **argv)
{
int ret;
char* rank_path;
char* save_path;
int ret;
char *rank_path;
char *save_path;
if (argc < 3) {
printf("Usage: %s [cmd: new, dec, enc, dump] "
"[path containing fiestaex_rank.bin fiestaex_save.bin]\n", argv[0]);
return -1;
if (argc < 3) {
printf(
"Usage: %s [cmd: new, dec, enc, dump] "
"[path containing fiestaex_rank.bin fiestaex_save.bin]\n",
argv[0]);
return -1;
}
ret = 0;
rank_path = util_str_merge(argv[2], "fiestaex_rank.bin");
save_path = util_str_merge(argv[2], "fiestaex_save.bin");
if (!strcmp(argv[1], "new")) {
struct asset_fex_usb_rank *rank = asset_fex_usb_rank_new();
struct asset_fex_usb_save *save = asset_fex_usb_save_new();
asset_fex_usb_rank_finalize(rank);
asset_fex_usb_save_finalize(save);
if (!asset_fex_usb_rank_save_to_file(rank_path, rank, true)) {
fprintf(stderr, "Creating rank file %s failed\n", rank_path);
ret = -2;
}
ret = 0;
if (!asset_fex_usb_save_save_to_file(save_path, save, true)) {
fprintf(stderr, "Creating save file %s failed\n", save_path);
ret = -3;
}
rank_path = util_str_merge(argv[2], "fiestaex_rank.bin");
save_path = util_str_merge(argv[2], "fiestaex_save.bin");
free(rank);
free(save);
} else {
struct asset_fex_usb_rank *rank;
struct asset_fex_usb_save *save;
bool encrypted;
if (!strcmp(argv[1], "new")) {
struct asset_fex_usb_rank* rank = asset_fex_usb_rank_new();
struct asset_fex_usb_save* save = asset_fex_usb_save_new();
if (!strcmp(argv[1], "enc")) {
char *tmp;
asset_fex_usb_rank_finalize(rank);
asset_fex_usb_save_finalize(save);
encrypted = false;
if (!asset_fex_usb_rank_save_to_file(rank_path, rank, true)) {
fprintf(stderr, "Creating rank file %s failed\n", rank_path);
ret = -2;
}
tmp = util_str_merge(rank_path, ".dec");
free(rank_path);
rank_path = tmp;
if (!asset_fex_usb_save_save_to_file(save_path, save, true)) {
fprintf(stderr, "Creating save file %s failed\n", save_path);
ret = -3;
}
free(rank);
free(save);
tmp = util_str_merge(save_path, ".dec");
free(save_path);
save_path = tmp;
} else {
struct asset_fex_usb_rank* rank;
struct asset_fex_usb_save* save;
bool encrypted;
if (!strcmp(argv[1], "enc")) {
char* tmp;
encrypted = false;
tmp = util_str_merge(rank_path, ".dec");
free(rank_path);
rank_path = tmp;
tmp = util_str_merge(save_path, ".dec");
free(save_path);
save_path = tmp;
} else {
encrypted = true;
}
rank = asset_fex_usb_rank_load_from_file(rank_path, encrypted);
save = asset_fex_usb_save_load_from_file(save_path, encrypted);
if (!rank) {
fprintf(stderr, "Loading %s failed", rank_path);
ret = -4;
goto cleanup;
}
if (!save) {
fprintf(stderr, "Loading %s failed", save_path);
ret = -5;
free(rank);
goto cleanup;
}
if (!strcmp(argv[1], "dec")) {
char* rank_path_dec;
char* save_path_dec;
rank_path_dec = util_str_merge(rank_path, ".dec");
save_path_dec = util_str_merge(save_path, ".dec");
if (!asset_fex_usb_rank_save_to_file(rank_path_dec, rank, false)) {
fprintf(stderr, "Saving decrypted rank file to %s failed\n",
rank_path_dec);
ret = -6;
}
if (!asset_fex_usb_save_save_to_file(save_path_dec, save, false)) {
fprintf(stderr, "Saving decrypted save file to %s failed\n",
save_path_dec);
ret = -7;
}
free(rank_path_dec);
free(save_path_dec);
} else if (!strcmp(argv[1], "enc")) {
char* rank_path_enc;
char* save_path_enc;
rank_path_enc = util_str_merge(rank_path, ".enc");
save_path_enc = util_str_merge(save_path, ".enc");
if (!asset_fex_usb_rank_save_to_file(rank_path_enc, rank, true)) {
fprintf(stderr, "Saving encrypted rank file to %s failed\n",
rank_path_enc);
ret = -6;
}
if (!asset_fex_usb_save_save_to_file(save_path_enc, save, true)) {
fprintf(stderr, "Saving encrypted save file to %s failed\n",
save_path_enc);
ret = -7;
}
free(rank_path_enc);
free(save_path_enc);
} else if (!strcmp(argv[1], "dump")) {
char* rank_str;
char* save_str;
rank_str = asset_fex_usb_rank_to_string(rank);
save_str = asset_fex_usb_save_to_string(save);
printf("----------------- rank -----------------\n"
"%s----------------- save -----------------\n%s",
rank_str, save_str);
free(rank_str);
free(save_str);
} else {
fprintf(stderr, "Unknown command %s\n", argv[1]);
ret = -4;
}
free(rank);
free(save);
encrypted = true;
}
rank = asset_fex_usb_rank_load_from_file(rank_path, encrypted);
save = asset_fex_usb_save_load_from_file(save_path, encrypted);
if (!rank) {
fprintf(stderr, "Loading %s failed", rank_path);
ret = -4;
goto cleanup;
}
if (!save) {
fprintf(stderr, "Loading %s failed", save_path);
ret = -5;
free(rank);
goto cleanup;
}
if (!strcmp(argv[1], "dec")) {
char *rank_path_dec;
char *save_path_dec;
rank_path_dec = util_str_merge(rank_path, ".dec");
save_path_dec = util_str_merge(save_path, ".dec");
if (!asset_fex_usb_rank_save_to_file(rank_path_dec, rank, false)) {
fprintf(
stderr, "Saving decrypted rank file to %s failed\n", rank_path_dec);
ret = -6;
}
if (!asset_fex_usb_save_save_to_file(save_path_dec, save, false)) {
fprintf(
stderr, "Saving decrypted save file to %s failed\n", save_path_dec);
ret = -7;
}
free(rank_path_dec);
free(save_path_dec);
} else if (!strcmp(argv[1], "enc")) {
char *rank_path_enc;
char *save_path_enc;
rank_path_enc = util_str_merge(rank_path, ".enc");
save_path_enc = util_str_merge(save_path, ".enc");
if (!asset_fex_usb_rank_save_to_file(rank_path_enc, rank, true)) {
fprintf(
stderr, "Saving encrypted rank file to %s failed\n", rank_path_enc);
ret = -6;
}
if (!asset_fex_usb_save_save_to_file(save_path_enc, save, true)) {
fprintf(
stderr, "Saving encrypted save file to %s failed\n", save_path_enc);
ret = -7;
}
free(rank_path_enc);
free(save_path_enc);
} else if (!strcmp(argv[1], "dump")) {
char *rank_str;
char *save_str;
rank_str = asset_fex_usb_rank_to_string(rank);
save_str = asset_fex_usb_save_to_string(save);
printf(
"----------------- rank -----------------\n"
"%s----------------- save -----------------\n%s",
rank_str,
save_str);
free(rank_str);
free(save_str);
} else {
fprintf(stderr, "Unknown command %s\n", argv[1]);
ret = -4;
}
free(rank);
free(save);
}
cleanup:
free(rank_path);
free(save_path);
free(rank_path);
free(save_path);
return ret;
return ret;
}
+30 -30
View File
@@ -3,36 +3,36 @@
/* Note: Version IDs must be sync with server code */
enum asset_game_version {
ASSET_GAME_VERSION_INVALID = 0,
ASSET_GAME_VERSION_FIRST = 1,
ASSET_GAME_VERSION_SECOND = 2,
ASSET_GAME_VERSION_OBG = 3,
ASSET_GAME_VERSION_OBG_SE = 4,
ASSET_GAME_VERSION_THE_COLLECTION = 5,
ASSET_GAME_VERSION_PERFECT_COLLECTION = 6,
ASSET_GAME_VERSION_EXTRA = 7,
ASSET_GAME_VERSION_PREMIERE_1 = 8,
ASSET_GAME_VERSION_PREX_1 = 9,
ASSET_GAME_VERSION_REBIRTH = 10,
ASSET_GAME_VERSION_PREMIERE_2 = 11,
ASSET_GAME_VERSION_PREX_2 = 12,
ASSET_GAME_VERSION_PREMIERE_3 = 13,
ASSET_GAME_VERSION_PREX_3 = 14,
ASSET_GAME_VERSION_EXCEED = 15,
ASSET_GAME_VERSION_EXCEED_2 = 16,
ASSET_GAME_VERSION_ZERO = 17,
ASSET_GAME_VERSION_NX = 18,
ASSET_GAME_VERSION_PRO = 19,
ASSET_GAME_VERSION_NX2 = 20,
ASSET_GAME_VERSION_NXA = 21,
ASSET_GAME_VERSION_FIESTA = 22,
ASSET_GAME_VERSION_PRO2 = 23,
ASSET_GAME_VERSION_FIESTA_EX = 24,
ASSET_GAME_VERSION_FIESTA_2 = 25,
ASSET_GAME_VERSION_INFINITY = 26,
ASSET_GAME_VERSION_PRIME = 27,
ASSET_GAME_VERSION_PRIME_2 = 28,
ASSET_GAME_VERSION_XX = 29
ASSET_GAME_VERSION_INVALID = 0,
ASSET_GAME_VERSION_FIRST = 1,
ASSET_GAME_VERSION_SECOND = 2,
ASSET_GAME_VERSION_OBG = 3,
ASSET_GAME_VERSION_OBG_SE = 4,
ASSET_GAME_VERSION_THE_COLLECTION = 5,
ASSET_GAME_VERSION_PERFECT_COLLECTION = 6,
ASSET_GAME_VERSION_EXTRA = 7,
ASSET_GAME_VERSION_PREMIERE_1 = 8,
ASSET_GAME_VERSION_PREX_1 = 9,
ASSET_GAME_VERSION_REBIRTH = 10,
ASSET_GAME_VERSION_PREMIERE_2 = 11,
ASSET_GAME_VERSION_PREX_2 = 12,
ASSET_GAME_VERSION_PREMIERE_3 = 13,
ASSET_GAME_VERSION_PREX_3 = 14,
ASSET_GAME_VERSION_EXCEED = 15,
ASSET_GAME_VERSION_EXCEED_2 = 16,
ASSET_GAME_VERSION_ZERO = 17,
ASSET_GAME_VERSION_NX = 18,
ASSET_GAME_VERSION_PRO = 19,
ASSET_GAME_VERSION_NX2 = 20,
ASSET_GAME_VERSION_NXA = 21,
ASSET_GAME_VERSION_FIESTA = 22,
ASSET_GAME_VERSION_PRO2 = 23,
ASSET_GAME_VERSION_FIESTA_EX = 24,
ASSET_GAME_VERSION_FIESTA_2 = 25,
ASSET_GAME_VERSION_INFINITY = 26,
ASSET_GAME_VERSION_PRIME = 27,
ASSET_GAME_VERSION_PRIME_2 = 28,
ASSET_GAME_VERSION_XX = 29
};
#endif
+51 -46
View File
@@ -5,64 +5,69 @@
#include "util/adler32.h"
#include "util/mem.h"
struct asset_nx_settings* asset_nx_settings_new(void)
struct asset_nx_settings *asset_nx_settings_new(void)
{
struct asset_nx_settings* settings;
struct asset_nx_settings *settings;
settings = util_xmalloc(sizeof(struct asset_nx_settings));
settings = util_xmalloc(sizeof(struct asset_nx_settings));
memset(settings->ff_pad, 0xFF, sizeof(settings->ff_pad));
memcpy(settings->ident, "NX10", 4);
/* Updated using finalize */
settings->adler32 = 0;
settings->total_uptime = 0;
settings->language = ASSET_NX_SETTINGS_LANG_ENG;
memset(settings->song_play_count, 0, sizeof(uint32_t) * ASSET_NX_SETTINGS_MAX_SONGS);
settings->game_option_default_station = ASSET_NX_SETTINGS_STATION_TRAIN;
settings->game_mode = ASSET_NX_SETTINGS_GAME_MODE_NORMAL;
settings->game_level = ASSET_NX_SETTINGS_LEVEL_NORMAL;
settings->game_stage_break = ASSET_NX_SETTINGS_STAGE_BREAK_2ND;
settings->game_demo_sound = 1;
settings->game_show_help = 1;
settings->game_mercy_ticket = 0;
settings->game_score_per_ticket = 0;
settings->coin_limit = 0;
settings->coin1_setting = 1;
settings->coin2_setting = 1;
memset(settings->unknown_unlock_flags, 0, ASSET_NX_SETTINGS_NUM_UNLOCK_FLAGS);
settings->unkn2 = 0x2A;
settings->unkn3 = 0;
settings->bookkeeping_coin1_total = 0;
settings->bookkeeping_coin2_total = 0;
settings->bookkeeping_service_total = 0;
settings->bookkeeping_play_total = 0;
settings->bookkeeping_faep21_play_count = 0;
settings->bookkeeping_ticket_1 = 0;
settings->bookkeeping_ticket_2 = 0;
settings->region = 0xFF;
memset(settings->censor_table, 0, ASSET_NX_SETTINGS_MAX_SONGS);
memset(settings->ff_pad, 0xFF, sizeof(settings->ff_pad));
memcpy(settings->ident, "NX10", 4);
/* Updated using finalize */
settings->adler32 = 0;
settings->total_uptime = 0;
settings->language = ASSET_NX_SETTINGS_LANG_ENG;
memset(
settings->song_play_count,
0,
sizeof(uint32_t) * ASSET_NX_SETTINGS_MAX_SONGS);
settings->game_option_default_station = ASSET_NX_SETTINGS_STATION_TRAIN;
settings->game_mode = ASSET_NX_SETTINGS_GAME_MODE_NORMAL;
settings->game_level = ASSET_NX_SETTINGS_LEVEL_NORMAL;
settings->game_stage_break = ASSET_NX_SETTINGS_STAGE_BREAK_2ND;
settings->game_demo_sound = 1;
settings->game_show_help = 1;
settings->game_mercy_ticket = 0;
settings->game_score_per_ticket = 0;
settings->coin_limit = 0;
settings->coin1_setting = 1;
settings->coin2_setting = 1;
memset(settings->unknown_unlock_flags, 0, ASSET_NX_SETTINGS_NUM_UNLOCK_FLAGS);
settings->unkn2 = 0x2A;
settings->unkn3 = 0;
settings->bookkeeping_coin1_total = 0;
settings->bookkeeping_coin2_total = 0;
settings->bookkeeping_service_total = 0;
settings->bookkeeping_play_total = 0;
settings->bookkeeping_faep21_play_count = 0;
settings->bookkeeping_ticket_1 = 0;
settings->bookkeeping_ticket_2 = 0;
settings->region = 0xFF;
memset(settings->censor_table, 0, ASSET_NX_SETTINGS_MAX_SONGS);
return settings;
return settings;
}
void asset_nx_settings_finalize(struct asset_nx_settings* settings)
void asset_nx_settings_finalize(struct asset_nx_settings *settings)
{
/* Seems odd, but they just checksum the game settings part...*/
settings->adler32 = util_adler32_calc(1, (const uint8_t*) &settings->game_mode, 8);
/* Seems odd, but they just checksum the game settings part...*/
settings->adler32 =
util_adler32_calc(1, (const uint8_t *) &settings->game_mode, 8);
}
void asset_nx_settings_unlock_all(struct asset_nx_settings* settings)
void asset_nx_settings_unlock_all(struct asset_nx_settings *settings)
{
/* FAEP 2-1 must be played at least 100 times to unlock FAEP 2-2 */
settings->bookkeeping_faep21_play_count = 100;
/* FAEP 2-1 must be played at least 100 times to unlock FAEP 2-2 */
settings->bookkeeping_faep21_play_count = 100;
/* To unlock all world tour missions and special zone songs, set this to 20k.
The first 10k unlock only the first half of the missions while another 10k unlocks the second half (wtf) */
settings->bookkeeping_play_total = 20000;
/* To unlock all world tour missions and special zone songs, set this to 20k.
The first 10k unlock only the first half of the missions while another 10k
unlocks the second half (wtf) */
settings->bookkeeping_play_total = 20000;
}
char* asset_nx_settings_to_string(const struct asset_nx_settings* settings)
char *asset_nx_settings_to_string(const struct asset_nx_settings *settings)
{
// TODO
return "";
// TODO
return "";
}
+69 -67
View File
@@ -8,94 +8,96 @@
#define ASSET_NX_SETTINGS_NUM_UNLOCK_FLAGS 59
enum asset_nx_settings_language {
ASSET_NX_SETTINGS_LANG_KOR = 0,
ASSET_NX_SETTINGS_LANG_ENG = 1,
ASSET_NX_SETTINGS_LANG_SP = 2,
ASSET_NX_SETTINGS_LANG_CH = 3,
ASSET_NX_SETTINGS_LANG_KOR = 0,
ASSET_NX_SETTINGS_LANG_ENG = 1,
ASSET_NX_SETTINGS_LANG_SP = 2,
ASSET_NX_SETTINGS_LANG_CH = 3,
};
enum asset_nx_settings_station {
ASSET_NX_SETTINGS_STATION_TRAIN = 0,
ASSET_NX_SETTINGS_STATION_ARCADE = 1,
ASSET_NX_SETTINGS_STATION_WORLD = 2,
ASSET_NX_SETTINGS_STATION_SPECIAL = 3,
ASSET_NX_SETTINGS_STATION_TRAIN = 0,
ASSET_NX_SETTINGS_STATION_ARCADE = 1,
ASSET_NX_SETTINGS_STATION_WORLD = 2,
ASSET_NX_SETTINGS_STATION_SPECIAL = 3,
};
enum asset_nx_settings_game_mode {
ASSET_NX_SETTINGS_GAME_MODE_NORMAL = 0,
ASSET_NX_SETTINGS_GAME_MODE_EVENT = 1,
ASSET_NX_SETTINGS_GAME_MODE_NORMAL = 0,
ASSET_NX_SETTINGS_GAME_MODE_EVENT = 1,
};
enum asset_nx_settings_level {
ASSET_NX_SETTINGS_LEVEL_EASY = 0,
ASSET_NX_SETTINGS_LEVEL_NORMAL = 1,
ASSET_NX_SETTINGS_LEVEL_HARD = 2,
ASSET_NX_SETTINGS_LEVEL_EASY = 0,
ASSET_NX_SETTINGS_LEVEL_NORMAL = 1,
ASSET_NX_SETTINGS_LEVEL_HARD = 2,
};
enum asset_nx_settings_stage_break {
ASSET_NX_SETTINGS_STAGE_BREAK_OFF = 0,
ASSET_NX_SETTINGS_STAGE_BREAK_1ST = 1,
ASSET_NX_SETTINGS_STAGE_BREAK_2ND = 2,
ASSET_NX_SETTINGS_STAGE_BREAK_3RD = 3,
ASSET_NX_SETTINGS_STAGE_BREAK_4TH = 4,
ASSET_NX_SETTINGS_STAGE_BREAK_OFF = 0,
ASSET_NX_SETTINGS_STAGE_BREAK_1ST = 1,
ASSET_NX_SETTINGS_STAGE_BREAK_2ND = 2,
ASSET_NX_SETTINGS_STAGE_BREAK_3RD = 3,
ASSET_NX_SETTINGS_STAGE_BREAK_4TH = 4,
};
struct asset_nx_settings {
/* Padding to fill up to 4k EEPROM legacy size */
uint8_t ff_pad[0xB9D];
/* NX10 */
char ident[4];
uint32_t adler32;
uint32_t total_uptime;
uint8_t language;
uint32_t song_play_count[ASSET_NX_SETTINGS_MAX_SONGS];
uint32_t game_option_default_station;
uint8_t game_mode;
uint8_t game_level;
uint8_t game_stage_break;
/* 0 off, 1 on */
uint8_t game_demo_sound;
/* 0 off, 1 on */
uint8_t game_show_help;
/* 0 off, 1 on */
uint8_t game_mercy_ticket;
/* 0 off, 1 - 6 for score */
uint8_t game_score_per_ticket;
/* 0 none */
uint8_t coin_limit; // 0 none
/* 0 freeplay */
uint8_t coin1_setting;
/* 0 freeplay */
uint8_t coin2_setting;
/* Unlock flags for world tour missions? setting them to 1 doesn't unlock anything.
64 missions total, 55 unlock flags, 0 = locked, 1 = unlocked */
uint8_t unknown_unlock_flags[ASSET_NX_SETTINGS_NUM_UNLOCK_FLAGS];
/* Default value 0x2A */
uint32_t unkn2;
uint32_t unkn3;
uint32_t bookkeeping_coin1_total;
uint32_t bookkeeping_coin2_total;
uint32_t bookkeeping_service_total;
uint32_t bookkeeping_play_total;
/* Separate counter for FAEP 2-1 play counts. Once this hits 100, FAEP 2-2 is unlocked in arcade station */
uint32_t bookkeeping_faep21_play_count;
uint32_t bookkeeping_ticket_1;
uint32_t bookkeeping_ticket_2;
/* FF -> not used, censoring globally disabled. unused feature though */
uint8_t region;
/* 0 = censoring of song off */
uint8_t censor_table[ASSET_NX_SETTINGS_MAX_SONGS];
/* Padding to fill up to 4k EEPROM legacy size */
uint8_t ff_pad[0xB9D];
/* NX10 */
char ident[4];
uint32_t adler32;
uint32_t total_uptime;
uint8_t language;
uint32_t song_play_count[ASSET_NX_SETTINGS_MAX_SONGS];
uint32_t game_option_default_station;
uint8_t game_mode;
uint8_t game_level;
uint8_t game_stage_break;
/* 0 off, 1 on */
uint8_t game_demo_sound;
/* 0 off, 1 on */
uint8_t game_show_help;
/* 0 off, 1 on */
uint8_t game_mercy_ticket;
/* 0 off, 1 - 6 for score */
uint8_t game_score_per_ticket;
/* 0 none */
uint8_t coin_limit; // 0 none
/* 0 freeplay */
uint8_t coin1_setting;
/* 0 freeplay */
uint8_t coin2_setting;
/* Unlock flags for world tour missions? setting them to 1 doesn't unlock
anything. 64 missions total, 55 unlock flags, 0 = locked, 1 = unlocked */
uint8_t unknown_unlock_flags[ASSET_NX_SETTINGS_NUM_UNLOCK_FLAGS];
/* Default value 0x2A */
uint32_t unkn2;
uint32_t unkn3;
uint32_t bookkeeping_coin1_total;
uint32_t bookkeeping_coin2_total;
uint32_t bookkeeping_service_total;
uint32_t bookkeeping_play_total;
/* Separate counter for FAEP 2-1 play counts. Once this hits 100, FAEP 2-2 is
* unlocked in arcade station */
uint32_t bookkeeping_faep21_play_count;
uint32_t bookkeeping_ticket_1;
uint32_t bookkeeping_ticket_2;
/* FF -> not used, censoring globally disabled. unused feature though */
uint8_t region;
/* 0 = censoring of song off */
uint8_t censor_table[ASSET_NX_SETTINGS_MAX_SONGS];
} __attribute__((__packed__));
struct asset_nx_settings* asset_nx_settings_new(void);
struct asset_nx_settings *asset_nx_settings_new(void);
// update checksum
void asset_nx_settings_finalize(struct asset_nx_settings* settings);
void asset_nx_settings_finalize(struct asset_nx_settings *settings);
// unlocks FAEP 2-2 by setting the play count to 100
// and sets all missions cleared to unlock special stage songs and other missions
void asset_nx_settings_unlock_all(struct asset_nx_settings* settings);
// and sets all missions cleared to unlock special stage songs and other
// missions
void asset_nx_settings_unlock_all(struct asset_nx_settings *settings);
char* asset_nx_settings_to_string(const struct asset_nx_settings* settings);
char *asset_nx_settings_to_string(const struct asset_nx_settings *settings);
#endif
+26 -19
View File
@@ -5,31 +5,38 @@
#include "util/fs.h"
#include "util/log.h"
struct asset_nx_settings* asset_nx_util_load_settings_from_file(const char* path)
struct asset_nx_settings *
asset_nx_util_load_settings_from_file(const char *path)
{
struct asset_nx_settings* settings;
size_t size;
struct asset_nx_settings *settings;
size_t size;
if (!util_file_load(path, (void**) &settings, &size, false)) {
log_error("Loading nx setting file %s failed", path);
return NULL;
}
if (!util_file_load(path, (void **) &settings, &size, false)) {
log_error("Loading nx setting file %s failed", path);
return NULL;
}
if (size != sizeof(struct asset_nx_settings)) {
log_error("Invalid size of nx setting file %s: %d != %d", path, size, sizeof(struct asset_nx_settings));
free(settings);
return NULL;
}
if (size != sizeof(struct asset_nx_settings)) {
log_error(
"Invalid size of nx setting file %s: %d != %d",
path,
size,
sizeof(struct asset_nx_settings));
free(settings);
return NULL;
}
return settings;
return settings;
}
bool asset_nx_util_save_settings_to_file(const char* path, const struct asset_nx_settings* settings)
bool asset_nx_util_save_settings_to_file(
const char *path, const struct asset_nx_settings *settings)
{
if (!util_file_save(path, (void**) settings, sizeof(struct asset_nx_settings))) {
log_error("Storing nx settings data to %s failed", path);
return false;
}
if (!util_file_save(
path, (void **) settings, sizeof(struct asset_nx_settings))) {
log_error("Storing nx settings data to %s failed", path);
return false;
}
return true;
return true;
}
+4 -2
View File
@@ -5,8 +5,10 @@
#include "asset/nx/lib/settings.h"
struct asset_nx_settings* asset_nx_util_load_settings_from_file(const char* path);
struct asset_nx_settings *
asset_nx_util_load_settings_from_file(const char *path);
bool asset_nx_util_save_settings_to_file(const char* path, const struct asset_nx_settings* settings);
bool asset_nx_util_save_settings_to_file(
const char *path, const struct asset_nx_settings *settings);
#endif
+65 -62
View File
@@ -8,81 +8,84 @@
#include "asset/nx/lib/settings.h"
#include "asset/nx/lib/util.h"
static int main_settings(char* cmd, char* file);
static int main_settings(char *cmd, char *file);
int main(int argc, char** argv)
int main(int argc, char **argv)
{
int ret;
char* cmd;
char* type;
char* file;
int ret;
char *cmd;
char *type;
char *file;
if (argc < 4) {
printf("Usage: %s [cmd: new, dump, unlock] [type: ini, mrank, rank] [file]\n", argv[0]);
return -1;
}
if (argc < 4) {
printf(
"Usage: %s [cmd: new, dump, unlock] [type: ini, mrank, rank] [file]\n",
argv[0]);
return -1;
}
cmd = argv[1];
type = argv[2];
file = argv[3];
cmd = argv[1];
type = argv[2];
file = argv[3];
if (!strcmp(type, "ini")) {
ret = main_settings(cmd, file);
} else {
fprintf(stderr, "Unknown file type %s\n", type);
ret = -1;
}
if (!strcmp(type, "ini")) {
ret = main_settings(cmd, file);
} else {
fprintf(stderr, "Unknown file type %s\n", type);
ret = -1;
}
return ret;
return ret;
}
static int main_settings(char* cmd, char* file)
static int main_settings(char *cmd, char *file)
{
int ret;
int ret;
ret = 0;
ret = 0;
if (!strcmp(cmd, "new")) {
struct asset_nx_settings* settings = asset_nx_settings_new();
if (!strcmp(cmd, "new")) {
struct asset_nx_settings *settings = asset_nx_settings_new();
asset_nx_settings_finalize(settings);
asset_nx_settings_finalize(settings);
if (!asset_nx_util_save_settings_to_file(file, settings)) {
fprintf(stderr, "Creating nx settings file %s failed\n", file);
ret = -1;
}
free(settings);
} else {
struct asset_nx_settings* settings = asset_nx_util_load_settings_from_file(file);
if (!settings) {
fprintf(stderr, "Loading %s failed", file);
ret = -1;
}
if (!strcmp(cmd, "dump")) {
char* str = asset_nx_settings_to_string(settings);
printf("----------------- settings -----------------\n%s\n", str);
free(str);
} else if (!strcmp(cmd, "unlock")) {
asset_nx_settings_unlock_all(settings);
asset_nx_settings_finalize(settings);
if (!asset_nx_util_save_settings_to_file(file, settings)) {
fprintf(stderr, "Saving nx settings file %s failed\n", file);
ret = -1;
}
} else {
fprintf(stderr, "Unknown command %s\n", cmd);
ret = -1;
}
free(settings);
if (!asset_nx_util_save_settings_to_file(file, settings)) {
fprintf(stderr, "Creating nx settings file %s failed\n", file);
ret = -1;
}
return ret;
free(settings);
} else {
struct asset_nx_settings *settings =
asset_nx_util_load_settings_from_file(file);
if (!settings) {
fprintf(stderr, "Loading %s failed", file);
ret = -1;
}
if (!strcmp(cmd, "dump")) {
char *str = asset_nx_settings_to_string(settings);
printf("----------------- settings -----------------\n%s\n", str);
free(str);
} else if (!strcmp(cmd, "unlock")) {
asset_nx_settings_unlock_all(settings);
asset_nx_settings_finalize(settings);
if (!asset_nx_util_save_settings_to_file(file, settings)) {
fprintf(stderr, "Saving nx settings file %s failed\n", file);
ret = -1;
}
} else {
fprintf(stderr, "Unknown command %s\n", cmd);
ret = -1;
}
free(settings);
}
return ret;
}
+63 -58
View File
@@ -6,88 +6,93 @@
#include "usb-rank.h"
struct asset_nx2_usb_rank* asset_nx2_usb_rank_new(void)
struct asset_nx2_usb_rank *asset_nx2_usb_rank_new(void)
{
struct asset_nx2_usb_rank* rank;
struct asset_nx2_usb_rank *rank;
rank = (struct asset_nx2_usb_rank*)
util_xmalloc(sizeof(struct asset_nx2_usb_rank));
rank = (struct asset_nx2_usb_rank *) util_xmalloc(
sizeof(struct asset_nx2_usb_rank));
memset(rank, 0, sizeof(struct asset_nx2_usb_rank));
memset(rank, 0, sizeof(struct asset_nx2_usb_rank));
return rank;
return rank;
}
void asset_nx2_usb_rank_finalize(struct asset_nx2_usb_rank* rank)
void asset_nx2_usb_rank_finalize(struct asset_nx2_usb_rank *rank)
{
rank->adler32 = util_adler32_calc(1, ((const uint8_t*) rank) + 4,
sizeof(struct asset_nx2_usb_rank) - 4);
rank->adler32 = util_adler32_calc(
1, ((const uint8_t *) rank) + 4, sizeof(struct asset_nx2_usb_rank) - 4);
}
char* asset_nx2_usb_rank_to_string(const struct asset_nx2_usb_rank* rank)
char *asset_nx2_usb_rank_to_string(const struct asset_nx2_usb_rank *rank)
{
char* buffer;
char* buffer2;
char* merged;
char *buffer;
char *buffer2;
char *merged;
buffer = (char*) util_xmalloc(128);
memset(buffer, 0, 128);
buffer = (char *) util_xmalloc(128);
memset(buffer, 0, 128);
util_str_format(buffer, 128,
"adler32: 0x%X\n"
"num_rankings: %d\n"
"ranking entries:\n",
rank->adler32,
rank->num_rankings);
util_str_format(
buffer,
128,
"adler32: 0x%X\n"
"num_rankings: %d\n"
"ranking entries:\n",
rank->adler32,
rank->num_rankings);
for (uint32_t i = 0; i < ASSET_NX2_USB_RANK_MAX_RANK_ENTRIES; i++) {
for (uint32_t i = 0; i < ASSET_NX2_USB_RANK_MAX_RANK_ENTRIES; i++) {
for (uint32_t j = 0; j < ASSET_NX2_USB_RANK_MAX_STAGES; j++) {
buffer2 = (char*) util_xmalloc(512);
memset(buffer2, 0, 512);
for (uint32_t j = 0; j < ASSET_NX2_USB_RANK_MAX_STAGES; j++) {
buffer2 = (char *) util_xmalloc(512);
memset(buffer2, 0, 512);
util_str_format(buffer2, 512,
"%d/%d:\n"
"game_mode: %d\n"
"play_order: %d\n"
"play_score: %d\n"
"grade: %d\n"
"mileage: %d\n"
"play_time: %f\n"
"kcal: %f\n"
"v02: %f\n",
i, j,
rank->entries[i][j].game_mode,
rank->entries[i][j].play_order,
rank->entries[i][j].play_score,
rank->entries[i][j].grade,
rank->entries[i][j].mileage,
rank->entries[i][j].play_time,
rank->entries[i][j].kcal,
rank->entries[i][j].v02);
util_str_format(
buffer2,
512,
"%d/%d:\n"
"game_mode: %d\n"
"play_order: %d\n"
"play_score: %d\n"
"grade: %d\n"
"mileage: %d\n"
"play_time: %f\n"
"kcal: %f\n"
"v02: %f\n",
i,
j,
rank->entries[i][j].game_mode,
rank->entries[i][j].play_order,
rank->entries[i][j].play_score,
rank->entries[i][j].grade,
rank->entries[i][j].mileage,
rank->entries[i][j].play_time,
rank->entries[i][j].kcal,
rank->entries[i][j].v02);
merged = util_str_merge(buffer, buffer2);
merged = util_str_merge(buffer, buffer2);
free(buffer);
free(buffer2);
free(buffer);
free(buffer2);
buffer = merged;
}
buffer = merged;
}
}
return buffer;
return buffer;
}
void asset_nx2_usb_rank_decrypt(uint8_t* buf, size_t len)
void asset_nx2_usb_rank_decrypt(uint8_t *buf, size_t len)
{
for (size_t a = len - 1; a > 0; --a) {
buf[a] = (buf[a] ^ buf[a - 1]) + ((a * 1234567) >> 8);
}
for (size_t a = len - 1; a > 0; --a) {
buf[a] = (buf[a] ^ buf[a - 1]) + ((a * 1234567) >> 8);
}
}
void asset_nx2_usb_rank_encrypt(uint8_t* buf, size_t len)
void asset_nx2_usb_rank_encrypt(uint8_t *buf, size_t len)
{
for (size_t a = 1; a < len; ++a) {
buf[a] = (buf[a] - ((a * 1234567) >> 8)) ^ buf[a - 1];
}
for (size_t a = 1; a < len; ++a) {
buf[a] = (buf[a] - ((a * 1234567) >> 8)) ^ buf[a - 1];
}
}
+19 -18
View File
@@ -7,36 +7,37 @@
#define ASSET_NX2_USB_RANK_SIZE 12296
enum asset_nx2_usb_rank_sizes {
ASSET_NX2_USB_RANK_MAX_STAGES = 3,
ASSET_NX2_USB_RANK_MAX_RANK_ENTRIES = 128,
ASSET_NX2_USB_RANK_MAX_STAGES = 3,
ASSET_NX2_USB_RANK_MAX_RANK_ENTRIES = 128,
};
struct asset_nx2_usb_rank_entry {
int32_t game_mode;
int32_t play_order;
int32_t play_score;
int32_t grade;
int32_t mileage;
float play_time;
float kcal;
float v02;
int32_t game_mode;
int32_t play_order;
int32_t play_score;
int32_t grade;
int32_t mileage;
float play_time;
float kcal;
float v02;
} __attribute__((__packed__));
struct asset_nx2_usb_rank {
uint32_t adler32;
uint32_t num_rankings;
struct asset_nx2_usb_rank_entry entries[ASSET_NX2_USB_RANK_MAX_RANK_ENTRIES][ASSET_NX2_USB_RANK_MAX_STAGES];
uint32_t adler32;
uint32_t num_rankings;
struct asset_nx2_usb_rank_entry entries[ASSET_NX2_USB_RANK_MAX_RANK_ENTRIES]
[ASSET_NX2_USB_RANK_MAX_STAGES];
} __attribute__((__packed__));
struct asset_nx2_usb_rank* asset_nx2_usb_rank_new(void);
struct asset_nx2_usb_rank *asset_nx2_usb_rank_new(void);
// update checksum and prepare profile to get encrypted
void asset_nx2_usb_rank_finalize(struct asset_nx2_usb_rank* rank);
void asset_nx2_usb_rank_finalize(struct asset_nx2_usb_rank *rank);
char* asset_nx2_usb_rank_to_string(const struct asset_nx2_usb_rank* rank);
char *asset_nx2_usb_rank_to_string(const struct asset_nx2_usb_rank *rank);
void asset_nx2_usb_rank_decrypt(uint8_t* buf, size_t len);
void asset_nx2_usb_rank_decrypt(uint8_t *buf, size_t len);
void asset_nx2_usb_rank_encrypt(uint8_t* buf, size_t len);
void asset_nx2_usb_rank_encrypt(uint8_t *buf, size_t len);
#endif
+330 -301
View File
@@ -8,363 +8,392 @@
#include "usb-save.h"
static char* asset_nx2_usb_save_time_to_string(
const struct asset_nx2_usb_save_time* time)
static char *
asset_nx2_usb_save_time_to_string(const struct asset_nx2_usb_save_time *time)
{
char* buffer;
char *buffer;
buffer = (char*) util_xmalloc(128);
memset(buffer, 0, 128);
buffer = (char *) util_xmalloc(128);
memset(buffer, 0, 128);
util_str_format(buffer, 128,
"year: %d\n"
"month: %d\n"
"day: %d\n"
"hour: %d\n"
"min: %d\n"
"ms: %d\n",
time->year,
time->month,
time->day,
time->hour,
time->min,
time->ms);
util_str_format(
buffer,
128,
"year: %d\n"
"month: %d\n"
"day: %d\n"
"hour: %d\n"
"min: %d\n"
"ms: %d\n",
time->year,
time->month,
time->day,
time->hour,
time->min,
time->ms);
return buffer;
return buffer;
}
static char* asset_nx2_usb_save_review_to_string(
const struct asset_nx2_usb_save_review* review)
static char *asset_nx2_usb_save_review_to_string(
const struct asset_nx2_usb_save_review *review)
{
char* buffer;
char* land;
char* mission;
char *buffer;
char *land;
char *mission;
buffer = (char*) util_xmalloc(1024);
memset(buffer, 0, 1024);
buffer = (char *) util_xmalloc(1024);
memset(buffer, 0, 1024);
land = util_str_buffer((const uint8_t*) review->worldmax_current_land,
ASSET_NX2_USB_SAVE_WORLDMAX_LOC_MAX);
mission = util_str_buffer((const uint8_t*) review->worldmax_current_mission,
ASSET_NX2_USB_SAVE_WORLDMAX_LOC_MAX);
land = util_str_buffer(
(const uint8_t *) review->worldmax_current_land,
ASSET_NX2_USB_SAVE_WORLDMAX_LOC_MAX);
mission = util_str_buffer(
(const uint8_t *) review->worldmax_current_mission,
ASSET_NX2_USB_SAVE_WORLDMAX_LOC_MAX);
util_str_format(buffer, 1024,
">>> review:\n"
"player_id: %s\n"
"mileage: %d\n"
"reward_count: %d\n"
"worldmax_count: %d\n"
"play_count: %d\n"
"worldmax_current_land: %s\n"
"worldmax_current_mission: %s\n"
"kcal: %d\n"
"v02: %d\n",
review->player_id,
review->mileage,
review->reward_count,
review->worldmax_count,
review->play_count,
land,
mission,
review->kcal,
review->v02);
util_str_format(
buffer,
1024,
">>> review:\n"
"player_id: %s\n"
"mileage: %d\n"
"reward_count: %d\n"
"worldmax_count: %d\n"
"play_count: %d\n"
"worldmax_current_land: %s\n"
"worldmax_current_mission: %s\n"
"kcal: %d\n"
"v02: %d\n",
review->player_id,
review->mileage,
review->reward_count,
review->worldmax_count,
review->play_count,
land,
mission,
review->kcal,
review->v02);
free(land);
free(mission);
free(land);
free(mission);
return buffer;
return buffer;
}
static char* asset_nx2_usb_save_stats_to_string(
const struct asset_nx2_usb_save_stats* stats)
static char *
asset_nx2_usb_save_stats_to_string(const struct asset_nx2_usb_save_stats *stats)
{
char* merged;
char* buffer;
char* timestamp;
char* tmp;
const size_t buf_size = 512;
char *merged;
char *buffer;
char *timestamp;
char *tmp;
const size_t buf_size = 512;
merged = (char*) util_xmalloc(buf_size);
memset(merged, 0, buf_size);
merged = (char *) util_xmalloc(buf_size);
memset(merged, 0, buf_size);
buffer = (char*) util_xmalloc(buf_size);
memset(buffer, 0, buf_size);
buffer = (char *) util_xmalloc(buf_size);
memset(buffer, 0, buf_size);
timestamp = asset_nx2_usb_save_time_to_string(&stats->timestamp);
timestamp = asset_nx2_usb_save_time_to_string(&stats->timestamp);
util_str_format(merged, buf_size,
">>> stats:\n"
"adler32: 0x%X\n"
"usb_serial: %s\n"
"timestamp: %s"
"avatar_id: %d\n"
"rank: %d\n"
"country_id: %d\n"
"player_id: %s\n"
"mileage: %d\n"
"play_count: %d\n"
"kcal: %d\n"
"v02: %d\n"
"worldmax_map_position: 0x%X\n"
"reward_count: %d\n"
"worldmax_count: %d\n",
stats->adler32,
stats->usb_serial,
timestamp,
stats->avatar_id,
stats->rank,
stats->country_id,
stats->player_id,
stats->mileage,
stats->play_count,
stats->kcal,
stats->v02,
stats->worldmax_map_position,
stats->reward_count,
stats->worldmax_count);
util_str_format(
merged,
buf_size,
">>> stats:\n"
"adler32: 0x%X\n"
"usb_serial: %s\n"
"timestamp: %s"
"avatar_id: %d\n"
"rank: %d\n"
"country_id: %d\n"
"player_id: %s\n"
"mileage: %d\n"
"play_count: %d\n"
"kcal: %d\n"
"v02: %d\n"
"worldmax_map_position: 0x%X\n"
"reward_count: %d\n"
"worldmax_count: %d\n",
stats->adler32,
stats->usb_serial,
timestamp,
stats->avatar_id,
stats->rank,
stats->country_id,
stats->player_id,
stats->mileage,
stats->play_count,
stats->kcal,
stats->v02,
stats->worldmax_map_position,
stats->reward_count,
stats->worldmax_count);
free(timestamp);
free(timestamp);
tmp = util_str_merge(merged, "song_unlocks:\n");
tmp = util_str_merge(merged, "song_unlocks:\n");
free(merged);
merged = tmp;
for (uint32_t i = 0; i < ASSET_NX2_USB_SAVE_SONG_MAX; i++) {
util_str_format(
buffer,
buf_size,
"song slot: %d\n"
"mode: 0x%X\n"
"unused: 0x%X\n"
"song: %d\n"
"reveal: %d\n",
i,
stats->song_unlocks[i].mode,
stats->song_unlocks[i].unused,
stats->song_unlocks[i].song,
stats->song_unlocks[i].reveal);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NX2_USB_SAVE_SONG_MAX; i++) {
for (uint32_t i = 0; i < ASSET_NX2_USB_SAVE_MISSION_MAX; i++) {
util_str_format(buffer, buf_size,
"song slot: %d\n"
"mode: 0x%X\n"
"unused: 0x%X\n"
"song: %d\n"
"reveal: %d\n",
i,
stats->song_unlocks[i].mode,
stats->song_unlocks[i].unused,
stats->song_unlocks[i].song,
stats->song_unlocks[i].reveal);
util_str_format(
buffer,
buf_size,
"mission slot: %d\n"
"clear_flags_directions: 0x%X\n"
"clear_flag_mission: %d\n"
"unused: 0x%X\n",
i,
stats->worldmax_mission_unlocks[i].clear_flags_directions,
stats->worldmax_mission_unlocks[i].clear_flag_mission,
stats->worldmax_mission_unlocks[i].unused);
tmp = util_str_merge(merged, buffer);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NX2_USB_SAVE_MISSION_MAX; i++) {
util_str_format(
buffer,
buf_size,
"worldmax_high_score %d: %d\n",
i,
stats->worldmax_high_score[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NX2_USB_SAVE_MISSION_MAX; i++) {
util_str_format(
buffer,
buf_size,
"worldmax_challenge %d: %d\n",
i,
stats->worldmax_challenge[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NX2_USB_SAVE_BARRICADE_MAX; i++) {
util_str_format(
buffer,
buf_size,
"worldmax_barricade %d:\n"
"flag_open: %d\n"
"unused: 0x%X\n",
i,
stats->worldmax_barricade[i].flag_open,
stats->worldmax_barricade[i].unused);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NX2_USB_SAVE_EVENT_MAX; i++) {
util_str_format(
buffer,
buf_size,
"worldmax_event %d:\n"
"flag_cleared: %d\n"
"unused: 0x%X\n",
i,
stats->worldmax_event[i].flag_cleared,
stats->worldmax_event[i].unused);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NX2_USB_SAVE_WARP_MAX; i++) {
util_str_format(
buffer,
buf_size,
"worldmax_warp %d:\n"
"direction_clear: 0x%X\n"
"clear: %d\n",
"unused: 0x%X\n",
i,
stats->worldmax_warp[i].direction_clear,
stats->worldmax_warp[i].clear,
stats->worldmax_warp[i].unused);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NX2_USB_SAVE_WORLDMAX_LOC_MAX; i++) {
util_str_format(
buffer,
buf_size,
"worldmax_current_land %d: %d\n",
i,
stats->worldmax_current_land[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NX2_USB_SAVE_WORLDMAX_LOC_MAX; i++) {
util_str_format(
buffer,
buf_size,
"worldmax_current_mission %d: %d\n",
i,
stats->worldmax_current_mission[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NX2_USB_SAVE_SONG_MAX; i++) {
for (uint32_t j = 0; j < ASSET_NX2_USB_SAVE_NUM_MODES; j++) {
util_str_format(
buffer,
buf_size,
"song_scores %d/%d:\n"
"score: %d\n"
"player_id: %s\n",
i,
j,
stats->song_scores[i][j].score,
stats->song_scores[i][j].player_id);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
}
for (uint32_t i = 0; i < ASSET_NX2_USB_SAVE_MISSION_MAX; i++) {
free(buffer);
util_str_format(buffer, buf_size,
"mission slot: %d\n"
"clear_flags_directions: 0x%X\n"
"clear_flag_mission: %d\n"
"unused: 0x%X\n",
i,
stats->worldmax_mission_unlocks[i].clear_flags_directions,
stats->worldmax_mission_unlocks[i].clear_flag_mission,
stats->worldmax_mission_unlocks[i].unused);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NX2_USB_SAVE_MISSION_MAX; i++) {
util_str_format(buffer, buf_size,
"worldmax_high_score %d: %d\n",
i,
stats->worldmax_high_score[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NX2_USB_SAVE_MISSION_MAX; i++) {
util_str_format(buffer, buf_size,
"worldmax_challenge %d: %d\n",
i,
stats->worldmax_challenge[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NX2_USB_SAVE_BARRICADE_MAX; i++) {
util_str_format(buffer, buf_size,
"worldmax_barricade %d:\n"
"flag_open: %d\n"
"unused: 0x%X\n",
i,
stats->worldmax_barricade[i].flag_open,
stats->worldmax_barricade[i].unused);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NX2_USB_SAVE_EVENT_MAX; i++) {
util_str_format(buffer, buf_size,
"worldmax_event %d:\n"
"flag_cleared: %d\n"
"unused: 0x%X\n",
i,
stats->worldmax_event[i].flag_cleared,
stats->worldmax_event[i].unused);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NX2_USB_SAVE_WARP_MAX; i++) {
util_str_format(buffer, buf_size,
"worldmax_warp %d:\n"
"direction_clear: 0x%X\n"
"clear: %d\n",
"unused: 0x%X\n",
i,
stats->worldmax_warp[i].direction_clear,
stats->worldmax_warp[i].clear,
stats->worldmax_warp[i].unused);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NX2_USB_SAVE_WORLDMAX_LOC_MAX; i++) {
util_str_format(buffer, buf_size,
"worldmax_current_land %d: %d\n",
i,
stats->worldmax_current_land[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NX2_USB_SAVE_WORLDMAX_LOC_MAX; i++) {
util_str_format(buffer, buf_size,
"worldmax_current_mission %d: %d\n",
i,
stats->worldmax_current_mission[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NX2_USB_SAVE_SONG_MAX; i++) {
for (uint32_t j = 0; j < ASSET_NX2_USB_SAVE_NUM_MODES; j++) {
util_str_format(buffer, buf_size,
"song_scores %d/%d:\n"
"score: %d\n"
"player_id: %s\n",
i,
j,
stats->song_scores[i][j].score,
stats->song_scores[i][j].player_id);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
}
free(buffer);
return merged;
return merged;
}
struct asset_nx2_usb_save* asset_nx2_usb_save_new(void)
struct asset_nx2_usb_save *asset_nx2_usb_save_new(void)
{
struct asset_nx2_usb_save* save;
char name[10];
struct asset_nx2_usb_save *save;
char name[10];
save = (struct asset_nx2_usb_save*) util_xmalloc(
sizeof(struct asset_nx2_usb_save));
save = (struct asset_nx2_usb_save *) util_xmalloc(
sizeof(struct asset_nx2_usb_save));
memset(save, 0, sizeof(struct asset_nx2_usb_save));
memset(save, 0, sizeof(struct asset_nx2_usb_save));
sprintf(name, "NX%06d", rand() % 1000000);
strcpy(save->review.player_id, name);
strcpy(save->stats.player_id, name);
sprintf(name, "NX%06d", rand() % 1000000);
strcpy(save->review.player_id, name);
strcpy(save->stats.player_id, name);
/* default world map position */
save->stats.worldmax_map_position = 0xEF001;
/* default world map position */
save->stats.worldmax_map_position = 0xEF001;
/* nx2 release date as default timestamp */
save->stats.timestamp.year = 2008;
save->stats.timestamp.month = 1;
save->stats.timestamp.day = 21;
save->stats.timestamp.hour = 0;
save->stats.timestamp.min = 0;
save->stats.timestamp.ms = 0;
/* nx2 release date as default timestamp */
save->stats.timestamp.year = 2008;
save->stats.timestamp.month = 1;
save->stats.timestamp.day = 21;
save->stats.timestamp.hour = 0;
save->stats.timestamp.min = 0;
save->stats.timestamp.ms = 0;
return save;
return save;
}
void asset_nx2_usb_save_finalize(struct asset_nx2_usb_save* save)
void asset_nx2_usb_save_finalize(struct asset_nx2_usb_save *save)
{
/* checksum update */
save->stats.adler32 = util_adler32_calc(1,
((const uint8_t*) &save->stats) + 4,
sizeof(struct asset_nx2_usb_save_stats) - 4);
/* checksum update */
save->stats.adler32 = util_adler32_calc(
1,
((const uint8_t *) &save->stats) + 4,
sizeof(struct asset_nx2_usb_save_stats) - 4);
}
char* asset_nx2_usb_save_to_string(const struct asset_nx2_usb_save* save)
char *asset_nx2_usb_save_to_string(const struct asset_nx2_usb_save *save)
{
char* review;
char* stats;
char* merged;
char *review;
char *stats;
char *merged;
review = asset_nx2_usb_save_review_to_string(&save->review);
stats = asset_nx2_usb_save_stats_to_string(&save->stats);
review = asset_nx2_usb_save_review_to_string(&save->review);
stats = asset_nx2_usb_save_stats_to_string(&save->stats);
merged = util_str_merge(review, stats);
merged = util_str_merge(review, stats);
free(review);
free(stats);
free(review);
free(stats);
return merged;
return merged;
}
void asset_nx2_usb_save_decrypt(uint8_t* buf, size_t len)
void asset_nx2_usb_save_decrypt(uint8_t *buf, size_t len)
{
/* skip non encrypted review area */
buf += sizeof(struct asset_nx2_usb_save_review);
len -= sizeof(struct asset_nx2_usb_save_review);
/* skip non encrypted review area */
buf += sizeof(struct asset_nx2_usb_save_review);
len -= sizeof(struct asset_nx2_usb_save_review);
for (size_t a = len - 1; a > 0; --a) {
buf[a] = (buf[a] ^ buf[a - 1]) + ((a * 1234567) >> 8);
}
for (size_t a = len - 1; a > 0; --a) {
buf[a] = (buf[a] ^ buf[a - 1]) + ((a * 1234567) >> 8);
}
}
void asset_nx2_usb_save_encrypt(uint8_t* buf, size_t len)
void asset_nx2_usb_save_encrypt(uint8_t *buf, size_t len)
{
/* skip non encrypted review area */
buf += sizeof(struct asset_nx2_usb_save_review);
len -= sizeof(struct asset_nx2_usb_save_review);
/* skip non encrypted review area */
buf += sizeof(struct asset_nx2_usb_save_review);
len -= sizeof(struct asset_nx2_usb_save_review);
for (size_t a = 1; a < len; ++a) {
buf[a] = (buf[a] - ((a * 1234567) >> 8)) ^ buf[a - 1];
}
for (size_t a = 1; a < len; ++a) {
buf[a] = (buf[a] - ((a * 1234567) >> 8)) ^ buf[a - 1];
}
}
+84 -84
View File
@@ -7,116 +7,116 @@
#define ASSET_NX2_USB_SAVE_SIZE 30780
enum asset_nx2_usb_save_limits {
ASSET_NX2_USB_SAVE_SERIAL_ID_MAX = 64,
ASSET_NX2_USB_SAVE_PLAYER_ID_MAX = 12,
ASSET_NX2_USB_SAVE_WORLDMAX_LOC_MAX = 128,
ASSET_NX2_USB_SAVE_SONG_MAX = 256,
ASSET_NX2_USB_SAVE_MISSION_MAX = 1024,
ASSET_NX2_USB_SAVE_BARRICADE_MAX = 16,
ASSET_NX2_USB_SAVE_EVENT_MAX = 128,
ASSET_NX2_USB_SAVE_WARP_MAX = 8,
ASSET_NX2_USB_SAVE_NUM_MODES = 5,
ASSET_NX2_USB_SAVE_SERIAL_ID_MAX = 64,
ASSET_NX2_USB_SAVE_PLAYER_ID_MAX = 12,
ASSET_NX2_USB_SAVE_WORLDMAX_LOC_MAX = 128,
ASSET_NX2_USB_SAVE_SONG_MAX = 256,
ASSET_NX2_USB_SAVE_MISSION_MAX = 1024,
ASSET_NX2_USB_SAVE_BARRICADE_MAX = 16,
ASSET_NX2_USB_SAVE_EVENT_MAX = 128,
ASSET_NX2_USB_SAVE_WARP_MAX = 8,
ASSET_NX2_USB_SAVE_NUM_MODES = 5,
};
struct asset_nx2_usb_save_time {
int16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t min;
uint16_t ms;
int16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t min;
uint16_t ms;
} __attribute__((__packed__));
struct asset_nx2_usb_save_review {
char player_id[ASSET_NX2_USB_SAVE_PLAYER_ID_MAX];
int32_t mileage;
int32_t reward_count;
int32_t worldmax_count;
int32_t play_count;
char worldmax_current_land[ASSET_NX2_USB_SAVE_WORLDMAX_LOC_MAX];
char worldmax_current_mission[ASSET_NX2_USB_SAVE_WORLDMAX_LOC_MAX];
int32_t kcal;
int32_t v02;
char player_id[ASSET_NX2_USB_SAVE_PLAYER_ID_MAX];
int32_t mileage;
int32_t reward_count;
int32_t worldmax_count;
int32_t play_count;
char worldmax_current_land[ASSET_NX2_USB_SAVE_WORLDMAX_LOC_MAX];
char worldmax_current_mission[ASSET_NX2_USB_SAVE_WORLDMAX_LOC_MAX];
int32_t kcal;
int32_t v02;
} __attribute__((__packed__));
struct asset_nx2_usb_save_stats {
uint32_t adler32;
char usb_serial[ASSET_NX2_USB_SAVE_SERIAL_ID_MAX];
struct asset_nx2_usb_save_time timestamp;
int32_t avatar_id;
int32_t rank;
int32_t country_id;
char player_id[ASSET_NX2_USB_SAVE_PLAYER_ID_MAX];
int32_t mileage;
int32_t play_count;
int32_t kcal;
int32_t v02;
int32_t worldmax_map_position;
int32_t reward_count;
int32_t worldmax_count;
uint32_t adler32;
char usb_serial[ASSET_NX2_USB_SAVE_SERIAL_ID_MAX];
struct asset_nx2_usb_save_time timestamp;
int32_t avatar_id;
int32_t rank;
int32_t country_id;
char player_id[ASSET_NX2_USB_SAVE_PLAYER_ID_MAX];
int32_t mileage;
int32_t play_count;
int32_t kcal;
int32_t v02;
int32_t worldmax_map_position;
int32_t reward_count;
int32_t worldmax_count;
struct {
/* bits 0-4 for modes/stepcharts */
uint8_t mode : 5;
/* unused bit */
uint8_t unused : 1;
/* bit 6 song itself */
uint8_t song : 1;
/* bit 7 reveal flag */
uint8_t reveal : 1;
} song_unlocks[ASSET_NX2_USB_SAVE_SONG_MAX] __attribute__((__packed__));
struct {
/* bits 0-4 for modes/stepcharts */
uint8_t mode : 5;
/* unused bit */
uint8_t unused : 1;
/* bit 6 song itself */
uint8_t song : 1;
/* bit 7 reveal flag */
uint8_t reveal : 1;
} song_unlocks[ASSET_NX2_USB_SAVE_SONG_MAX] __attribute__((__packed__));
struct {
uint8_t clear_flags_directions : 4;
uint8_t clear_flag_mission : 1;
uint8_t unused : 3;
} worldmax_mission_unlocks[ASSET_NX2_USB_SAVE_MISSION_MAX]
__attribute__((__packed__));
struct {
uint8_t clear_flags_directions : 4;
uint8_t clear_flag_mission : 1;
uint8_t unused : 3;
} worldmax_mission_unlocks[ASSET_NX2_USB_SAVE_MISSION_MAX]
__attribute__((__packed__));
int32_t worldmax_high_score[ASSET_NX2_USB_SAVE_MISSION_MAX];
int32_t worldmax_challenge[ASSET_NX2_USB_SAVE_MISSION_MAX];
int32_t worldmax_high_score[ASSET_NX2_USB_SAVE_MISSION_MAX];
int32_t worldmax_challenge[ASSET_NX2_USB_SAVE_MISSION_MAX];
struct {
uint8_t flag_open : 1;
uint8_t unused : 7;
} worldmax_barricade[ASSET_NX2_USB_SAVE_BARRICADE_MAX]
__attribute__((__packed__));
struct {
uint8_t flag_open : 1;
uint8_t unused : 7;
} worldmax_barricade[ASSET_NX2_USB_SAVE_BARRICADE_MAX]
__attribute__((__packed__));
struct {
uint8_t flag_cleared : 1;
uint8_t unused : 7;
} worldmax_event[ASSET_NX2_USB_SAVE_EVENT_MAX] __attribute__((__packed__));
struct {
uint8_t flag_cleared : 1;
uint8_t unused : 7;
} worldmax_event[ASSET_NX2_USB_SAVE_EVENT_MAX] __attribute__((__packed__));
struct {
uint8_t direction_clear : 4;
uint8_t clear : 1;
uint8_t unused : 3;
} worldmax_warp[ASSET_NX2_USB_SAVE_WARP_MAX] __attribute__((__packed__));
struct {
uint8_t direction_clear : 4;
uint8_t clear : 1;
uint8_t unused : 3;
} worldmax_warp[ASSET_NX2_USB_SAVE_WARP_MAX] __attribute__((__packed__));
char worldmax_current_land[ASSET_NX2_USB_SAVE_WORLDMAX_LOC_MAX];
char worldmax_current_mission[ASSET_NX2_USB_SAVE_WORLDMAX_LOC_MAX];
char worldmax_current_land[ASSET_NX2_USB_SAVE_WORLDMAX_LOC_MAX];
char worldmax_current_mission[ASSET_NX2_USB_SAVE_WORLDMAX_LOC_MAX];
struct {
int32_t score;
char player_id[ASSET_NX2_USB_SAVE_PLAYER_ID_MAX];
} song_scores[ASSET_NX2_USB_SAVE_SONG_MAX][ASSET_NX2_USB_SAVE_NUM_MODES]
__attribute__((__packed__));
struct {
int32_t score;
char player_id[ASSET_NX2_USB_SAVE_PLAYER_ID_MAX];
} song_scores[ASSET_NX2_USB_SAVE_SONG_MAX][ASSET_NX2_USB_SAVE_NUM_MODES]
__attribute__((__packed__));
} __attribute__((__packed__));
struct asset_nx2_usb_save {
struct asset_nx2_usb_save_review review;
struct asset_nx2_usb_save_stats stats;
struct asset_nx2_usb_save_review review;
struct asset_nx2_usb_save_stats stats;
} __attribute__((__packed__));
struct asset_nx2_usb_save* asset_nx2_usb_save_new(void);
struct asset_nx2_usb_save *asset_nx2_usb_save_new(void);
// update checksum and prepare profile to get encrypted
void asset_nx2_usb_save_finalize(struct asset_nx2_usb_save* save);
void asset_nx2_usb_save_finalize(struct asset_nx2_usb_save *save);
char* asset_nx2_usb_save_to_string(const struct asset_nx2_usb_save* save);
char *asset_nx2_usb_save_to_string(const struct asset_nx2_usb_save *save);
void asset_nx2_usb_save_decrypt(uint8_t* buf, size_t len);
void asset_nx2_usb_save_decrypt(uint8_t *buf, size_t len);
void asset_nx2_usb_save_encrypt(uint8_t* buf, size_t len);
void asset_nx2_usb_save_encrypt(uint8_t *buf, size_t len);
#endif
+70 -64
View File
@@ -7,94 +7,100 @@
#include "util.h"
struct asset_nx2_usb_rank* asset_nx2_usb_rank_load_from_file(const char* path,
bool encrypted)
struct asset_nx2_usb_rank *
asset_nx2_usb_rank_load_from_file(const char *path, bool encrypted)
{
struct asset_nx2_usb_rank* rank;
size_t size;
struct asset_nx2_usb_rank *rank;
size_t size;
if (!util_file_load(path, (void**) &rank, &size, false)) {
log_error("Loading nx2 rank file %s failed", path);
return NULL;
}
if (!util_file_load(path, (void **) &rank, &size, false)) {
log_error("Loading nx2 rank file %s failed", path);
return NULL;
}
if (size != sizeof(struct asset_nx2_usb_rank)) {
log_error("Invalid size of nx2 rank file %s: %d != %d", path, size,
sizeof(struct asset_nx2_usb_rank));
free(rank);
return NULL;
}
if (size != sizeof(struct asset_nx2_usb_rank)) {
log_error(
"Invalid size of nx2 rank file %s: %d != %d",
path,
size,
sizeof(struct asset_nx2_usb_rank));
free(rank);
return NULL;
}
if (encrypted) {
asset_nx2_usb_rank_decrypt((uint8_t*) rank, size);
}
if (encrypted) {
asset_nx2_usb_rank_decrypt((uint8_t *) rank, size);
}
return rank;
return rank;
}
bool asset_nx2_usb_rank_save_to_file(const char* path,
const struct asset_nx2_usb_rank* rank, bool encrypt)
bool asset_nx2_usb_rank_save_to_file(
const char *path, const struct asset_nx2_usb_rank *rank, bool encrypt)
{
struct asset_nx2_usb_rank rank_enc;
struct asset_nx2_usb_rank rank_enc;
memcpy(&rank_enc, rank, sizeof(struct asset_nx2_usb_rank));
memcpy(&rank_enc, rank, sizeof(struct asset_nx2_usb_rank));
if (encrypt) {
asset_nx2_usb_rank_encrypt((uint8_t*) &rank_enc,
sizeof(struct asset_nx2_usb_rank));
}
if (encrypt) {
asset_nx2_usb_rank_encrypt(
(uint8_t *) &rank_enc, sizeof(struct asset_nx2_usb_rank));
}
if (!util_file_save(path, (void**) &rank_enc,
sizeof(struct asset_nx2_usb_rank))) {
log_error("Storing nx2 rank data to %s failed", path);
return false;
}
if (!util_file_save(
path, (void **) &rank_enc, sizeof(struct asset_nx2_usb_rank))) {
log_error("Storing nx2 rank data to %s failed", path);
return false;
}
return true;
return true;
}
struct asset_nx2_usb_save* asset_nx2_usb_save_load_from_file(const char* path,
bool encrypted)
struct asset_nx2_usb_save *
asset_nx2_usb_save_load_from_file(const char *path, bool encrypted)
{
struct asset_nx2_usb_save* save;
size_t size;
struct asset_nx2_usb_save *save;
size_t size;
if (!util_file_load(path, (void**) &save, &size, false)) {
log_error("Loading nx2 save file %s failed", path);
return NULL;
}
if (!util_file_load(path, (void **) &save, &size, false)) {
log_error("Loading nx2 save file %s failed", path);
return NULL;
}
if (size != sizeof(struct asset_nx2_usb_save)) {
log_error("Invalid size of nx2 save file %s: %d != %d", path, size,
sizeof(struct asset_nx2_usb_save));
free(save);
return NULL;
}
if (size != sizeof(struct asset_nx2_usb_save)) {
log_error(
"Invalid size of nx2 save file %s: %d != %d",
path,
size,
sizeof(struct asset_nx2_usb_save));
free(save);
return NULL;
}
if (encrypted) {
asset_nx2_usb_save_decrypt((uint8_t*) save, size);
}
if (encrypted) {
asset_nx2_usb_save_decrypt((uint8_t *) save, size);
}
return save;
return save;
}
bool asset_nx2_usb_save_save_to_file(const char* path,
const struct asset_nx2_usb_save* save, bool encrypt)
bool asset_nx2_usb_save_save_to_file(
const char *path, const struct asset_nx2_usb_save *save, bool encrypt)
{
struct asset_nx2_usb_save save_enc;
struct asset_nx2_usb_save save_enc;
memcpy(&save_enc, save, sizeof(struct asset_nx2_usb_save));
memcpy(&save_enc, save, sizeof(struct asset_nx2_usb_save));
if (encrypt) {
asset_nx2_usb_save_encrypt((uint8_t*) &save_enc,
sizeof(struct asset_nx2_usb_save));
}
if (encrypt) {
asset_nx2_usb_save_encrypt(
(uint8_t *) &save_enc, sizeof(struct asset_nx2_usb_save));
}
if (!util_file_save(path, (const void*) &save_enc,
sizeof(struct asset_nx2_usb_save))) {
log_error("Storing nx2 save data to %s failed", path);
return false;
}
if (!util_file_save(
path, (const void *) &save_enc, sizeof(struct asset_nx2_usb_save))) {
log_error("Storing nx2 save data to %s failed", path);
return false;
}
return true;
return true;
}
+8 -4
View File
@@ -7,15 +7,19 @@
#include "usb-save.h"
// load from file and decrypt, returns decrypted struct
struct asset_nx2_usb_rank* asset_nx2_usb_rank_load_from_file(const char* path, bool encrypted);
struct asset_nx2_usb_rank *
asset_nx2_usb_rank_load_from_file(const char *path, bool encrypted);
// takes decrypted rank data, encrypts it and writes it to file
bool asset_nx2_usb_rank_save_to_file(const char* path, const struct asset_nx2_usb_rank* rank, bool encrypt);
bool asset_nx2_usb_rank_save_to_file(
const char *path, const struct asset_nx2_usb_rank *rank, bool encrypt);
// load from file and decrypt, returns decrypted struct
struct asset_nx2_usb_save* asset_nx2_usb_save_load_from_file(const char* path, bool encrypted);
struct asset_nx2_usb_save *
asset_nx2_usb_save_load_from_file(const char *path, bool encrypted);
// takes decrypted save data, encrypts it and writes it to file
bool asset_nx2_usb_save_save_to_file(const char* path, const struct asset_nx2_usb_save* save, bool encrypt);
bool asset_nx2_usb_save_save_to_file(
const char *path, const struct asset_nx2_usb_save *save, bool encrypt);
#endif
+132 -128
View File
@@ -9,146 +9,150 @@
#include "util/str.h"
int main(int argc, char** argv)
int main(int argc, char **argv)
{
int ret;
char* rank_path;
char* save_path;
int ret;
char *rank_path;
char *save_path;
if (argc < 3) {
printf("Usage: %s [cmd: new, dec, enc, dump] "
"[path containing nx2rank.bin nx2save.bin]\n", argv[0]);
return -1;
if (argc < 3) {
printf(
"Usage: %s [cmd: new, dec, enc, dump] "
"[path containing nx2rank.bin nx2save.bin]\n",
argv[0]);
return -1;
}
ret = 0;
rank_path = util_str_merge(argv[2], "nx2rank.bin");
save_path = util_str_merge(argv[2], "nx2save.bin");
if (!strcmp(argv[1], "new")) {
struct asset_nx2_usb_rank *rank = asset_nx2_usb_rank_new();
struct asset_nx2_usb_save *save = asset_nx2_usb_save_new();
asset_nx2_usb_rank_finalize(rank);
asset_nx2_usb_save_finalize(save);
if (!asset_nx2_usb_rank_save_to_file(rank_path, rank, true)) {
fprintf(stderr, "Creating rank file %s failed\n", rank_path);
ret = -2;
}
ret = 0;
if (!asset_nx2_usb_save_save_to_file(save_path, save, true)) {
fprintf(stderr, "Creating save file %s failed\n", save_path);
ret = -3;
}
rank_path = util_str_merge(argv[2], "nx2rank.bin");
save_path = util_str_merge(argv[2], "nx2save.bin");
free(rank);
free(save);
} else {
struct asset_nx2_usb_rank *rank;
struct asset_nx2_usb_save *save;
bool encrypted;
if (!strcmp(argv[1], "new")) {
struct asset_nx2_usb_rank* rank = asset_nx2_usb_rank_new();
struct asset_nx2_usb_save* save = asset_nx2_usb_save_new();
if (!strcmp(argv[1], "enc")) {
char *tmp;
asset_nx2_usb_rank_finalize(rank);
asset_nx2_usb_save_finalize(save);
encrypted = false;
if (!asset_nx2_usb_rank_save_to_file(rank_path, rank, true)) {
fprintf(stderr, "Creating rank file %s failed\n", rank_path);
ret = -2;
}
tmp = util_str_merge(rank_path, ".dec");
free(rank_path);
rank_path = tmp;
if (!asset_nx2_usb_save_save_to_file(save_path, save, true)) {
fprintf(stderr, "Creating save file %s failed\n", save_path);
ret = -3;
}
free(rank);
free(save);
tmp = util_str_merge(save_path, ".dec");
free(save_path);
save_path = tmp;
} else {
struct asset_nx2_usb_rank* rank;
struct asset_nx2_usb_save* save;
bool encrypted;
if (!strcmp(argv[1], "enc")) {
char* tmp;
encrypted = false;
tmp = util_str_merge(rank_path, ".dec");
free(rank_path);
rank_path = tmp;
tmp = util_str_merge(save_path, ".dec");
free(save_path);
save_path = tmp;
} else {
encrypted = true;
}
rank = asset_nx2_usb_rank_load_from_file(rank_path, encrypted);
save = asset_nx2_usb_save_load_from_file(save_path, encrypted);
if (!rank) {
fprintf(stderr, "Loading %s failed", rank_path);
ret = -4;
goto cleanup;
}
if (!save) {
fprintf(stderr, "Loading %s failed", save_path);
ret = -5;
free(rank);
goto cleanup;
}
if (!strcmp(argv[1], "dec")) {
char* rank_path_dec;
char* save_path_dec;
rank_path_dec = util_str_merge(rank_path, ".dec");
save_path_dec = util_str_merge(save_path, ".dec");
if (!asset_nx2_usb_rank_save_to_file(rank_path_dec, rank, false)) {
fprintf(stderr, "Saving decrypted rank file to %s failed\n",
rank_path_dec);
ret = -6;
}
if (!asset_nx2_usb_save_save_to_file(save_path_dec, save, false)) {
fprintf(stderr, "Saving decrypted save file to %s failed\n",
save_path_dec);
ret = -7;
}
free(rank_path_dec);
free(save_path_dec);
} else if (!strcmp(argv[1], "enc")) {
char* rank_path_enc;
char* save_path_enc;
rank_path_enc = util_str_merge(rank_path, ".enc");
save_path_enc = util_str_merge(save_path, ".enc");
if (!asset_nx2_usb_rank_save_to_file(rank_path_enc, rank, true)) {
fprintf(stderr, "Saving encrypted rank file to %s failed\n",
rank_path_enc);
ret = -6;
}
if (!asset_nx2_usb_save_save_to_file(save_path_enc, save, true)) {
fprintf(stderr, "Saving encrypted save file to %s failed\n",
save_path_enc);
ret = -7;
}
free(rank_path_enc);
free(save_path_enc);
} else if (!strcmp(argv[1], "dump")) {
char* rank_str;
char* save_str;
rank_str = asset_nx2_usb_rank_to_string(rank);
save_str = asset_nx2_usb_save_to_string(save);
printf("----------------- rank -----------------\n"
"%s----------------- save -----------------\n%s",
rank_str, save_str);
free(rank_str);
free(save_str);
} else {
fprintf(stderr, "Unknown command %s\n", argv[1]);
ret = -4;
}
free(rank);
free(save);
encrypted = true;
}
rank = asset_nx2_usb_rank_load_from_file(rank_path, encrypted);
save = asset_nx2_usb_save_load_from_file(save_path, encrypted);
if (!rank) {
fprintf(stderr, "Loading %s failed", rank_path);
ret = -4;
goto cleanup;
}
if (!save) {
fprintf(stderr, "Loading %s failed", save_path);
ret = -5;
free(rank);
goto cleanup;
}
if (!strcmp(argv[1], "dec")) {
char *rank_path_dec;
char *save_path_dec;
rank_path_dec = util_str_merge(rank_path, ".dec");
save_path_dec = util_str_merge(save_path, ".dec");
if (!asset_nx2_usb_rank_save_to_file(rank_path_dec, rank, false)) {
fprintf(
stderr, "Saving decrypted rank file to %s failed\n", rank_path_dec);
ret = -6;
}
if (!asset_nx2_usb_save_save_to_file(save_path_dec, save, false)) {
fprintf(
stderr, "Saving decrypted save file to %s failed\n", save_path_dec);
ret = -7;
}
free(rank_path_dec);
free(save_path_dec);
} else if (!strcmp(argv[1], "enc")) {
char *rank_path_enc;
char *save_path_enc;
rank_path_enc = util_str_merge(rank_path, ".enc");
save_path_enc = util_str_merge(save_path, ".enc");
if (!asset_nx2_usb_rank_save_to_file(rank_path_enc, rank, true)) {
fprintf(
stderr, "Saving encrypted rank file to %s failed\n", rank_path_enc);
ret = -6;
}
if (!asset_nx2_usb_save_save_to_file(save_path_enc, save, true)) {
fprintf(
stderr, "Saving encrypted save file to %s failed\n", save_path_enc);
ret = -7;
}
free(rank_path_enc);
free(save_path_enc);
} else if (!strcmp(argv[1], "dump")) {
char *rank_str;
char *save_str;
rank_str = asset_nx2_usb_rank_to_string(rank);
save_str = asset_nx2_usb_save_to_string(save);
printf(
"----------------- rank -----------------\n"
"%s----------------- save -----------------\n%s",
rank_str,
save_str);
free(rank_str);
free(save_str);
} else {
fprintf(stderr, "Unknown command %s\n", argv[1]);
ret = -4;
}
free(rank);
free(save);
}
cleanup:
free(rank_path);
free(save_path);
free(rank_path);
free(save_path);
return ret;
return ret;
}
+69 -64
View File
@@ -8,96 +8,101 @@
#include "usb-rank.h"
struct asset_nxa_usb_rank* asset_nxa_usb_rank_new(void)
struct asset_nxa_usb_rank *asset_nxa_usb_rank_new(void)
{
struct asset_nxa_usb_rank* rank;
struct asset_nxa_usb_rank *rank;
rank = (struct asset_nxa_usb_rank*)
util_xmalloc(sizeof(struct asset_nxa_usb_rank));
rank = (struct asset_nxa_usb_rank *) util_xmalloc(
sizeof(struct asset_nxa_usb_rank));
memset(rank, 0, sizeof(struct asset_nxa_usb_rank));
memset(rank, 0, sizeof(struct asset_nxa_usb_rank));
return rank;
return rank;
}
void asset_nxa_usb_rank_finalize(struct asset_nxa_usb_rank* rank)
void asset_nxa_usb_rank_finalize(struct asset_nxa_usb_rank *rank)
{
rank->adler32 = util_adler32_calc(1, ((const uint8_t*) rank) + 4,
sizeof(struct asset_nxa_usb_rank) - 4);
rank->adler32 = util_adler32_calc(
1, ((const uint8_t *) rank) + 4, sizeof(struct asset_nxa_usb_rank) - 4);
}
char* asset_nxa_usb_rank_to_string(const struct asset_nxa_usb_rank* rank)
char *asset_nxa_usb_rank_to_string(const struct asset_nxa_usb_rank *rank)
{
char* buffer;
char* buffer2;
char* merged;
char* usb_ser;
char *buffer;
char *buffer2;
char *merged;
char *usb_ser;
buffer = (char*) util_xmalloc(512);
memset(buffer, 0, 512);
buffer = (char *) util_xmalloc(512);
memset(buffer, 0, 512);
usb_ser = util_str_buffer((const uint8_t*) rank->usb_serial,
ASSET_NXA_USB_RANK_USB_SERIAL_LEN);
usb_ser = util_str_buffer(
(const uint8_t *) rank->usb_serial, ASSET_NXA_USB_RANK_USB_SERIAL_LEN);
util_str_format(buffer, 512,
"adler32: 0x%X\n"
// "usb_serial: %s\n",
"num_rankings: %d\n"
"ranking entries:\n",
rank->adler32,
// usb_ser,
rank->num_rankings);
util_str_format(
buffer,
512,
"adler32: 0x%X\n"
// "usb_serial: %s\n",
"num_rankings: %d\n"
"ranking entries:\n",
rank->adler32,
// usb_ser,
rank->num_rankings);
for (uint32_t i = 0; i < ASSET_NXA_USB_RANK_MAX_RANK_ENTRIES; i++) {
for (uint32_t i = 0; i < ASSET_NXA_USB_RANK_MAX_RANK_ENTRIES; i++) {
for (uint32_t j = 0; j < ASSET_NXA_USB_RANK_MAX_STAGES; j++) {
buffer2 = (char*) util_xmalloc(512);
memset(buffer2, 0, 512);
for (uint32_t j = 0; j < ASSET_NXA_USB_RANK_MAX_STAGES; j++) {
buffer2 = (char *) util_xmalloc(512);
memset(buffer2, 0, 512);
util_str_format(buffer2, 512,
"%d/%d:\n"
"game_mode: %d\n"
"play_order: %d\n"
"play_score: %d\n"
"grade: %d\n"
"mileage: %d\n"
"play_time: %f\n"
"kcal: %f\n"
"v02: %f\n",
i, j,
rank->entries[i][j].game_mode,
rank->entries[i][j].play_order,
rank->entries[i][j].play_score,
rank->entries[i][j].grade,
rank->entries[i][j].mileage,
rank->entries[i][j].play_time,
rank->entries[i][j].kcal,
rank->entries[i][j].v02);
util_str_format(
buffer2,
512,
"%d/%d:\n"
"game_mode: %d\n"
"play_order: %d\n"
"play_score: %d\n"
"grade: %d\n"
"mileage: %d\n"
"play_time: %f\n"
"kcal: %f\n"
"v02: %f\n",
i,
j,
rank->entries[i][j].game_mode,
rank->entries[i][j].play_order,
rank->entries[i][j].play_score,
rank->entries[i][j].grade,
rank->entries[i][j].mileage,
rank->entries[i][j].play_time,
rank->entries[i][j].kcal,
rank->entries[i][j].v02);
merged = util_str_merge(buffer, buffer2);
merged = util_str_merge(buffer, buffer2);
free(buffer);
free(buffer2);
free(buffer);
free(buffer2);
buffer = merged;
}
buffer = merged;
}
}
free(usb_ser);
free(usb_ser);
return buffer;
return buffer;
}
void asset_nxa_usb_rank_decrypt(uint8_t* buf, size_t len)
void asset_nxa_usb_rank_decrypt(uint8_t *buf, size_t len)
{
for (size_t a = len - 1; a > 0; --a) {
buf[a] = (buf[a] ^ buf[a - 1]) + ((a * 1234567) >> 8);
}
for (size_t a = len - 1; a > 0; --a) {
buf[a] = (buf[a] ^ buf[a - 1]) + ((a * 1234567) >> 8);
}
}
void asset_nxa_usb_rank_encrypt(uint8_t* buf, size_t len)
void asset_nxa_usb_rank_encrypt(uint8_t *buf, size_t len)
{
for (size_t a = 1; a < len; ++a) {
buf[a] = (buf[a] - ((a * 1234567) >> 8)) ^ buf[a - 1];
}
for (size_t a = 1; a < len; ++a) {
buf[a] = (buf[a] - ((a * 1234567) >> 8)) ^ buf[a - 1];
}
}
+21 -21
View File
@@ -5,39 +5,39 @@
#include <stdlib.h>
enum asset_nxa_usb_rank_sizes {
ASSET_NXA_USB_RANK_MAX_STAGES = 3,
ASSET_NXA_USB_RANK_MAX_RANK_ENTRIES = 256,
ASSET_NXA_USB_RANK_USB_SERIAL_LEN = 64,
ASSET_NXA_USB_RANK_MAX_STAGES = 3,
ASSET_NXA_USB_RANK_MAX_RANK_ENTRIES = 256,
ASSET_NXA_USB_RANK_USB_SERIAL_LEN = 64,
};
struct asset_nxa_usb_rank_entry {
int32_t game_mode;
int32_t play_order;
int32_t play_score;
int32_t grade;
int32_t mileage;
float play_time;
float kcal;
float v02;
int32_t game_mode;
int32_t play_order;
int32_t play_score;
int32_t grade;
int32_t mileage;
float play_time;
float kcal;
float v02;
} __attribute__((__packed__));
struct asset_nxa_usb_rank {
uint32_t adler32;
char usb_serial[ASSET_NXA_USB_RANK_USB_SERIAL_LEN];
uint32_t num_rankings;
struct asset_nxa_usb_rank_entry
entries[ASSET_NXA_USB_RANK_MAX_RANK_ENTRIES][ASSET_NXA_USB_RANK_MAX_STAGES];
uint32_t adler32;
char usb_serial[ASSET_NXA_USB_RANK_USB_SERIAL_LEN];
uint32_t num_rankings;
struct asset_nxa_usb_rank_entry entries[ASSET_NXA_USB_RANK_MAX_RANK_ENTRIES]
[ASSET_NXA_USB_RANK_MAX_STAGES];
} __attribute__((__packed__));
struct asset_nxa_usb_rank* asset_nxa_usb_rank_new(void);
struct asset_nxa_usb_rank *asset_nxa_usb_rank_new(void);
// update checksum and prepare profile to get encrypted
void asset_nxa_usb_rank_finalize(struct asset_nxa_usb_rank* rank);
void asset_nxa_usb_rank_finalize(struct asset_nxa_usb_rank *rank);
char* asset_nxa_usb_rank_to_string(const struct asset_nxa_usb_rank* rank);
char *asset_nxa_usb_rank_to_string(const struct asset_nxa_usb_rank *rank);
void asset_nxa_usb_rank_decrypt(uint8_t* buf, size_t len);
void asset_nxa_usb_rank_decrypt(uint8_t *buf, size_t len);
void asset_nxa_usb_rank_encrypt(uint8_t* buf, size_t len);
void asset_nxa_usb_rank_encrypt(uint8_t *buf, size_t len);
#endif
+410 -381
View File
@@ -8,450 +8,479 @@
#include "usb-save.h"
static char* asset_nxa_usb_save_time_to_string(
const struct asset_nxa_usb_save_time* time)
static char *
asset_nxa_usb_save_time_to_string(const struct asset_nxa_usb_save_time *time)
{
char* buffer;
char *buffer;
buffer = (char*) util_xmalloc(128);
memset(buffer, 0, 128);
buffer = (char *) util_xmalloc(128);
memset(buffer, 0, 128);
util_str_format(buffer, 128,
"year: %d\n"
"month: %d\n"
"day: %d\n"
"hour: %d\n"
"min: %d\n"
"ms: %d\n",
time->year,
time->month,
time->day,
time->hour,
time->min,
time->ms);
util_str_format(
buffer,
128,
"year: %d\n"
"month: %d\n"
"day: %d\n"
"hour: %d\n"
"min: %d\n"
"ms: %d\n",
time->year,
time->month,
time->day,
time->hour,
time->min,
time->ms);
return buffer;
return buffer;
}
static char* asset_nxa_usb_save_review_to_string(
const struct asset_nxa_usb_save_review* review)
static char *asset_nxa_usb_save_review_to_string(
const struct asset_nxa_usb_save_review *review)
{
char* buffer;
char* land;
char* mission;
char* timestamp;
char *buffer;
char *land;
char *mission;
char *timestamp;
buffer = (char*) util_xmalloc(1024);
memset(buffer, 0, 1024);
buffer = (char *) util_xmalloc(1024);
memset(buffer, 0, 1024);
land = util_str_buffer((const uint8_t*) review->worldmax_current_land,
ASSET_NXA_USB_SAVE_WORLDMAX_LOC_MAX);
mission = util_str_buffer((const uint8_t*) review->worldmax_current_mission,
ASSET_NXA_USB_SAVE_WORLDMAX_LOC_MAX);
timestamp = asset_nxa_usb_save_time_to_string(&review->timestamp);
land = util_str_buffer(
(const uint8_t *) review->worldmax_current_land,
ASSET_NXA_USB_SAVE_WORLDMAX_LOC_MAX);
mission = util_str_buffer(
(const uint8_t *) review->worldmax_current_mission,
ASSET_NXA_USB_SAVE_WORLDMAX_LOC_MAX);
timestamp = asset_nxa_usb_save_time_to_string(&review->timestamp);
util_str_format(buffer, 1024,
">>> review:\n"
"player_id: %s\n"
"mileage: %d\n"
"reward_count: %d\n"
"worldmax_count: %d\n"
"play_count: %d\n"
"worldmax_current_land: %s\n"
"worldmax_current_mission: %s\n"
"kcal: %d\n"
"v02: %d\n",
"timestamp: \n%s",
"running_step: %d\n",
"play_time_minutes: %f\n",
"total_completion_percentage: %f\n",
"arcade_percentage: %f\n",
"brain_shower_percentage: %f\n",
"special_percentage: %f\n",
review->player_id,
review->mileage,
review->reward_count,
review->worldmax_count,
review->play_count,
land,
mission,
review->kcal,
review->v02,
timestamp,
review->running_step,
review->play_time_minutes,
review->total_completion_percentage,
review->arcade_percentage,
review->brain_shower_percentage,
review->special_percentage);
util_str_format(
buffer,
1024,
">>> review:\n"
"player_id: %s\n"
"mileage: %d\n"
"reward_count: %d\n"
"worldmax_count: %d\n"
"play_count: %d\n"
"worldmax_current_land: %s\n"
"worldmax_current_mission: %s\n"
"kcal: %d\n"
"v02: %d\n",
"timestamp: \n%s",
"running_step: %d\n",
"play_time_minutes: %f\n",
"total_completion_percentage: %f\n",
"arcade_percentage: %f\n",
"brain_shower_percentage: %f\n",
"special_percentage: %f\n",
review->player_id,
review->mileage,
review->reward_count,
review->worldmax_count,
review->play_count,
land,
mission,
review->kcal,
review->v02,
timestamp,
review->running_step,
review->play_time_minutes,
review->total_completion_percentage,
review->arcade_percentage,
review->brain_shower_percentage,
review->special_percentage);
free(land);
free(mission);
free(timestamp);
free(land);
free(mission);
free(timestamp);
return buffer;
return buffer;
}
static char* asset_nxa_usb_save_stats_to_string(
const struct asset_nxa_usb_save_stats* stats)
static char *
asset_nxa_usb_save_stats_to_string(const struct asset_nxa_usb_save_stats *stats)
{
char* merged;
char* buffer;
char* timestamp;
char* tmp;
char* tmp2;
const size_t buf_size = 16384;
char *merged;
char *buffer;
char *timestamp;
char *tmp;
char *tmp2;
const size_t buf_size = 16384;
merged = (char*) util_xmalloc(buf_size);
memset(merged, 0, buf_size);
merged = (char *) util_xmalloc(buf_size);
memset(merged, 0, buf_size);
buffer = (char*) util_xmalloc(buf_size);
memset(buffer, 0, buf_size);
buffer = (char *) util_xmalloc(buf_size);
memset(buffer, 0, buf_size);
timestamp = asset_nxa_usb_save_time_to_string(&stats->timestamp);
timestamp = asset_nxa_usb_save_time_to_string(&stats->timestamp);
util_str_format(merged, buf_size,
">>> stats:\n"
"adler32: 0x%X\n"
"usb_serial: %s\n"
"timestamp: %s"
"avatar_id: %d\n"
"rank: %d\n"
"country_id: %d\n"
"player_id: %s\n"
"mileage: %d\n"
"play_count: %d\n"
"kcal: %d\n"
"v02: %d\n"
"worldmax_map_position: 0x%X\n"
"reward_count: %d\n"
"worldmax_count: %d\n",
stats->adler32,
stats->usb_serial,
timestamp,
stats->avatar_id,
stats->rank,
stats->country_id,
stats->player_id,
stats->mileage,
stats->play_count,
stats->kcal,
stats->v02,
stats->worldmax_map_position,
stats->reward_count,
stats->worldmax_count);
util_str_format(
merged,
buf_size,
">>> stats:\n"
"adler32: 0x%X\n"
"usb_serial: %s\n"
"timestamp: %s"
"avatar_id: %d\n"
"rank: %d\n"
"country_id: %d\n"
"player_id: %s\n"
"mileage: %d\n"
"play_count: %d\n"
"kcal: %d\n"
"v02: %d\n"
"worldmax_map_position: 0x%X\n"
"reward_count: %d\n"
"worldmax_count: %d\n",
stats->adler32,
stats->usb_serial,
timestamp,
stats->avatar_id,
stats->rank,
stats->country_id,
stats->player_id,
stats->mileage,
stats->play_count,
stats->kcal,
stats->v02,
stats->worldmax_map_position,
stats->reward_count,
stats->worldmax_count);
free(timestamp);
free(timestamp);
tmp = util_str_merge(merged, "song_unlocks:\n");
tmp = util_str_merge(merged, "song_unlocks:\n");
free(merged);
merged = tmp;
free(merged);
merged = tmp;
for (uint32_t i = 0; i < ASSET_NXA_USB_SAVE_SONG_MAX; i++) {
for (uint32_t i = 0; i < ASSET_NXA_USB_SAVE_SONG_MAX; i++) {
util_str_format(buffer, buf_size,
"song slot: %d\n"
"mode: 0x%X\n"
"unused: 0x%X\n"
"song: %d\n"
"reveal: %d\n",
i,
stats->song_unlocks[i].mode,
stats->song_unlocks[i].unused,
stats->song_unlocks[i].song,
stats->song_unlocks[i].reveal);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NXA_USB_SAVE_MISSION_MAX; i++) {
util_str_format(buffer, buf_size,
"mission slot: %d\n"
"clear_flags_directions: 0x%X\n"
"clear_flag_mission: %d\n"
"unused: 0x%X\n",
i,
stats->worldmax_mission_unlocks[i].clear_flags_directions,
stats->worldmax_mission_unlocks[i].clear_flag_mission,
stats->worldmax_mission_unlocks[i].unused);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NXA_USB_SAVE_MISSION_MAX; i++) {
util_str_format(buffer, buf_size,
"worldmax_high_score %d: %d\n",
i,
stats->worldmax_high_score[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NXA_USB_SAVE_MISSION_MAX; i++) {
util_str_format(buffer, buf_size,
"worldmax_challenge %d: %d\n",
i,
stats->worldmax_challenge[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NXA_USB_SAVE_BARRICADE_MAX; i++) {
util_str_format(buffer, buf_size,
"worldmax_barricade %d:\n"
"flag_open: %d\n"
"unused: 0x%X\n",
i,
stats->worldmax_barricade[i].flag_open,
stats->worldmax_barricade[i].unused);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NXA_USB_SAVE_EVENT_MAX; i++) {
util_str_format(buffer, buf_size,
"worldmax_event %d:\n"
"flag_cleared: %d\n"
"unused: 0x%X\n",
i,
stats->worldmax_event[i].flag_cleared,
stats->worldmax_event[i].unused);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NXA_USB_SAVE_WARP_MAX; i++) {
util_str_format(buffer, buf_size,
"worldmax_warp %d:\n"
"direction_clear: 0x%X\n"
"clear: %d\n",
"unused: 0x%X\n",
i,
stats->worldmax_warp[i].direction_clear,
stats->worldmax_warp[i].clear,
stats->worldmax_warp[i].unused);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NXA_USB_SAVE_WORLDMAX_LOC_MAX; i++) {
util_str_format(buffer, buf_size,
"worldmax_current_land %d: %d\n",
i,
stats->worldmax_current_land[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NXA_USB_SAVE_WORLDMAX_LOC_MAX; i++) {
util_str_format(buffer, buf_size,
"worldmax_current_mission %d: %d\n",
i,
stats->worldmax_current_mission[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NXA_USB_SAVE_SONG_MAX; i++) {
for (uint32_t j = 0; j < ASSET_NXA_USB_SAVE_NUM_MODES; j++) {
util_str_format(buffer, buf_size,
"song_scores %d/%d:\n"
"score: %d\n"
"player_id: %s\n",
i,
j,
stats->song_scores[i][j].score,
stats->song_scores[i][j].player_id);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
}
/* ------------- */
util_str_format(buffer, buf_size,
"security_dongle_mfgid 0x%X\n"
"unlock_signal: 0x%X\n"
"running_steps: %d\n"
"total_play_time_min: %f\n"
"total_completion_percentage: %f\n"
"arcade_completion_percentage: %f\n"
"brain_shower_completion_percentage: %f\n"
"special_stage_completion_percentage: %f\n",
stats->security_dongle_mfgid,
stats->unlock_signal,
stats->running_steps,
stats->total_play_time_min,
stats->total_completion_percentage,
stats->arcade_completion_percentage,
stats->brain_shower_completion_percentage,
stats->special_stage_completion_percentage);
util_str_format(
buffer,
buf_size,
"song slot: %d\n"
"mode: 0x%X\n"
"unused: 0x%X\n"
"song: %d\n"
"reveal: %d\n",
i,
stats->song_unlocks[i].mode,
stats->song_unlocks[i].unused,
stats->song_unlocks[i].song,
stats->song_unlocks[i].reveal);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
/* ------------- */
tmp2 = util_str_buffer(stats->unkn_some_map_scores_to_song_ids,
4096);
for (uint32_t i = 0; i < ASSET_NXA_USB_SAVE_MISSION_MAX; i++) {
util_str_format(buffer, buf_size,
"unkn_some_map_scores_to_song_ids: %s\n",
tmp2);
tmp = util_str_merge(merged, buffer);
free(tmp2);
free(merged);
merged = tmp;
/* ------------- */
tmp2 = util_str_buffer(stats->unkn2, sizeof(stats->unkn2));
util_str_format(buffer, buf_size,
"unkn2: %s\n",
tmp2);
tmp = util_str_merge(merged, buffer);
free(tmp2);
free(merged);
merged = tmp;
/* ------------- */
util_str_format(buffer, buf_size,
"break_item_slot 0x%X\n"
"func_item_slot: 0x%X\n"
"bga_item_slot: 0x%X\n"
"time_item_slot: 0x%X\n"
"unknown: 0x%X\n",
stats->break_item_slot,
stats->func_item_slot,
stats->bga_item_slot,
stats->time_item_slot,
stats->unknown);
util_str_format(
buffer,
buf_size,
"mission slot: %d\n"
"clear_flags_directions: 0x%X\n"
"clear_flag_mission: %d\n"
"unused: 0x%X\n",
i,
stats->worldmax_mission_unlocks[i].clear_flags_directions,
stats->worldmax_mission_unlocks[i].clear_flag_mission,
stats->worldmax_mission_unlocks[i].unused);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
free(buffer);
for (uint32_t i = 0; i < ASSET_NXA_USB_SAVE_MISSION_MAX; i++) {
return merged;
util_str_format(
buffer,
buf_size,
"worldmax_high_score %d: %d\n",
i,
stats->worldmax_high_score[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NXA_USB_SAVE_MISSION_MAX; i++) {
util_str_format(
buffer,
buf_size,
"worldmax_challenge %d: %d\n",
i,
stats->worldmax_challenge[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NXA_USB_SAVE_BARRICADE_MAX; i++) {
util_str_format(
buffer,
buf_size,
"worldmax_barricade %d:\n"
"flag_open: %d\n"
"unused: 0x%X\n",
i,
stats->worldmax_barricade[i].flag_open,
stats->worldmax_barricade[i].unused);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NXA_USB_SAVE_EVENT_MAX; i++) {
util_str_format(
buffer,
buf_size,
"worldmax_event %d:\n"
"flag_cleared: %d\n"
"unused: 0x%X\n",
i,
stats->worldmax_event[i].flag_cleared,
stats->worldmax_event[i].unused);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NXA_USB_SAVE_WARP_MAX; i++) {
util_str_format(
buffer,
buf_size,
"worldmax_warp %d:\n"
"direction_clear: 0x%X\n"
"clear: %d\n",
"unused: 0x%X\n",
i,
stats->worldmax_warp[i].direction_clear,
stats->worldmax_warp[i].clear,
stats->worldmax_warp[i].unused);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NXA_USB_SAVE_WORLDMAX_LOC_MAX; i++) {
util_str_format(
buffer,
buf_size,
"worldmax_current_land %d: %d\n",
i,
stats->worldmax_current_land[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NXA_USB_SAVE_WORLDMAX_LOC_MAX; i++) {
util_str_format(
buffer,
buf_size,
"worldmax_current_mission %d: %d\n",
i,
stats->worldmax_current_mission[i]);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
for (uint32_t i = 0; i < ASSET_NXA_USB_SAVE_SONG_MAX; i++) {
for (uint32_t j = 0; j < ASSET_NXA_USB_SAVE_NUM_MODES; j++) {
util_str_format(
buffer,
buf_size,
"song_scores %d/%d:\n"
"score: %d\n"
"player_id: %s\n",
i,
j,
stats->song_scores[i][j].score,
stats->song_scores[i][j].player_id);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
}
}
/* ------------- */
util_str_format(
buffer,
buf_size,
"security_dongle_mfgid 0x%X\n"
"unlock_signal: 0x%X\n"
"running_steps: %d\n"
"total_play_time_min: %f\n"
"total_completion_percentage: %f\n"
"arcade_completion_percentage: %f\n"
"brain_shower_completion_percentage: %f\n"
"special_stage_completion_percentage: %f\n",
stats->security_dongle_mfgid,
stats->unlock_signal,
stats->running_steps,
stats->total_play_time_min,
stats->total_completion_percentage,
stats->arcade_completion_percentage,
stats->brain_shower_completion_percentage,
stats->special_stage_completion_percentage);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
/* ------------- */
tmp2 = util_str_buffer(stats->unkn_some_map_scores_to_song_ids, 4096);
util_str_format(
buffer, buf_size, "unkn_some_map_scores_to_song_ids: %s\n", tmp2);
tmp = util_str_merge(merged, buffer);
free(tmp2);
free(merged);
merged = tmp;
/* ------------- */
tmp2 = util_str_buffer(stats->unkn2, sizeof(stats->unkn2));
util_str_format(buffer, buf_size, "unkn2: %s\n", tmp2);
tmp = util_str_merge(merged, buffer);
free(tmp2);
free(merged);
merged = tmp;
/* ------------- */
util_str_format(
buffer,
buf_size,
"break_item_slot 0x%X\n"
"func_item_slot: 0x%X\n"
"bga_item_slot: 0x%X\n"
"time_item_slot: 0x%X\n"
"unknown: 0x%X\n",
stats->break_item_slot,
stats->func_item_slot,
stats->bga_item_slot,
stats->time_item_slot,
stats->unknown);
tmp = util_str_merge(merged, buffer);
free(merged);
merged = tmp;
free(buffer);
return merged;
}
struct asset_nxa_usb_save* asset_nxa_usb_save_new(void)
struct asset_nxa_usb_save *asset_nxa_usb_save_new(void)
{
struct asset_nxa_usb_save* save;
char name[10];
struct asset_nxa_usb_save *save;
char name[10];
save = (struct asset_nxa_usb_save*) util_xmalloc(
sizeof(struct asset_nxa_usb_save));
save = (struct asset_nxa_usb_save *) util_xmalloc(
sizeof(struct asset_nxa_usb_save));
memset(save, 0, sizeof(struct asset_nxa_usb_save));
memset(save, 0, sizeof(struct asset_nxa_usb_save));
sprintf(name, "NX%06d", rand() % 1000000);
strcpy(save->review.player_id, name);
strcpy(save->stats.player_id, name);
sprintf(name, "NX%06d", rand() % 1000000);
strcpy(save->review.player_id, name);
strcpy(save->stats.player_id, name);
/* default world map position */
save->stats.worldmax_map_position = 0xEF001;
/* default world map position */
save->stats.worldmax_map_position = 0xEF001;
/* nxa release date as default timestamp */
save->stats.timestamp.year = 2008;
save->stats.timestamp.month = 12;
save->stats.timestamp.day = 26;
save->stats.timestamp.hour = 0;
save->stats.timestamp.min = 0;
save->stats.timestamp.ms = 0;
/* nxa release date as default timestamp */
save->stats.timestamp.year = 2008;
save->stats.timestamp.month = 12;
save->stats.timestamp.day = 26;
save->stats.timestamp.hour = 0;
save->stats.timestamp.min = 0;
save->stats.timestamp.ms = 0;
return save;
return save;
}
void asset_nxa_usb_save_finalize(struct asset_nxa_usb_save* save)
void asset_nxa_usb_save_finalize(struct asset_nxa_usb_save *save)
{
/* checksum update, expected size for area to checksum: 90540 */
save->stats.adler32 = util_adler32_calc(1,
((const uint8_t*) &save->stats) + 4,
sizeof(struct asset_nxa_usb_save_stats) - 4);
/* checksum update, expected size for area to checksum: 90540 */
save->stats.adler32 = util_adler32_calc(
1,
((const uint8_t *) &save->stats) + 4,
sizeof(struct asset_nxa_usb_save_stats) - 4);
}
char* asset_nxa_usb_save_to_string(const struct asset_nxa_usb_save* save)
char *asset_nxa_usb_save_to_string(const struct asset_nxa_usb_save *save)
{
char* review;
char* stats;
char* merged;
char *review;
char *stats;
char *merged;
review = asset_nxa_usb_save_review_to_string(&save->review);
stats = asset_nxa_usb_save_stats_to_string(&save->stats);
review = asset_nxa_usb_save_review_to_string(&save->review);
stats = asset_nxa_usb_save_stats_to_string(&save->stats);
merged = util_str_merge(review, stats);
merged = util_str_merge(review, stats);
free(review);
free(stats);
free(review);
free(stats);
return merged;
return merged;
}
void asset_nxa_usb_save_decrypt(uint8_t* buf, size_t len)
void asset_nxa_usb_save_decrypt(uint8_t *buf, size_t len)
{
/* skip non encrypted review area */
buf += sizeof(struct asset_nxa_usb_save_review);
len -= sizeof(struct asset_nxa_usb_save_review);
/* skip non encrypted review area */
buf += sizeof(struct asset_nxa_usb_save_review);
len -= sizeof(struct asset_nxa_usb_save_review);
for (size_t a = len - 1; a > 0; --a) {
buf[a] = (buf[a] ^ buf[a - 1]) + ((a * 1234567) >> 8);
}
for (size_t a = len - 1; a > 0; --a) {
buf[a] = (buf[a] ^ buf[a - 1]) + ((a * 1234567) >> 8);
}
}
void asset_nxa_usb_save_encrypt(uint8_t* buf, size_t len)
void asset_nxa_usb_save_encrypt(uint8_t *buf, size_t len)
{
/* skip non encrypted review area */
buf += sizeof(struct asset_nxa_usb_save_review);
len -= sizeof(struct asset_nxa_usb_save_review);
/* skip non encrypted review area */
buf += sizeof(struct asset_nxa_usb_save_review);
len -= sizeof(struct asset_nxa_usb_save_review);
for (size_t a = 1; a < len; ++a) {
buf[a] = (buf[a] - ((a * 1234567) >> 8)) ^ buf[a - 1];
}
for (size_t a = 1; a < len; ++a) {
buf[a] = (buf[a] - ((a * 1234567) >> 8)) ^ buf[a - 1];
}
}
+217 -216
View File
@@ -5,271 +5,272 @@
#include <stdlib.h>
enum asset_nxa_usb_save_limits {
ASSET_NXA_USB_SAVE_SERIAL_ID_MAX = 64,
ASSET_NXA_USB_SAVE_PLAYER_ID_MAX = 12,
ASSET_NXA_USB_SAVE_WORLDMAX_LOC_MAX = 128,
ASSET_NXA_USB_SAVE_SONG_MAX = 256,
ASSET_NXA_USB_SAVE_MISSION_MAX = 1024,
ASSET_NXA_USB_SAVE_BARRICADE_MAX = 16,
ASSET_NXA_USB_SAVE_EVENT_MAX = 128,
ASSET_NXA_USB_SAVE_WARP_MAX = 8,
ASSET_NXA_USB_SAVE_NUM_MODES = 5,
ASSET_NXA_USB_SAVE_SERIAL_ID_MAX = 64,
ASSET_NXA_USB_SAVE_PLAYER_ID_MAX = 12,
ASSET_NXA_USB_SAVE_WORLDMAX_LOC_MAX = 128,
ASSET_NXA_USB_SAVE_SONG_MAX = 256,
ASSET_NXA_USB_SAVE_MISSION_MAX = 1024,
ASSET_NXA_USB_SAVE_BARRICADE_MAX = 16,
ASSET_NXA_USB_SAVE_EVENT_MAX = 128,
ASSET_NXA_USB_SAVE_WARP_MAX = 8,
ASSET_NXA_USB_SAVE_NUM_MODES = 5,
};
struct asset_nxa_usb_save_time {
int16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t min;
uint16_t ms;
int16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t min;
uint16_t ms;
} __attribute__((__packed__));
/* Not encrypted and read only, offset 0x00 to 0x144 (excl) */
struct asset_nxa_usb_save_review {
/* 0x00, 12 byte char array: max char length is 8 which gets displayed
ingame */
char player_id[ASSET_NXA_USB_SAVE_PLAYER_ID_MAX];
/* 0x0C, 4 byte int */
uint32_t mileage;
/* 0x10, 4 byte int: achieved reward count, max 65 */
uint32_t reward_count;
/* 0x14, 4 byte int: successful mission count, max 634 */
uint32_t worldmax_count;
/* 0x18, 4 byte int */
uint32_t play_count;
/* 0x1C, 128 byte char array */
char worldmax_current_land[ASSET_NXA_USB_SAVE_WORLDMAX_LOC_MAX];
/* 0x9C, 128 byte char array */
char worldmax_current_mission[ASSET_NXA_USB_SAVE_WORLDMAX_LOC_MAX];
/* 0x11C, 4 byte int */
uint32_t kcal;
/* 0x120, 4 byte int */
uint32_t v02;
/* 0x124, 8 byte */
struct asset_nxa_usb_save_time timestamp;
/* 0x12C, 4 byte int */
uint32_t running_step;
/* 0x130, 4 byte float */
float play_time_minutes;
/* 0x134, 4 byte float */
float total_completion_percentage;
/* 0x138, 4 byte float */
float arcade_percentage;
/* 0x13C, 4 byte float */
float brain_shower_percentage;
/* 0x140, 4 byte float */
float special_percentage;
/* 0x00, 12 byte char array: max char length is 8 which gets displayed
ingame */
char player_id[ASSET_NXA_USB_SAVE_PLAYER_ID_MAX];
/* 0x0C, 4 byte int */
uint32_t mileage;
/* 0x10, 4 byte int: achieved reward count, max 65 */
uint32_t reward_count;
/* 0x14, 4 byte int: successful mission count, max 634 */
uint32_t worldmax_count;
/* 0x18, 4 byte int */
uint32_t play_count;
/* 0x1C, 128 byte char array */
char worldmax_current_land[ASSET_NXA_USB_SAVE_WORLDMAX_LOC_MAX];
/* 0x9C, 128 byte char array */
char worldmax_current_mission[ASSET_NXA_USB_SAVE_WORLDMAX_LOC_MAX];
/* 0x11C, 4 byte int */
uint32_t kcal;
/* 0x120, 4 byte int */
uint32_t v02;
/* 0x124, 8 byte */
struct asset_nxa_usb_save_time timestamp;
/* 0x12C, 4 byte int */
uint32_t running_step;
/* 0x130, 4 byte float */
float play_time_minutes;
/* 0x134, 4 byte float */
float total_completion_percentage;
/* 0x138, 4 byte float */
float arcade_percentage;
/* 0x13C, 4 byte float */
float brain_shower_percentage;
/* 0x140, 4 byte float */
float special_percentage;
} __attribute__((__packed__));
struct asset_nxa_usb_save_stats {
/* 0x144, 4 byte int */
uint32_t adler32;
/* 0x148, 64 byte */
char usb_serial[ASSET_NXA_USB_SAVE_SERIAL_ID_MAX];
/* 0x188, 8 byte */
struct asset_nxa_usb_save_time timestamp;
/* 0x190, 4 byte int */
int32_t avatar_id;
/* 0x194, 4 byte int: setting this non null will give you a trophy */
int32_t rank;
/* 0x198, 4 byte int: seems unused */
int32_t country_id;
/* 0x19C, 12 byte char array */
char player_id[ASSET_NXA_USB_SAVE_PLAYER_ID_MAX];
/* 0x1A8, 4 byte int */
int32_t mileage;
/* 0x1AD, 4 byte int */
int32_t play_count;
/* 0x1B0, 4 byte int */
int32_t kcal;
/* 0x1B4, 4 byte int */
int32_t v02;
/* 0x1B8, 4 byte int */
int32_t worldmax_map_position;
/* 0x1BC, 4 byte int: achieved reward count, max 65 */
int32_t reward_count;
/* 0x1C0, 4 byte int: successful mission count, max 634 */
int32_t worldmax_count;
/* 0x144, 4 byte int */
uint32_t adler32;
/* 0x148, 64 byte */
char usb_serial[ASSET_NXA_USB_SAVE_SERIAL_ID_MAX];
/* 0x188, 8 byte */
struct asset_nxa_usb_save_time timestamp;
/* 0x190, 4 byte int */
int32_t avatar_id;
/* 0x194, 4 byte int: setting this non null will give you a trophy */
int32_t rank;
/* 0x198, 4 byte int: seems unused */
int32_t country_id;
/* 0x19C, 12 byte char array */
char player_id[ASSET_NXA_USB_SAVE_PLAYER_ID_MAX];
/* 0x1A8, 4 byte int */
int32_t mileage;
/* 0x1AD, 4 byte int */
int32_t play_count;
/* 0x1B0, 4 byte int */
int32_t kcal;
/* 0x1B4, 4 byte int */
int32_t v02;
/* 0x1B8, 4 byte int */
int32_t worldmax_map_position;
/* 0x1BC, 4 byte int: achieved reward count, max 65 */
int32_t reward_count;
/* 0x1C0, 4 byte int: successful mission count, max 634 */
int32_t worldmax_count;
/* 0x1C4, 256 bytes */
struct {
/* bits 0-4 for modes/stepcharts */
uint8_t mode : 5;
/* unused bit */
uint8_t unused : 1;
/* bit 6 song itself */
uint8_t song : 1;
/* bit 7 reveal flag */
uint8_t reveal : 1;
} song_unlocks[ASSET_NXA_USB_SAVE_SONG_MAX] __attribute__((__packed__));
/* 0x1C4, 256 bytes */
struct {
/* bits 0-4 for modes/stepcharts */
uint8_t mode : 5;
/* unused bit */
uint8_t unused : 1;
/* bit 6 song itself */
uint8_t song : 1;
/* bit 7 reveal flag */
uint8_t reveal : 1;
} song_unlocks[ASSET_NXA_USB_SAVE_SONG_MAX] __attribute__((__packed__));
/* 0x2C4, 1024 bytes */
struct {
uint8_t clear_flags_directions : 4;
uint8_t clear_flag_mission : 1;
uint8_t unused : 3;
} worldmax_mission_unlocks[ASSET_NXA_USB_SAVE_MISSION_MAX]
__attribute__((__packed__));
/* 0x2C4, 1024 bytes */
struct {
uint8_t clear_flags_directions : 4;
uint8_t clear_flag_mission : 1;
uint8_t unused : 3;
} worldmax_mission_unlocks[ASSET_NXA_USB_SAVE_MISSION_MAX]
__attribute__((__packed__));
/* 0x6C4, 4 byte int * 1024: high score for each mission */
int32_t worldmax_high_score[ASSET_NXA_USB_SAVE_MISSION_MAX];
/* 0x6C4, 4 byte int * 1024: high score for each mission */
int32_t worldmax_high_score[ASSET_NXA_USB_SAVE_MISSION_MAX];
/* 0x16C4, 4 byte int * 1024 */
int32_t worldmax_challenge[ASSET_NXA_USB_SAVE_MISSION_MAX];
/* 0x16C4, 4 byte int * 1024 */
int32_t worldmax_challenge[ASSET_NXA_USB_SAVE_MISSION_MAX];
/* 0x26C4, 16 bytes
0x00 for barricade clear and 0x01 for block */
struct {
uint8_t flag_open : 1;
uint8_t unused : 7;
} worldmax_barricade[ASSET_NXA_USB_SAVE_BARRICADE_MAX]
__attribute__((__packed__));
/* 0x26C4, 16 bytes
0x00 for barricade clear and 0x01 for block */
struct {
uint8_t flag_open : 1;
uint8_t unused : 7;
} worldmax_barricade[ASSET_NXA_USB_SAVE_BARRICADE_MAX]
__attribute__((__packed__));
/* 0x26D4, 128 bytes
0x00 for event clear and 0x01 for not cleared */
struct {
uint8_t flag_cleared : 1;
uint8_t unused : 7;
} worldmax_event[ASSET_NXA_USB_SAVE_EVENT_MAX] __attribute__((__packed__));
/* 0x26D4, 128 bytes
0x00 for event clear and 0x01 for not cleared */
struct {
uint8_t flag_cleared : 1;
uint8_t unused : 7;
} worldmax_event[ASSET_NXA_USB_SAVE_EVENT_MAX] __attribute__((__packed__));
/* 0x2754, 8 bytes
bit 0~3: clear bit for each direction bit:4 clear */
struct {
uint8_t direction_clear : 4;
uint8_t clear : 1;
uint8_t unused : 3;
} worldmax_warp[ASSET_NXA_USB_SAVE_WARP_MAX] __attribute__((__packed__));
/* 0x2754, 8 bytes
bit 0~3: clear bit for each direction bit:4 clear */
struct {
uint8_t direction_clear : 4;
uint8_t clear : 1;
uint8_t unused : 3;
} worldmax_warp[ASSET_NXA_USB_SAVE_WARP_MAX] __attribute__((__packed__));
/* 0x275C, 128 byte char array */
char worldmax_current_land[ASSET_NXA_USB_SAVE_WORLDMAX_LOC_MAX];
/* 0x275C, 128 byte char array */
char worldmax_current_land[ASSET_NXA_USB_SAVE_WORLDMAX_LOC_MAX];
/* 0x27DC, 128 byte char array */
char worldmax_current_mission[ASSET_NXA_USB_SAVE_WORLDMAX_LOC_MAX];
/* 0x27DC, 128 byte char array */
char worldmax_current_mission[ASSET_NXA_USB_SAVE_WORLDMAX_LOC_MAX];
/* 0x285C */
struct {
int32_t score;
char player_id[ASSET_NXA_USB_SAVE_PLAYER_ID_MAX];
} song_scores[ASSET_NXA_USB_SAVE_SONG_MAX][ASSET_NXA_USB_SAVE_NUM_MODES]
__attribute__((__packed__));
/* 0x285C */
struct {
int32_t score;
char player_id[ASSET_NXA_USB_SAVE_PLAYER_ID_MAX];
} song_scores[ASSET_NXA_USB_SAVE_SONG_MAX][ASSET_NXA_USB_SAVE_NUM_MODES]
__attribute__((__packed__));
/* 0x785C, 4 byte int */
uint32_t security_dongle_mfgid;
/* 0x785C, 4 byte int */
uint32_t security_dongle_mfgid;
/* 0x7860, 4 byte int: <=3 Tells game to unlock new song */
uint32_t unlock_signal;
/* 0x7860, 4 byte int: <=3 Tells game to unlock new song */
uint32_t unlock_signal;
/* 0x7864, 4 byte int */
uint32_t running_steps;
/* 0x7864, 4 byte int */
uint32_t running_steps;
/* 0x7868, 4 byte float */
float total_play_time_min;
/* 0x7868, 4 byte float */
float total_play_time_min;
/* 0x786C, 4 byte float */
float total_completion_percentage;
/* 0x786C, 4 byte float */
float total_completion_percentage;
/* 0x7870, 4 byte float */
float arcade_completion_percentage;
/* 0x7870, 4 byte float */
float arcade_completion_percentage;
/* 0x7874, 4 byte float */
float brain_shower_completion_percentage;
/* 0x7874, 4 byte float */
float brain_shower_completion_percentage;
/* 0x7878, 4 byte float */
float special_stage_completion_percentage;
/* 0x7878, 4 byte float */
float special_stage_completion_percentage;
/* 0x787C TODO unknown
0x787C, 1 byte char * 4096 - Used by GetSongIndex -
Assuming Maps Scores to Song IDs */
uint8_t unkn_some_map_scores_to_song_ids[4096];
/* 0x787C TODO unknown
0x787C, 1 byte char * 4096 - Used by GetSongIndex -
Assuming Maps Scores to Song IDs */
uint8_t unkn_some_map_scores_to_song_ids[4096];
/* 0x887C TODO unknown
0x887C, 1 byte char * 576 - Song Locks/Unlocks - 0x40 Unlocks (Special Zone, etc.)
0x8A70 , 1 byte char * 36 - WorldMax Keys and various other events for completion
0x8A9C, 8 byte char* - A Worldmax ID (Perhaps one to mark progress in Space)
0x8AA4, 1 byte char * 24 - More WorldMax Event Switches */
uint8_t unkn2[576];
/* 0x887C TODO unknown
0x887C, 1 byte char * 576 - Song Locks/Unlocks - 0x40 Unlocks (Special
Zone, etc.) 0x8A70 , 1 byte char * 36 - WorldMax Keys and various other
events for completion 0x8A9C, 8 byte char* - A Worldmax ID (Perhaps one to
mark progress in Space) 0x8AA4, 1 byte char * 24 - More WorldMax Event
Switches */
uint8_t unkn2[576];
/* 0x8ABC, 4 byte int: possible values
0x1 - grey
0x2 - red
0x3 - yellow
0x4 - green
0x5 - Dark Green
0x6 - aqua
0x7 - blue
0x8 - purple
0x9 - pink
0xA - light grey
0xB - Black
0xC - Orange
*/
uint32_t break_item_slot;
/* 0x8ABC, 4 byte int: possible values
0x1 - grey
0x2 - red
0x3 - yellow
0x4 - green
0x5 - Dark Green
0x6 - aqua
0x7 - blue
0x8 - purple
0x9 - pink
0xA - light grey
0xB - Black
0xC - Orange
*/
uint32_t break_item_slot;
/* 0x8AC0, 4 byte int
0x1 - Shield
0x2 - PermaShield
0x3 - Line Searcher
0x4 - Perma Line Searcher
0x5 - Life Up
0x6 - Perma Life Up
0x7 - Lucky
0x8 - Perma Lucky
0x9 - Portal Pass
*/
uint32_t func_item_slot;
/* 0x8AC0, 4 byte int
0x1 - Shield
0x2 - PermaShield
0x3 - Line Searcher
0x4 - Perma Line Searcher
0x5 - Life Up
0x6 - Perma Life Up
0x7 - Lucky
0x8 - Perma Lucky
0x9 - Portal Pass
*/
uint32_t func_item_slot;
/* 0x8AC4, 4 byte int
0x1 - BGA OFF
0x2 - Perma BGA OFF
*/
uint32_t bga_item_slot;
/* 0x8AC4, 4 byte int
0x1 - BGA OFF
0x2 - Perma BGA OFF
*/
uint32_t bga_item_slot;
/* 0x8AC4, 4 byte int
0x1 - 10+
0x2 - 20+
0x3 - 30+
*/
uint32_t time_item_slot;
/* 0x8AC4, 4 byte int
0x1 - 10+
0x2 - 20+
0x3 - 30+
*/
uint32_t time_item_slot;
/* 0x8AC8, 4 byte int */
uint32_t unknown;
/* 0x8AC8, 4 byte int */
uint32_t unknown;
/* 0x8ACC, unknown stuff: More WorldMax Event Switches (Unused)? */
uint8_t unknown2[12];
/* 0x8ACC, unknown stuff: More WorldMax Event Switches (Unused)? */
uint8_t unknown2[12];
/* 0x8AD8, 4 byte float - Unknown What this Does (Unused) */
float unknown3;
/* 0x8AD8, 4 byte float - Unknown What this Does (Unused) */
float unknown3;
/* 0x8ADC, totally unknown stuff, just nulls */
uint8_t unknown4[0x7F8];
/* 0x8ADC, totally unknown stuff, just nulls */
uint8_t unknown4[0x7F8];
/* 0x92D4 */
uint8_t unknown5[0xD01C];
/* 0x92D4 */
uint8_t unknown5[0xD01C];
/* TODO missing switches for dark/light world stuff
0x8ACC, 1 byte char - More WorldMax Event Switches (Unused)
0x8AD8 , 4 byte float - Unknown What this Does (Unused)
0x92D4, High Score Table [See Below]
0x132D0, 5216 bytes - Unknown Table (Unused)
0x162D0, 24 bytes - Unknown Footer (Unused by Game - Most Likely PumBI)
*/
/* TODO missing switches for dark/light world stuff
0x8ACC, 1 byte char - More WorldMax Event Switches (Unused)
0x8AD8 , 4 byte float - Unknown What this Does (Unused)
0x92D4, High Score Table [See Below]
0x132D0, 5216 bytes - Unknown Table (Unused)
0x162D0, 24 bytes - Unknown Footer (Unused by Game - Most Likely PumBI)
*/
} __attribute__((__packed__));
struct asset_nxa_usb_save {
struct asset_nxa_usb_save_review review;
struct asset_nxa_usb_save_stats stats;
struct asset_nxa_usb_save_review review;
struct asset_nxa_usb_save_stats stats;
} __attribute__((__packed__));
struct asset_nxa_usb_save* asset_nxa_usb_save_new(void);
struct asset_nxa_usb_save *asset_nxa_usb_save_new(void);
/* update checksum and prepare profile to get encrypted */
void asset_nxa_usb_save_finalize(struct asset_nxa_usb_save* save);
void asset_nxa_usb_save_finalize(struct asset_nxa_usb_save *save);
char* asset_nxa_usb_save_to_string(const struct asset_nxa_usb_save* save);
char *asset_nxa_usb_save_to_string(const struct asset_nxa_usb_save *save);
void asset_nxa_usb_save_decrypt(uint8_t* buf, size_t len);
void asset_nxa_usb_save_decrypt(uint8_t *buf, size_t len);
void asset_nxa_usb_save_encrypt(uint8_t* buf, size_t len);
void asset_nxa_usb_save_encrypt(uint8_t *buf, size_t len);
#endif
+70 -64
View File
@@ -7,94 +7,100 @@
#include "util.h"
struct asset_nxa_usb_rank* asset_nxa_usb_rank_load_from_file(const char* path,
bool encrypted)
struct asset_nxa_usb_rank *
asset_nxa_usb_rank_load_from_file(const char *path, bool encrypted)
{
struct asset_nxa_usb_rank* rank;
size_t size;
struct asset_nxa_usb_rank *rank;
size_t size;
if (!util_file_load(path, (void**) &rank, &size, false)) {
log_error("Loading nxa rank file %s failed", path);
return NULL;
}
if (!util_file_load(path, (void **) &rank, &size, false)) {
log_error("Loading nxa rank file %s failed", path);
return NULL;
}
if (size != sizeof(struct asset_nxa_usb_rank)) {
log_error("Invalid size of nxa rank file %s: %d != %d", path, size,
sizeof(struct asset_nxa_usb_rank));
free(rank);
return NULL;
}
if (size != sizeof(struct asset_nxa_usb_rank)) {
log_error(
"Invalid size of nxa rank file %s: %d != %d",
path,
size,
sizeof(struct asset_nxa_usb_rank));
free(rank);
return NULL;
}
if (encrypted) {
asset_nxa_usb_rank_decrypt((uint8_t*) rank, size);
}
if (encrypted) {
asset_nxa_usb_rank_decrypt((uint8_t *) rank, size);
}
return rank;
return rank;
}
bool asset_nxa_usb_rank_save_to_file(const char* path,
const struct asset_nxa_usb_rank* rank, bool encrypt)
bool asset_nxa_usb_rank_save_to_file(
const char *path, const struct asset_nxa_usb_rank *rank, bool encrypt)
{
struct asset_nxa_usb_rank rank_enc;
struct asset_nxa_usb_rank rank_enc;
memcpy(&rank_enc, rank, sizeof(struct asset_nxa_usb_rank));
memcpy(&rank_enc, rank, sizeof(struct asset_nxa_usb_rank));
if (encrypt) {
asset_nxa_usb_rank_encrypt((uint8_t*) &rank_enc,
sizeof(struct asset_nxa_usb_rank));
}
if (encrypt) {
asset_nxa_usb_rank_encrypt(
(uint8_t *) &rank_enc, sizeof(struct asset_nxa_usb_rank));
}
if (!util_file_save(path, (void**) &rank_enc,
sizeof(struct asset_nxa_usb_rank))) {
log_error("Storing nxa rank data to %s failed", path);
return false;
}
if (!util_file_save(
path, (void **) &rank_enc, sizeof(struct asset_nxa_usb_rank))) {
log_error("Storing nxa rank data to %s failed", path);
return false;
}
return true;
return true;
}
struct asset_nxa_usb_save* asset_nxa_usb_save_load_from_file(const char* path,
bool encrypted)
struct asset_nxa_usb_save *
asset_nxa_usb_save_load_from_file(const char *path, bool encrypted)
{
struct asset_nxa_usb_save* save;
size_t size;
struct asset_nxa_usb_save *save;
size_t size;
if (!util_file_load(path, (void**) &save, &size, false)) {
log_error("Loading nxa save file %s failed", path);
return NULL;
}
if (!util_file_load(path, (void **) &save, &size, false)) {
log_error("Loading nxa save file %s failed", path);
return NULL;
}
if (size != sizeof(struct asset_nxa_usb_save)) {
log_error("Invalid size of nxa save file %s: %d != %d", path, size,
sizeof(struct asset_nxa_usb_save));
free(save);
return NULL;
}
if (size != sizeof(struct asset_nxa_usb_save)) {
log_error(
"Invalid size of nxa save file %s: %d != %d",
path,
size,
sizeof(struct asset_nxa_usb_save));
free(save);
return NULL;
}
if (encrypted) {
asset_nxa_usb_save_decrypt((uint8_t*) save, size);
}
if (encrypted) {
asset_nxa_usb_save_decrypt((uint8_t *) save, size);
}
return save;
return save;
}
bool asset_nxa_usb_save_save_to_file(const char* path,
const struct asset_nxa_usb_save* save, bool encrypt)
bool asset_nxa_usb_save_save_to_file(
const char *path, const struct asset_nxa_usb_save *save, bool encrypt)
{
struct asset_nxa_usb_save save_enc;
struct asset_nxa_usb_save save_enc;
memcpy(&save_enc, save, sizeof(struct asset_nxa_usb_save));
memcpy(&save_enc, save, sizeof(struct asset_nxa_usb_save));
if (encrypt) {
asset_nxa_usb_save_encrypt((uint8_t*) &save_enc,
sizeof(struct asset_nxa_usb_save));
}
if (encrypt) {
asset_nxa_usb_save_encrypt(
(uint8_t *) &save_enc, sizeof(struct asset_nxa_usb_save));
}
if (!util_file_save(path, (const void*) &save_enc,
sizeof(struct asset_nxa_usb_save))) {
log_error("Storing nxa save data to %s failed", path);
return false;
}
if (!util_file_save(
path, (const void *) &save_enc, sizeof(struct asset_nxa_usb_save))) {
log_error("Storing nxa save data to %s failed", path);
return false;
}
return true;
return true;
}
+8 -4
View File
@@ -7,15 +7,19 @@
#include "usb-save.h"
// load from file and decrypt, returns decrypted struct
struct asset_nxa_usb_rank* asset_nxa_usb_rank_load_from_file(const char* path, bool encrypted);
struct asset_nxa_usb_rank *
asset_nxa_usb_rank_load_from_file(const char *path, bool encrypted);
// takes decrypted rank data, encrypts it and writes it to file
bool asset_nxa_usb_rank_save_to_file(const char* path, const struct asset_nxa_usb_rank* rank, bool encrypt);
bool asset_nxa_usb_rank_save_to_file(
const char *path, const struct asset_nxa_usb_rank *rank, bool encrypt);
// load from file and decrypt, returns decrypted struct
struct asset_nxa_usb_save* asset_nxa_usb_save_load_from_file(const char* path, bool encrypted);
struct asset_nxa_usb_save *
asset_nxa_usb_save_load_from_file(const char *path, bool encrypted);
// takes decrypted save data, encrypts it and writes it to file
bool asset_nxa_usb_save_save_to_file(const char* path, const struct asset_nxa_usb_save* save, bool encrypt);
bool asset_nxa_usb_save_save_to_file(
const char *path, const struct asset_nxa_usb_save *save, bool encrypt);
#endif
+132 -128
View File
@@ -9,146 +9,150 @@
#include "util/str.h"
int main(int argc, char** argv)
int main(int argc, char **argv)
{
int ret;
char* rank_path;
char* save_path;
int ret;
char *rank_path;
char *save_path;
if (argc < 3) {
printf("Usage: %s [cmd: new, dec, enc, dump] "
"[path containing nxarank.bin nxasave.bin]\n", argv[0]);
return -1;
if (argc < 3) {
printf(
"Usage: %s [cmd: new, dec, enc, dump] "
"[path containing nxarank.bin nxasave.bin]\n",
argv[0]);
return -1;
}
ret = 0;
rank_path = util_str_merge(argv[2], "nxarank.bin");
save_path = util_str_merge(argv[2], "nxasave.bin");
if (!strcmp(argv[1], "new")) {
struct asset_nxa_usb_rank *rank = asset_nxa_usb_rank_new();
struct asset_nxa_usb_save *save = asset_nxa_usb_save_new();
asset_nxa_usb_rank_finalize(rank);
asset_nxa_usb_save_finalize(save);
if (!asset_nxa_usb_rank_save_to_file(rank_path, rank, true)) {
fprintf(stderr, "Creating rank file %s failed\n", rank_path);
ret = -2;
}
ret = 0;
if (!asset_nxa_usb_save_save_to_file(save_path, save, true)) {
fprintf(stderr, "Creating save file %s failed\n", save_path);
ret = -3;
}
rank_path = util_str_merge(argv[2], "nxarank.bin");
save_path = util_str_merge(argv[2], "nxasave.bin");
free(rank);
free(save);
} else {
struct asset_nxa_usb_rank *rank;
struct asset_nxa_usb_save *save;
bool encrypted;
if (!strcmp(argv[1], "new")) {
struct asset_nxa_usb_rank* rank = asset_nxa_usb_rank_new();
struct asset_nxa_usb_save* save = asset_nxa_usb_save_new();
if (!strcmp(argv[1], "enc")) {
char *tmp;
asset_nxa_usb_rank_finalize(rank);
asset_nxa_usb_save_finalize(save);
encrypted = false;
if (!asset_nxa_usb_rank_save_to_file(rank_path, rank, true)) {
fprintf(stderr, "Creating rank file %s failed\n", rank_path);
ret = -2;
}
tmp = util_str_merge(rank_path, ".dec");
free(rank_path);
rank_path = tmp;
if (!asset_nxa_usb_save_save_to_file(save_path, save, true)) {
fprintf(stderr, "Creating save file %s failed\n", save_path);
ret = -3;
}
free(rank);
free(save);
tmp = util_str_merge(save_path, ".dec");
free(save_path);
save_path = tmp;
} else {
struct asset_nxa_usb_rank* rank;
struct asset_nxa_usb_save* save;
bool encrypted;
if (!strcmp(argv[1], "enc")) {
char* tmp;
encrypted = false;
tmp = util_str_merge(rank_path, ".dec");
free(rank_path);
rank_path = tmp;
tmp = util_str_merge(save_path, ".dec");
free(save_path);
save_path = tmp;
} else {
encrypted = true;
}
rank = asset_nxa_usb_rank_load_from_file(rank_path, encrypted);
save = asset_nxa_usb_save_load_from_file(save_path, encrypted);
if (!rank) {
fprintf(stderr, "Loading %s failed", rank_path);
ret = -4;
goto cleanup;
}
if (!save) {
fprintf(stderr, "Loading %s failed", save_path);
ret = -5;
free(rank);
goto cleanup;
}
if (!strcmp(argv[1], "dec")) {
char* rank_path_dec;
char* save_path_dec;
rank_path_dec = util_str_merge(rank_path, ".dec");
save_path_dec = util_str_merge(save_path, ".dec");
if (!asset_nxa_usb_rank_save_to_file(rank_path_dec, rank, false)) {
fprintf(stderr, "Saving decrypted rank file to %s failed\n",
rank_path_dec);
ret = -6;
}
if (!asset_nxa_usb_save_save_to_file(save_path_dec, save, false)) {
fprintf(stderr, "Saving decrypted save file to %s failed\n",
save_path_dec);
ret = -7;
}
free(rank_path_dec);
free(save_path_dec);
} else if (!strcmp(argv[1], "enc")) {
char* rank_path_enc;
char* save_path_enc;
rank_path_enc = util_str_merge(rank_path, ".enc");
save_path_enc = util_str_merge(save_path, ".enc");
if (!asset_nxa_usb_rank_save_to_file(rank_path_enc, rank, true)) {
fprintf(stderr, "Saving encrypted rank file to %s failed\n",
rank_path_enc);
ret = -6;
}
if (!asset_nxa_usb_save_save_to_file(save_path_enc, save, true)) {
fprintf(stderr, "Saving encrypted save file to %s failed\n",
save_path_enc);
ret = -7;
}
free(rank_path_enc);
free(save_path_enc);
} else if (!strcmp(argv[1], "dump")) {
char* rank_str;
char* save_str;
rank_str = asset_nxa_usb_rank_to_string(rank);
save_str = asset_nxa_usb_save_to_string(save);
printf("----------------- rank -----------------\n"
"%s----------------- save -----------------\n%s",
rank_str, save_str);
free(rank_str);
free(save_str);
} else {
fprintf(stderr, "Unknown command %s\n", argv[1]);
ret = -4;
}
free(rank);
free(save);
encrypted = true;
}
rank = asset_nxa_usb_rank_load_from_file(rank_path, encrypted);
save = asset_nxa_usb_save_load_from_file(save_path, encrypted);
if (!rank) {
fprintf(stderr, "Loading %s failed", rank_path);
ret = -4;
goto cleanup;
}
if (!save) {
fprintf(stderr, "Loading %s failed", save_path);
ret = -5;
free(rank);
goto cleanup;
}
if (!strcmp(argv[1], "dec")) {
char *rank_path_dec;
char *save_path_dec;
rank_path_dec = util_str_merge(rank_path, ".dec");
save_path_dec = util_str_merge(save_path, ".dec");
if (!asset_nxa_usb_rank_save_to_file(rank_path_dec, rank, false)) {
fprintf(
stderr, "Saving decrypted rank file to %s failed\n", rank_path_dec);
ret = -6;
}
if (!asset_nxa_usb_save_save_to_file(save_path_dec, save, false)) {
fprintf(
stderr, "Saving decrypted save file to %s failed\n", save_path_dec);
ret = -7;
}
free(rank_path_dec);
free(save_path_dec);
} else if (!strcmp(argv[1], "enc")) {
char *rank_path_enc;
char *save_path_enc;
rank_path_enc = util_str_merge(rank_path, ".enc");
save_path_enc = util_str_merge(save_path, ".enc");
if (!asset_nxa_usb_rank_save_to_file(rank_path_enc, rank, true)) {
fprintf(
stderr, "Saving encrypted rank file to %s failed\n", rank_path_enc);
ret = -6;
}
if (!asset_nxa_usb_save_save_to_file(save_path_enc, save, true)) {
fprintf(
stderr, "Saving encrypted save file to %s failed\n", save_path_enc);
ret = -7;
}
free(rank_path_enc);
free(save_path_enc);
} else if (!strcmp(argv[1], "dump")) {
char *rank_str;
char *save_str;
rank_str = asset_nxa_usb_rank_to_string(rank);
save_str = asset_nxa_usb_save_to_string(save);
printf(
"----------------- rank -----------------\n"
"%s----------------- save -----------------\n%s",
rank_str,
save_str);
free(rank_str);
free(save_str);
} else {
fprintf(stderr, "Unknown command %s\n", argv[1]);
ret = -4;
}
free(rank);
free(save);
}
cleanup:
free(rank_path);
free(save_path);
free(rank_path);
free(save_path);
return ret;
return ret;
}
+51 -63
View File
@@ -5,83 +5,71 @@
#include "util/adler32.h"
#include "util/mem.h"
static const char* _asset_x2_settings_defaut_high_score_names[] = {
"MKII",
"YAHP",
"KANN",
"ZINY",
"PIAH",
"AHN ",
"PIYO",
"HIKO",
"HALO",
"BAJI",
"YUTE",
"SS ",
"SIHO",
"AZKI",
"JUNE",
"GOON",
"ARI*",
"TAMA",
"YSMA",
"PIU "
};
static const char *_asset_x2_settings_defaut_high_score_names[] = {
"MKII", "YAHP", "KANN", "ZINY", "PIAH", "AHN ", "PIYO",
"HIKO", "HALO", "BAJI", "YUTE", "SS ", "SIHO", "AZKI",
"JUNE", "GOON", "ARI*", "TAMA", "YSMA", "PIU "};
struct asset_x2_settings* asset_x2_settings_new(void)
struct asset_x2_settings *asset_x2_settings_new(void)
{
struct asset_x2_settings* settings;
struct asset_x2_settings *settings;
settings = util_xmalloc(sizeof(struct asset_x2_settings));
settings = util_xmalloc(sizeof(struct asset_x2_settings));
memset(settings->ff_pad, 0xFF, sizeof(settings->ff_pad));
memset(settings->unkn, 0, sizeof(settings->unkn));
settings->unlock_canond_full = 0;
settings->total_uptime = 0;
settings->unkn69 = 0x69;
memset(settings->song_blacklist, 0, ASSET_X2_SETTINGS_MAX_SONGS);
memset(settings->unkn3, 0, sizeof(settings->unkn3));
memcpy(settings->ident, "EX02", 4);
/* Updated using finalize */
settings->adler32 = 0;
memset(settings->song_play_count, 0, sizeof(uint16_t) * ASSET_X2_SETTINGS_MAX_SONGS);
settings->padding = 0;
memset(settings->ff_pad, 0xFF, sizeof(settings->ff_pad));
memset(settings->unkn, 0, sizeof(settings->unkn));
settings->unlock_canond_full = 0;
settings->total_uptime = 0;
settings->unkn69 = 0x69;
memset(settings->song_blacklist, 0, ASSET_X2_SETTINGS_MAX_SONGS);
memset(settings->unkn3, 0, sizeof(settings->unkn3));
memcpy(settings->ident, "EX02", 4);
/* Updated using finalize */
settings->adler32 = 0;
memset(
settings->song_play_count,
0,
sizeof(uint16_t) * ASSET_X2_SETTINGS_MAX_SONGS);
settings->padding = 0;
for (uint8_t i = 0; i < ASSET_X2_SETTINGS_HIGH_SCORE_COUNT; i++) {
settings->high_score_scores[i] = 10000u - (500u * i);
memcpy(&settings->high_score_names[i], &_asset_x2_settings_defaut_high_score_names[i],
ASSET_X2_SETTINGS_HIGH_SCORE_NAME_LEN);
}
for (uint8_t i = 0; i < ASSET_X2_SETTINGS_HIGH_SCORE_COUNT; i++) {
settings->high_score_scores[i] = 10000u - (500u * i);
memcpy(
&settings->high_score_names[i],
&_asset_x2_settings_defaut_high_score_names[i],
ASSET_X2_SETTINGS_HIGH_SCORE_NAME_LEN);
}
settings->coin_limit = 0;
settings->game_mode = ASSET_X2_SETTINGS_GAME_MODE_NORMAL;
settings->game_level = ASSET_X2_SETTINGS_LEVEL_NORMAL;
settings->game_stage_break = ASSET_X2_SETTINGS_STAGE_BREAK_2ND;
settings->language = ASSET_X2_SETTINGS_LANG_ENG;
settings->game_demo_sound = 1;
settings->game_show_help = 1;
settings->coin1_setting = 1;
settings->coin2_setting = 1;
settings->bookkeeping_coin1_total = 0;
settings->bookkeeping_coin2_total = 0;
settings->bookkeeping_service_total = 0;
settings->coin_limit = 0;
settings->game_mode = ASSET_X2_SETTINGS_GAME_MODE_NORMAL;
settings->game_level = ASSET_X2_SETTINGS_LEVEL_NORMAL;
settings->game_stage_break = ASSET_X2_SETTINGS_STAGE_BREAK_2ND;
settings->language = ASSET_X2_SETTINGS_LANG_ENG;
settings->game_demo_sound = 1;
settings->game_show_help = 1;
settings->coin1_setting = 1;
settings->coin2_setting = 1;
settings->bookkeeping_coin1_total = 0;
settings->bookkeeping_coin2_total = 0;
settings->bookkeeping_service_total = 0;
return settings;
return settings;
}
void asset_x2_settings_finalize(struct asset_x2_settings* settings)
void asset_x2_settings_finalize(struct asset_x2_settings *settings)
{
/* Seems odd, but they just checksum the game settings part...*/
settings->adler32 = util_adler32_calc(1, (const uint8_t*) &settings->game_mode, 8);
/* Seems odd, but they just checksum the game settings part...*/
settings->adler32 =
util_adler32_calc(1, (const uint8_t *) &settings->game_mode, 8);
}
void asset_x2_settings_unlock_all(struct asset_x2_settings* settings)
void asset_x2_settings_unlock_all(struct asset_x2_settings *settings)
{
settings->unlock_canond_full = 1;
settings->unlock_canond_full = 1;
}
char* asset_x2_settings_to_string(const struct asset_x2_settings* settings)
char *asset_x2_settings_to_string(const struct asset_x2_settings *settings)
{
// TODO
return "";
// TODO
return "";
}
+52 -51
View File
@@ -9,74 +9,75 @@
#define ASSET_X2_SETTINGS_HIGH_SCORE_NAME_LEN 4
enum asset_x2_settings_language {
ASSET_X2_SETTINGS_LANG_KOR = 0,
ASSET_X2_SETTINGS_LANG_ENG = 1,
ASSET_X2_SETTINGS_LANG_SP = 2,
ASSET_X2_SETTINGS_LANG_CH = 3,
ASSET_X2_SETTINGS_LANG_KOR = 0,
ASSET_X2_SETTINGS_LANG_ENG = 1,
ASSET_X2_SETTINGS_LANG_SP = 2,
ASSET_X2_SETTINGS_LANG_CH = 3,
};
enum asset_x2_settings_game_mode {
ASSET_X2_SETTINGS_GAME_MODE_NORMAL = 0,
ASSET_X2_SETTINGS_GAME_MODE_EVENT = 1,
ASSET_X2_SETTINGS_GAME_MODE_NORMAL = 0,
ASSET_X2_SETTINGS_GAME_MODE_EVENT = 1,
};
enum asset_x2_settings_level {
ASSET_X2_SETTINGS_LEVEL_EASY = 0,
ASSET_X2_SETTINGS_LEVEL_NORMAL = 1,
ASSET_X2_SETTINGS_LEVEL_HARD = 2,
ASSET_X2_SETTINGS_LEVEL_EASY = 0,
ASSET_X2_SETTINGS_LEVEL_NORMAL = 1,
ASSET_X2_SETTINGS_LEVEL_HARD = 2,
};
enum asset_x2_settings_stage_break {
ASSET_X2_SETTINGS_STAGE_BREAK_OFF = 0,
ASSET_X2_SETTINGS_STAGE_BREAK_1ST = 1,
ASSET_X2_SETTINGS_STAGE_BREAK_2ND = 2,
ASSET_X2_SETTINGS_STAGE_BREAK_3RD = 3,
ASSET_X2_SETTINGS_STAGE_BREAK_4TH = 4,
ASSET_X2_SETTINGS_STAGE_BREAK_OFF = 0,
ASSET_X2_SETTINGS_STAGE_BREAK_1ST = 1,
ASSET_X2_SETTINGS_STAGE_BREAK_2ND = 2,
ASSET_X2_SETTINGS_STAGE_BREAK_3RD = 3,
ASSET_X2_SETTINGS_STAGE_BREAK_4TH = 4,
};
struct asset_x2_settings {
/* Padding to fill up to 4k EEPROM legacy size */
uint8_t ff_pad[0x51B];
uint8_t unkn[10];
uint8_t unlock_canond_full;
uint32_t total_uptime;
uint8_t unkn69;
uint8_t song_blacklist[ASSET_X2_SETTINGS_MAX_SONGS];
uint8_t unkn3[0x75];
/* EX02 */
char ident[4];
uint32_t adler32;
uint16_t song_play_count[ASSET_X2_SETTINGS_MAX_SONGS];
uint16_t padding;
uint32_t high_score_scores[ASSET_X2_SETTINGS_HIGH_SCORE_COUNT];
/* 20 names a 4 chars for the default high score list */
char high_score_names[ASSET_X2_SETTINGS_HIGH_SCORE_COUNT][ASSET_X2_SETTINGS_HIGH_SCORE_NAME_LEN];
/* 0 none */
uint8_t coin_limit;
uint8_t game_mode;
uint8_t game_level;
uint8_t game_stage_break;
uint8_t language;
/* 0 off, 1 on */
uint8_t game_demo_sound;
/* 0 off, 1 on */
uint8_t game_show_help;
/* 0 freeplay */
uint8_t coin1_setting;
/* 0 freeplay */
uint8_t coin2_setting;
uint32_t bookkeeping_coin1_total;
uint32_t bookkeeping_coin2_total;
uint32_t bookkeeping_service_total;
/* Padding to fill up to 4k EEPROM legacy size */
uint8_t ff_pad[0x51B];
uint8_t unkn[10];
uint8_t unlock_canond_full;
uint32_t total_uptime;
uint8_t unkn69;
uint8_t song_blacklist[ASSET_X2_SETTINGS_MAX_SONGS];
uint8_t unkn3[0x75];
/* EX02 */
char ident[4];
uint32_t adler32;
uint16_t song_play_count[ASSET_X2_SETTINGS_MAX_SONGS];
uint16_t padding;
uint32_t high_score_scores[ASSET_X2_SETTINGS_HIGH_SCORE_COUNT];
/* 20 names a 4 chars for the default high score list */
char high_score_names[ASSET_X2_SETTINGS_HIGH_SCORE_COUNT]
[ASSET_X2_SETTINGS_HIGH_SCORE_NAME_LEN];
/* 0 none */
uint8_t coin_limit;
uint8_t game_mode;
uint8_t game_level;
uint8_t game_stage_break;
uint8_t language;
/* 0 off, 1 on */
uint8_t game_demo_sound;
/* 0 off, 1 on */
uint8_t game_show_help;
/* 0 freeplay */
uint8_t coin1_setting;
/* 0 freeplay */
uint8_t coin2_setting;
uint32_t bookkeeping_coin1_total;
uint32_t bookkeeping_coin2_total;
uint32_t bookkeeping_service_total;
} __attribute__((__packed__));
struct asset_x2_settings* asset_x2_settings_new(void);
struct asset_x2_settings *asset_x2_settings_new(void);
// update checksum
void asset_x2_settings_finalize(struct asset_x2_settings* settings);
void asset_x2_settings_finalize(struct asset_x2_settings *settings);
void asset_x2_settings_unlock_all(struct asset_x2_settings* settings);
void asset_x2_settings_unlock_all(struct asset_x2_settings *settings);
char* asset_x2_settings_to_string(const struct asset_x2_settings* settings);
char *asset_x2_settings_to_string(const struct asset_x2_settings *settings);
#endif
+48 -41
View File
@@ -5,58 +5,65 @@
#include "util/adler32.h"
#include "util/mem.h"
struct asset_zero_settings* asset_zero_settings_new(void)
struct asset_zero_settings *asset_zero_settings_new(void)
{
struct asset_zero_settings* settings;
struct asset_zero_settings *settings;
settings = util_xmalloc(sizeof(struct asset_zero_settings));
settings = util_xmalloc(sizeof(struct asset_zero_settings));
memset(settings->ff_pad, 0xFF, sizeof(settings->ff_pad));
memcpy(settings->ident, "ZERO", 4);
/* Updated using finalize */
settings->adler32 = 0;
settings->total_uptime = 0;
settings->language = ASSET_ZERO_SETTINGS_LANG_ENG;
memset(settings->song_play_count, 0, sizeof(uint32_t) * ASSET_ZERO_SETTINGS_MAX_SONGS);
settings->game_option_default_station = ASSET_ZERO_SETTINGS_STATION_EASY;
settings->game_mode = ASSET_ZERO_SETTINGS_GAME_MODE_NORMAL;
settings->game_level = ASSET_ZERO_SETTINGS_LEVEL_NORMAL;
settings->game_stage_break = ASSET_ZERO_SETTINGS_STAGE_BREAK_2ND;
settings->game_demo_sound = 1;
settings->game_show_help = 1;
settings->game_mercy_ticket = 0;
settings->game_score_per_ticket = 0;
settings->coin_limit = 0;
settings->coin1_setting = 1;
settings->coin2_setting = 1;
memset(settings->mission_unlock_flags, 0, ASSET_ZERO_SETTINGS_NUM_UNLOCK_FLAGS);
settings->unkn2 = 0x2A;
settings->unkn3 = 0;
settings->bookkeeping_coin1_total = 0;
settings->bookkeeping_coin2_total = 0;
settings->bookkeeping_service_total = 0;
settings->bookkeeping_ticket_1 = 0;
settings->bookkeeping_ticket_2 = 0;
settings->region = 0xFF;
memset(settings->censor_table, 0, ASSET_ZERO_SETTINGS_MAX_SONGS);
memset(settings->ff_pad, 0xFF, sizeof(settings->ff_pad));
memcpy(settings->ident, "ZERO", 4);
/* Updated using finalize */
settings->adler32 = 0;
settings->total_uptime = 0;
settings->language = ASSET_ZERO_SETTINGS_LANG_ENG;
memset(
settings->song_play_count,
0,
sizeof(uint32_t) * ASSET_ZERO_SETTINGS_MAX_SONGS);
settings->game_option_default_station = ASSET_ZERO_SETTINGS_STATION_EASY;
settings->game_mode = ASSET_ZERO_SETTINGS_GAME_MODE_NORMAL;
settings->game_level = ASSET_ZERO_SETTINGS_LEVEL_NORMAL;
settings->game_stage_break = ASSET_ZERO_SETTINGS_STAGE_BREAK_2ND;
settings->game_demo_sound = 1;
settings->game_show_help = 1;
settings->game_mercy_ticket = 0;
settings->game_score_per_ticket = 0;
settings->coin_limit = 0;
settings->coin1_setting = 1;
settings->coin2_setting = 1;
memset(
settings->mission_unlock_flags, 0, ASSET_ZERO_SETTINGS_NUM_UNLOCK_FLAGS);
settings->unkn2 = 0x2A;
settings->unkn3 = 0;
settings->bookkeeping_coin1_total = 0;
settings->bookkeeping_coin2_total = 0;
settings->bookkeeping_service_total = 0;
settings->bookkeeping_ticket_1 = 0;
settings->bookkeeping_ticket_2 = 0;
settings->region = 0xFF;
memset(settings->censor_table, 0, ASSET_ZERO_SETTINGS_MAX_SONGS);
return settings;
return settings;
}
void asset_zero_settings_finalize(struct asset_zero_settings* settings)
void asset_zero_settings_finalize(struct asset_zero_settings *settings)
{
/* Seems odd, but they just checksum the game settings part...*/
settings->adler32 = util_adler32_calc(1, (const uint8_t*) &settings->game_mode, 8);
/* Seems odd, but they just checksum the game settings part...*/
settings->adler32 =
util_adler32_calc(1, (const uint8_t *) &settings->game_mode, 8);
}
void asset_zero_settings_unlock_all(struct asset_zero_settings* settings)
void asset_zero_settings_unlock_all(struct asset_zero_settings *settings)
{
/* Mark all missions cleared to unlock all missions and content locked by some missions */
memset(settings->mission_unlock_flags, 1, ASSET_ZERO_SETTINGS_NUM_UNLOCK_FLAGS);
/* Mark all missions cleared to unlock all missions and content locked by some
* missions */
memset(
settings->mission_unlock_flags, 1, ASSET_ZERO_SETTINGS_NUM_UNLOCK_FLAGS);
}
char* asset_zero_settings_to_string(const struct asset_zero_settings* settings)
char *asset_zero_settings_to_string(const struct asset_zero_settings *settings)
{
// TODO
return "";
// TODO
return "";
}
+61 -61
View File
@@ -8,88 +8,88 @@
#define ASSET_ZERO_SETTINGS_NUM_UNLOCK_FLAGS 59
enum asset_zero_settings_language {
ASSET_ZERO_SETTINGS_LANG_KOR = 0,
ASSET_ZERO_SETTINGS_LANG_ENG = 1,
ASSET_ZERO_SETTINGS_LANG_SP = 2,
ASSET_ZERO_SETTINGS_LANG_CH = 3,
ASSET_ZERO_SETTINGS_LANG_KOR = 0,
ASSET_ZERO_SETTINGS_LANG_ENG = 1,
ASSET_ZERO_SETTINGS_LANG_SP = 2,
ASSET_ZERO_SETTINGS_LANG_CH = 3,
};
enum asset_zero_settings_station {
ASSET_ZERO_SETTINGS_STATION_EASY = 0,
ASSET_ZERO_SETTINGS_STATION_ARCADE = 1,
ASSET_ZERO_SETTINGS_STATION_REMIX = 2,
ASSET_ZERO_SETTINGS_STATION_EASY = 0,
ASSET_ZERO_SETTINGS_STATION_ARCADE = 1,
ASSET_ZERO_SETTINGS_STATION_REMIX = 2,
};
enum asset_zero_settings_game_mode {
ASSET_ZERO_SETTINGS_GAME_MODE_NORMAL = 0,
ASSET_ZERO_SETTINGS_GAME_MODE_EVENT = 1,
ASSET_ZERO_SETTINGS_GAME_MODE_NORMAL = 0,
ASSET_ZERO_SETTINGS_GAME_MODE_EVENT = 1,
};
enum asset_zero_settings_level {
ASSET_ZERO_SETTINGS_LEVEL_EASY = 0,
ASSET_ZERO_SETTINGS_LEVEL_NORMAL = 1,
ASSET_ZERO_SETTINGS_LEVEL_HARD = 2,
ASSET_ZERO_SETTINGS_LEVEL_EASY = 0,
ASSET_ZERO_SETTINGS_LEVEL_NORMAL = 1,
ASSET_ZERO_SETTINGS_LEVEL_HARD = 2,
};
enum asset_zero_settings_stage_break {
ASSET_ZERO_SETTINGS_STAGE_BREAK_OFF = 0,
ASSET_ZERO_SETTINGS_STAGE_BREAK_1ST = 1,
ASSET_ZERO_SETTINGS_STAGE_BREAK_2ND = 2,
ASSET_ZERO_SETTINGS_STAGE_BREAK_3RD = 3,
ASSET_ZERO_SETTINGS_STAGE_BREAK_4TH = 4,
ASSET_ZERO_SETTINGS_STAGE_BREAK_OFF = 0,
ASSET_ZERO_SETTINGS_STAGE_BREAK_1ST = 1,
ASSET_ZERO_SETTINGS_STAGE_BREAK_2ND = 2,
ASSET_ZERO_SETTINGS_STAGE_BREAK_3RD = 3,
ASSET_ZERO_SETTINGS_STAGE_BREAK_4TH = 4,
};
struct asset_zero_settings {
/* Padding to fill up to 4k EEPROM legacy size */
uint8_t ff_pad[0xBA4];
/* ZERO */
char ident[4];
uint32_t adler32;
uint32_t total_uptime;
uint8_t language;
uint32_t song_play_count[ASSET_ZERO_SETTINGS_MAX_SONGS];
uint32_t game_option_default_station;
uint8_t game_mode;
uint8_t game_level;
uint8_t game_stage_break;
/* 0 off, 1 on */
uint8_t game_demo_sound;
/* 0 off, 1 on */
uint8_t game_show_help;
/* 0 off, 1 on */
uint8_t game_mercy_ticket;
/* 0 off, 1 - 6 for score */
uint8_t game_score_per_ticket;
/* 0 none */
uint8_t coin_limit; // 0 none
/* 0 freeplay */
uint8_t coin1_setting;
/* 0 freeplay */
uint8_t coin2_setting;
/* Unlock flags for missions (total of 30) */
uint8_t mission_unlock_flags[ASSET_ZERO_SETTINGS_NUM_UNLOCK_FLAGS];
/* Default value 0x2A */
uint32_t unkn2;
uint32_t unkn3;
uint32_t bookkeeping_coin1_total;
uint32_t bookkeeping_coin2_total;
uint32_t bookkeeping_service_total;
uint32_t bookkeeping_ticket_1;
uint32_t bookkeeping_ticket_2;
/* FF -> not used, censoring globally disabled. unused feature though */
uint8_t region;
/* 0 = censoring of song off */
uint8_t censor_table[ASSET_ZERO_SETTINGS_MAX_SONGS];
/* Padding to fill up to 4k EEPROM legacy size */
uint8_t ff_pad[0xBA4];
/* ZERO */
char ident[4];
uint32_t adler32;
uint32_t total_uptime;
uint8_t language;
uint32_t song_play_count[ASSET_ZERO_SETTINGS_MAX_SONGS];
uint32_t game_option_default_station;
uint8_t game_mode;
uint8_t game_level;
uint8_t game_stage_break;
/* 0 off, 1 on */
uint8_t game_demo_sound;
/* 0 off, 1 on */
uint8_t game_show_help;
/* 0 off, 1 on */
uint8_t game_mercy_ticket;
/* 0 off, 1 - 6 for score */
uint8_t game_score_per_ticket;
/* 0 none */
uint8_t coin_limit; // 0 none
/* 0 freeplay */
uint8_t coin1_setting;
/* 0 freeplay */
uint8_t coin2_setting;
/* Unlock flags for missions (total of 30) */
uint8_t mission_unlock_flags[ASSET_ZERO_SETTINGS_NUM_UNLOCK_FLAGS];
/* Default value 0x2A */
uint32_t unkn2;
uint32_t unkn3;
uint32_t bookkeeping_coin1_total;
uint32_t bookkeeping_coin2_total;
uint32_t bookkeeping_service_total;
uint32_t bookkeeping_ticket_1;
uint32_t bookkeeping_ticket_2;
/* FF -> not used, censoring globally disabled. unused feature though */
uint8_t region;
/* 0 = censoring of song off */
uint8_t censor_table[ASSET_ZERO_SETTINGS_MAX_SONGS];
} __attribute__((__packed__));
struct asset_zero_settings* asset_zero_settings_new(void);
struct asset_zero_settings *asset_zero_settings_new(void);
// update checksum
void asset_zero_settings_finalize(struct asset_zero_settings* settings);
void asset_zero_settings_finalize(struct asset_zero_settings *settings);
// sets all missions cleared to unlock special stage songs and other missions
void asset_zero_settings_unlock_all(struct asset_zero_settings* settings);
void asset_zero_settings_unlock_all(struct asset_zero_settings *settings);
char* asset_zero_settings_to_string(const struct asset_zero_settings* settings);
char *asset_zero_settings_to_string(const struct asset_zero_settings *settings);
#endif
File diff suppressed because it is too large Load Diff
+26 -25
View File
@@ -18,33 +18,33 @@
* Available operations to hook
*/
enum cnh_filehook_irp_op {
CNH_FILEHOOK_IRP_OP_OPEN = 0,
CNH_FILEHOOK_IRP_OP_CLOSE = 1,
CNH_FILEHOOK_IRP_OP_READ = 2,
CNH_FILEHOOK_IRP_OP_WRITE = 3,
CNH_FILEHOOK_IRP_OP_FGETS = 4,
CNH_FILEHOOK_IRP_OP_SEEK = 5,
CNH_FILEHOOK_IRP_OP_TELL = 6,
CNH_FILEHOOK_IRP_OP_EOF = 7,
CNH_FILEHOOK_IRP_OP_OPEN = 0,
CNH_FILEHOOK_IRP_OP_CLOSE = 1,
CNH_FILEHOOK_IRP_OP_READ = 2,
CNH_FILEHOOK_IRP_OP_WRITE = 3,
CNH_FILEHOOK_IRP_OP_FGETS = 4,
CNH_FILEHOOK_IRP_OP_SEEK = 5,
CNH_FILEHOOK_IRP_OP_TELL = 6,
CNH_FILEHOOK_IRP_OP_EOF = 7,
};
/**
* I/O request packet
*/
struct cnh_filehook_irp {
enum cnh_filehook_irp_op op;
size_t next_handler;
FILE* file;
const char *open_filename;
const char* open_mode;
struct cnh_iobuf read;
struct cnh_const_iobuf write;
size_t orig_read_write_size;
size_t orig_read_write_nmemb;
int seek_origin;
int64_t seek_offset;
uint64_t tell_offset;
bool eof;
enum cnh_filehook_irp_op op;
size_t next_handler;
FILE *file;
const char *open_filename;
const char *open_mode;
struct cnh_iobuf read;
struct cnh_const_iobuf write;
size_t orig_read_write_size;
size_t orig_read_write_nmemb;
int seek_origin;
int64_t seek_offset;
uint64_t tell_offset;
bool eof;
};
/**
@@ -77,14 +77,15 @@ enum cnh_result cnh_filehook_invoke_next(struct cnh_filehook_irp *irp);
*
* @return Actual file handle instance pointing to a dummy endpoint.
*/
FILE* cnh_filehook_open_dummy_file_handle();
FILE *cnh_filehook_open_dummy_file_handle();
/**
* Close a dummy file handle. Make sure to free your previously allocated handles
* to avoid resource leaks. Do not free them using the real close function.
* Close a dummy file handle. Make sure to free your previously allocated
* handles to avoid resource leaks. Do not free them using the real close
* function.
*
* @param file Dummy file handle to free
*/
void cnh_filehook_close_dummy_file_handle(FILE* file);
void cnh_filehook_close_dummy_file_handle(FILE *file);
#endif
+288 -253
View File
@@ -3,8 +3,8 @@
#include <pthread.h>
#include <stdatomic.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
@@ -14,34 +14,48 @@
#include "util/time.h"
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Real funcs typedefs */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
typedef DIR* (*cnh_fshook_opendir_t)(const char* name);
typedef int (*cnh_fshook_lxstat_t)(int version, const char* file, struct stat* buf);
typedef int (*cnh_fshook_xstat_t)(int version, const char* file, struct stat* buf);
typedef int (*cnh_fshook_rename_t)(const char* old, const char* new);
typedef int (*cnh_fshook_remove_t)(const char* pathname);
typedef int (*cnh_fshook_access_t)(const char* path, int amode);
typedef DIR *(*cnh_fshook_opendir_t)(const char *name);
typedef int (*cnh_fshook_lxstat_t)(
int version, const char *file, struct stat *buf);
typedef int (*cnh_fshook_xstat_t)(
int version, const char *file, struct stat *buf);
typedef int (*cnh_fshook_rename_t)(const char *old, const char *new);
typedef int (*cnh_fshook_remove_t)(const char *pathname);
typedef int (*cnh_fshook_access_t)(const char *path, int amode);
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Private helpers */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
static void _cnh_fshook_init(void);
static enum cnh_result _cnh_fshook_invoke_real(struct cnh_fshook_irp *irp);
static enum cnh_result _cnh_fshook_invoke_real_opendir(struct cnh_fshook_irp *irp);
static enum cnh_result _cnh_fshook_invoke_real_lxstat(struct cnh_fshook_irp *irp);
static enum cnh_result _cnh_fshook_invoke_real_xstat(struct cnh_fshook_irp *irp);
static enum cnh_result _cnh_fshook_invoke_real_rename(struct cnh_fshook_irp *irp);
static enum cnh_result _cnh_fshook_invoke_real_remove(struct cnh_fshook_irp *irp);
static enum cnh_result _cnh_fshook_invoke_real_access(struct cnh_fshook_irp *irp);
static enum cnh_result
_cnh_fshook_invoke_real_opendir(struct cnh_fshook_irp *irp);
static enum cnh_result
_cnh_fshook_invoke_real_lxstat(struct cnh_fshook_irp *irp);
static enum cnh_result
_cnh_fshook_invoke_real_xstat(struct cnh_fshook_irp *irp);
static enum cnh_result
_cnh_fshook_invoke_real_rename(struct cnh_fshook_irp *irp);
static enum cnh_result
_cnh_fshook_invoke_real_remove(struct cnh_fshook_irp *irp);
static enum cnh_result
_cnh_fshook_invoke_real_access(struct cnh_fshook_irp *irp);
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Private state */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
static cnh_fshook_opendir_t _cnh_fshook_real_opendir;
static cnh_fshook_lxstat_t _cnh_fshook_real_lxstat;
@@ -65,383 +79,404 @@ static pthread_mutex_t _cnh_fshook_lock;
static cnh_fshook_fn_t *_cnh_fshook_handlers;
static size_t _cnh_fshook_nhandlers;
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Public module functions */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
enum cnh_result cnh_fshook_push_handler(cnh_fshook_fn_t fn)
{
cnh_fshook_fn_t *new_array;
size_t new_size;
enum cnh_result result;
cnh_fshook_fn_t *new_array;
size_t new_size;
enum cnh_result result;
assert(fn != NULL);
assert(fn != NULL);
_cnh_fshook_init();
_cnh_fshook_init();
pthread_mutex_lock(&_cnh_fshook_lock);
pthread_mutex_lock(&_cnh_fshook_lock);
new_size = _cnh_fshook_nhandlers + 1;
new_array = realloc(_cnh_fshook_handlers, new_size * sizeof(cnh_fshook_fn_t));
new_size = _cnh_fshook_nhandlers + 1;
new_array = realloc(_cnh_fshook_handlers, new_size * sizeof(cnh_fshook_fn_t));
if (new_array != NULL) {
_cnh_fshook_handlers = new_array;
_cnh_fshook_handlers[_cnh_fshook_nhandlers++] = fn;
result = CNH_RESULT_SUCCESS;
} else {
result = CNH_RESULT_OUT_OF_MEMORY;
}
if (new_array != NULL) {
_cnh_fshook_handlers = new_array;
_cnh_fshook_handlers[_cnh_fshook_nhandlers++] = fn;
result = CNH_RESULT_SUCCESS;
} else {
result = CNH_RESULT_OUT_OF_MEMORY;
}
pthread_mutex_unlock(&_cnh_fshook_lock);
pthread_mutex_unlock(&_cnh_fshook_lock);
return result;
return result;
}
enum cnh_result cnh_fshook_invoke_next(struct cnh_fshook_irp *irp)
{
cnh_fshook_fn_t handler;
enum cnh_result result;
cnh_fshook_fn_t handler;
enum cnh_result result;
assert(irp != NULL);
assert(_cnh_fshook_initted > 0);
assert(irp != NULL);
assert(_cnh_fshook_initted > 0);
pthread_mutex_lock(&_cnh_fshook_lock);
pthread_mutex_lock(&_cnh_fshook_lock);
assert(irp->next_handler <= _cnh_fshook_nhandlers);
assert(irp->next_handler <= _cnh_fshook_nhandlers);
if (irp->next_handler < _cnh_fshook_nhandlers) {
handler = _cnh_fshook_handlers[irp->next_handler];
irp->next_handler++;
} else {
handler = _cnh_fshook_invoke_real;
irp->next_handler = (size_t) -1;
}
if (irp->next_handler < _cnh_fshook_nhandlers) {
handler = _cnh_fshook_handlers[irp->next_handler];
irp->next_handler++;
} else {
handler = _cnh_fshook_invoke_real;
irp->next_handler = (size_t) -1;
}
pthread_mutex_unlock(&_cnh_fshook_lock);
pthread_mutex_unlock(&_cnh_fshook_lock);
result = handler(irp);
result = handler(irp);
if (result != CNH_RESULT_SUCCESS) {
irp->next_handler = (size_t) -1;
}
if (result != CNH_RESULT_SUCCESS) {
irp->next_handler = (size_t) -1;
}
return result;
return result;
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Hooked functions */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
DIR* opendir(const char* name)
DIR *opendir(const char *name)
{
struct cnh_fshook_irp irp;
enum cnh_result result;
struct cnh_fshook_irp irp;
enum cnh_result result;
/* Ensure module is initialized */
_cnh_fshook_init();
/* Ensure module is initialized */
_cnh_fshook_init();
memset(&irp, 0, sizeof(irp));
irp.op = CNH_FSHOOK_IRP_OP_DIR_OPEN;
irp.opendir_name = name;
irp.opendir_ret = NULL;
memset(&irp, 0, sizeof(irp));
irp.op = CNH_FSHOOK_IRP_OP_DIR_OPEN;
irp.opendir_name = name;
irp.opendir_ret = NULL;
result = cnh_fshook_invoke_next(&irp);
result = cnh_fshook_invoke_next(&irp);
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return NULL;
}
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return NULL;
}
errno = 0;
errno = 0;
return irp.opendir_ret;
return irp.opendir_ret;
}
int __lxstat(int version, const char* file, struct stat* buf)
int __lxstat(int version, const char *file, struct stat *buf)
{
struct cnh_fshook_irp irp;
enum cnh_result result;
struct cnh_fshook_irp irp;
enum cnh_result result;
/* Ensure module is initialized */
_cnh_fshook_init();
/* Ensure module is initialized */
_cnh_fshook_init();
memset(&irp, 0, sizeof(irp));
irp.op = CNH_FSHOOK_IRP_OP_LXSTAT;
irp.xstat_version = version;
irp.xstat_file = file;
irp.xstat_buf = buf;
memset(&irp, 0, sizeof(irp));
irp.op = CNH_FSHOOK_IRP_OP_LXSTAT;
irp.xstat_version = version;
irp.xstat_file = file;
irp.xstat_buf = buf;
result = cnh_fshook_invoke_next(&irp);
result = cnh_fshook_invoke_next(&irp);
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return -1;
}
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return -1;
}
errno = 0;
errno = 0;
return 0;
return 0;
}
int __xstat(int version, const char* file, struct stat* buf)
int __xstat(int version, const char *file, struct stat *buf)
{
struct cnh_fshook_irp irp;
enum cnh_result result;
struct cnh_fshook_irp irp;
enum cnh_result result;
/* Ensure module is initialized */
_cnh_fshook_init();
/* Ensure module is initialized */
_cnh_fshook_init();
memset(&irp, 0, sizeof(irp));
irp.op = CNH_FSHOOK_IRP_OP_XSTAT;
irp.xstat_version = version;
irp.xstat_file = file;
irp.xstat_buf = buf;
memset(&irp, 0, sizeof(irp));
irp.op = CNH_FSHOOK_IRP_OP_XSTAT;
irp.xstat_version = version;
irp.xstat_file = file;
irp.xstat_buf = buf;
result = cnh_fshook_invoke_next(&irp);
result = cnh_fshook_invoke_next(&irp);
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return -1;
}
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return -1;
}
errno = 0;
errno = 0;
return 0;
return 0;
}
int rename(const char* old, const char* new)
int rename(const char *old, const char *new)
{
struct cnh_fshook_irp irp;
enum cnh_result result;
struct cnh_fshook_irp irp;
enum cnh_result result;
/* Ensure module is initialized */
_cnh_fshook_init();
/* Ensure module is initialized */
_cnh_fshook_init();
if (old == NULL || new == NULL) {
errno = cnh_result_to_errno(CNH_RESULT_INVALID_PARAMETER);
return -1;
}
if (old == NULL || new == NULL) {
errno = cnh_result_to_errno(CNH_RESULT_INVALID_PARAMETER);
return -1;
}
memset(&irp, 0, sizeof(irp));
irp.op = CNH_FSHOOK_IRP_OP_RENAME;
irp.rename_old = old;
irp.rename_new = new;
memset(&irp, 0, sizeof(irp));
irp.op = CNH_FSHOOK_IRP_OP_RENAME;
irp.rename_old = old;
irp.rename_new = new;
result = cnh_fshook_invoke_next(&irp);
result = cnh_fshook_invoke_next(&irp);
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return -1;
}
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return -1;
}
errno = 0;
errno = 0;
return 0;
return 0;
}
int remove(const char* pathname)
int remove(const char *pathname)
{
struct cnh_fshook_irp irp;
enum cnh_result result;
struct cnh_fshook_irp irp;
enum cnh_result result;
/* Ensure module is initialized */
_cnh_fshook_init();
/* Ensure module is initialized */
_cnh_fshook_init();
if (pathname == NULL) {
errno = cnh_result_to_errno(CNH_RESULT_INVALID_PARAMETER);
return -1;
}
if (pathname == NULL) {
errno = cnh_result_to_errno(CNH_RESULT_INVALID_PARAMETER);
return -1;
}
memset(&irp, 0, sizeof(irp));
irp.op = CNH_FSHOOK_IRP_OP_REMOVE;
irp.remove_pathname = pathname;
memset(&irp, 0, sizeof(irp));
irp.op = CNH_FSHOOK_IRP_OP_REMOVE;
irp.remove_pathname = pathname;
result = cnh_fshook_invoke_next(&irp);
result = cnh_fshook_invoke_next(&irp);
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return -1;
}
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return -1;
}
errno = 0;
errno = 0;
return 0;
return 0;
}
int access(const char* path, int amode)
int access(const char *path, int amode)
{
struct cnh_fshook_irp irp;
enum cnh_result result;
struct cnh_fshook_irp irp;
enum cnh_result result;
/* Ensure module is initialized */
_cnh_fshook_init();
/* Ensure module is initialized */
_cnh_fshook_init();
if (path == NULL) {
errno = cnh_result_to_errno(CNH_RESULT_INVALID_PARAMETER);
return -1;
}
if (path == NULL) {
errno = cnh_result_to_errno(CNH_RESULT_INVALID_PARAMETER);
return -1;
}
memset(&irp, 0, sizeof(irp));
irp.op = CNH_FSHOOK_IRP_OP_ACCESS;
irp.access_path = path;
irp.access_amode = amode;
memset(&irp, 0, sizeof(irp));
irp.op = CNH_FSHOOK_IRP_OP_ACCESS;
irp.access_path = path;
irp.access_amode = amode;
result = cnh_fshook_invoke_next(&irp);
result = cnh_fshook_invoke_next(&irp);
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return -1;
}
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return -1;
}
errno = 0;
errno = 0;
return 0;
return 0;
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Helper functions */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
static void _cnh_fshook_init(void)
{
int expected;
int expected;
if (atomic_load(&_cnh_fshook_initted) > 0) {
return;
if (atomic_load(&_cnh_fshook_initted) > 0) {
return;
}
expected = 0;
if (!atomic_compare_exchange_strong(
&_cnh_fshook_init_in_progress, &expected, 1)) {
while (atomic_load(&_cnh_fshook_init_in_progress) > 1) {
util_time_sleep_us(100);
}
expected = 0;
return;
}
if (!atomic_compare_exchange_strong(&_cnh_fshook_init_in_progress, &expected, 1)) {
while (atomic_load(&_cnh_fshook_init_in_progress) > 1) {
util_time_sleep_us(100);
}
return;
}
/* Check again to ensure the current thread yielded between the init'd check and setting init in progress */
if (atomic_load(&_cnh_fshook_initted) > 0) {
/* Revert init in progress, because nothing to do anymore */
atomic_store(&_cnh_fshook_init_in_progress, 0);
return;
}
_cnh_fshook_real_opendir = (cnh_fshook_opendir_t) cnh_lib_get_func_addr("opendir");
_cnh_fshook_real_lxstat = (cnh_fshook_lxstat_t) cnh_lib_get_func_addr("__lxstat");
_cnh_fshook_real_xstat = (cnh_fshook_xstat_t) cnh_lib_get_func_addr("__xstat");
_cnh_fshook_real_rename = (cnh_fshook_rename_t) cnh_lib_get_func_addr("rename");
_cnh_fshook_real_remove = (cnh_fshook_remove_t) cnh_lib_get_func_addr("remove");
_cnh_fshook_real_access = (cnh_fshook_access_t) cnh_lib_get_func_addr("access");
pthread_mutex_init(&_cnh_fshook_lock, NULL);
atomic_store(&_cnh_fshook_initted, 1);
/* Check again to ensure the current thread yielded between the init'd check
* and setting init in progress */
if (atomic_load(&_cnh_fshook_initted) > 0) {
/* Revert init in progress, because nothing to do anymore */
atomic_store(&_cnh_fshook_init_in_progress, 0);
return;
}
_cnh_fshook_real_opendir =
(cnh_fshook_opendir_t) cnh_lib_get_func_addr("opendir");
_cnh_fshook_real_lxstat =
(cnh_fshook_lxstat_t) cnh_lib_get_func_addr("__lxstat");
_cnh_fshook_real_xstat =
(cnh_fshook_xstat_t) cnh_lib_get_func_addr("__xstat");
_cnh_fshook_real_rename =
(cnh_fshook_rename_t) cnh_lib_get_func_addr("rename");
_cnh_fshook_real_remove =
(cnh_fshook_remove_t) cnh_lib_get_func_addr("remove");
_cnh_fshook_real_access =
(cnh_fshook_access_t) cnh_lib_get_func_addr("access");
pthread_mutex_init(&_cnh_fshook_lock, NULL);
atomic_store(&_cnh_fshook_initted, 1);
atomic_store(&_cnh_fshook_init_in_progress, 0);
}
static enum cnh_result _cnh_fshook_invoke_real(struct cnh_fshook_irp *irp)
{
cnh_fshook_fn_t handler;
cnh_fshook_fn_t handler;
assert(irp != NULL);
assert(irp->op < _countof(_cnh_fshook_real_handlers));
assert(irp != NULL);
assert(irp->op < _countof(_cnh_fshook_real_handlers));
handler = _cnh_fshook_real_handlers[irp->op];
handler = _cnh_fshook_real_handlers[irp->op];
assert(handler != NULL);
assert(handler != NULL);
return handler(irp);
return handler(irp);
}
static enum cnh_result _cnh_fshook_invoke_real_opendir(struct cnh_fshook_irp *irp)
static enum cnh_result
_cnh_fshook_invoke_real_opendir(struct cnh_fshook_irp *irp)
{
DIR* dir;
DIR *dir;
assert(irp != NULL);
assert(irp != NULL);
dir = _cnh_fshook_real_opendir(irp->opendir_name);
dir = _cnh_fshook_real_opendir(irp->opendir_name);
if (dir == NULL) {
return cnh_errno_to_result(errno);
}
if (dir == NULL) {
return cnh_errno_to_result(errno);
}
irp->opendir_ret = dir;
irp->opendir_ret = dir;
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
static enum cnh_result _cnh_fshook_invoke_real_lxstat(struct cnh_fshook_irp *irp)
static enum cnh_result
_cnh_fshook_invoke_real_lxstat(struct cnh_fshook_irp *irp)
{
int res;
int res;
assert(irp != NULL);
assert(irp != NULL);
res = _cnh_fshook_real_lxstat(irp->xstat_version, irp->xstat_file, irp->xstat_buf);
res = _cnh_fshook_real_lxstat(
irp->xstat_version, irp->xstat_file, irp->xstat_buf);
if (res != 0) {
return cnh_errno_to_result(errno);
}
if (res != 0) {
return cnh_errno_to_result(errno);
}
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
static enum cnh_result _cnh_fshook_invoke_real_xstat(struct cnh_fshook_irp *irp)
{
int res;
int res;
assert(irp != NULL);
assert(irp != NULL);
res = _cnh_fshook_real_xstat(irp->xstat_version, irp->xstat_file, irp->xstat_buf);
res = _cnh_fshook_real_xstat(
irp->xstat_version, irp->xstat_file, irp->xstat_buf);
if (res != 0) {
return cnh_errno_to_result(errno);
}
if (res != 0) {
return cnh_errno_to_result(errno);
}
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
static enum cnh_result _cnh_fshook_invoke_real_rename(struct cnh_fshook_irp *irp)
static enum cnh_result
_cnh_fshook_invoke_real_rename(struct cnh_fshook_irp *irp)
{
int res;
int res;
assert(irp != NULL);
assert(irp != NULL);
res = _cnh_fshook_real_rename(irp->rename_old, irp->rename_new);
res = _cnh_fshook_real_rename(irp->rename_old, irp->rename_new);
if (res != 0) {
return cnh_errno_to_result(errno);
}
if (res != 0) {
return cnh_errno_to_result(errno);
}
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
static enum cnh_result _cnh_fshook_invoke_real_remove(struct cnh_fshook_irp *irp)
static enum cnh_result
_cnh_fshook_invoke_real_remove(struct cnh_fshook_irp *irp)
{
int res;
int res;
assert(irp != NULL);
assert(irp != NULL);
res = _cnh_fshook_real_remove(irp->remove_pathname);
res = _cnh_fshook_real_remove(irp->remove_pathname);
if (res != 0) {
return cnh_errno_to_result(errno);
}
if (res != 0) {
return cnh_errno_to_result(errno);
}
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
static enum cnh_result _cnh_fshook_invoke_real_access(struct cnh_fshook_irp *irp)
static enum cnh_result
_cnh_fshook_invoke_real_access(struct cnh_fshook_irp *irp)
{
int res;
int res;
assert(irp != NULL);
assert(irp != NULL);
res = _cnh_fshook_real_access(irp->access_path, irp->access_amode);
res = _cnh_fshook_real_access(irp->access_path, irp->access_amode);
if (res != 0) {
return cnh_errno_to_result(errno);
}
if (res != 0) {
return cnh_errno_to_result(errno);
}
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
+18 -18
View File
@@ -19,30 +19,30 @@
* Available operations to hook
*/
enum cnh_fshook_irp_op {
CNH_FSHOOK_IRP_OP_DIR_OPEN = 0,
CNH_FSHOOK_IRP_OP_LXSTAT = 1,
CNH_FSHOOK_IRP_OP_XSTAT = 2,
CNH_FSHOOK_IRP_OP_RENAME = 3,
CNH_FSHOOK_IRP_OP_REMOVE = 4,
CNH_FSHOOK_IRP_OP_ACCESS = 5,
CNH_FSHOOK_IRP_OP_DIR_OPEN = 0,
CNH_FSHOOK_IRP_OP_LXSTAT = 1,
CNH_FSHOOK_IRP_OP_XSTAT = 2,
CNH_FSHOOK_IRP_OP_RENAME = 3,
CNH_FSHOOK_IRP_OP_REMOVE = 4,
CNH_FSHOOK_IRP_OP_ACCESS = 5,
};
/**
* I/O request packet
*/
struct cnh_fshook_irp {
enum cnh_fshook_irp_op op;
size_t next_handler;
const char* opendir_name;
DIR* opendir_ret;
int xstat_version;
const char* xstat_file;
struct stat* xstat_buf;
const char* rename_old;
const char* rename_new;
const char* remove_pathname;
const char* access_path;
int access_amode;
enum cnh_fshook_irp_op op;
size_t next_handler;
const char *opendir_name;
DIR *opendir_ret;
int xstat_version;
const char *xstat_file;
struct stat *xstat_buf;
const char *rename_old;
const char *rename_new;
const char *remove_pathname;
const char *access_path;
int access_amode;
};
/**
+138 -136
View File
@@ -5,249 +5,251 @@
void cnh_iobuf_flip(struct cnh_const_iobuf *child, struct cnh_iobuf *parent)
{
assert(child != NULL);
assert(parent != NULL);
assert(child != NULL);
assert(parent != NULL);
child->bytes = parent->bytes;
child->pos = 0;
child->nbytes = parent->pos;
child->bytes = parent->bytes;
child->pos = 0;
child->nbytes = parent->pos;
}
size_t cnh_iobuf_move(struct cnh_iobuf *dest, struct cnh_const_iobuf *src)
{
size_t dest_avail;
size_t src_avail;
size_t chunksz;
size_t dest_avail;
size_t src_avail;
size_t chunksz;
assert(dest != NULL);
assert(dest->bytes != NULL || dest->nbytes == 0);
assert(dest->pos <= dest->nbytes);
assert(dest != NULL);
assert(dest->bytes != NULL || dest->nbytes == 0);
assert(dest->pos <= dest->nbytes);
assert(src != NULL);
assert(src->bytes != NULL || src->nbytes == 0);
assert(src->pos <= src->nbytes);
assert(src != NULL);
assert(src->bytes != NULL || src->nbytes == 0);
assert(src->pos <= src->nbytes);
dest_avail = dest->nbytes - dest->pos;
src_avail = src->nbytes - src->pos;
chunksz = dest_avail < src_avail ? dest_avail : src_avail;
dest_avail = dest->nbytes - dest->pos;
src_avail = src->nbytes - src->pos;
chunksz = dest_avail < src_avail ? dest_avail : src_avail;
memcpy(&dest->bytes[dest->pos], &src->bytes[src->pos], chunksz);
memcpy(&dest->bytes[dest->pos], &src->bytes[src->pos], chunksz);
dest->pos += chunksz;
src->pos += chunksz;
dest->pos += chunksz;
src->pos += chunksz;
return chunksz;
return chunksz;
}
size_t cnh_iobuf_shift(struct cnh_iobuf *dest, struct cnh_iobuf *src)
{
struct cnh_const_iobuf span;
struct cnh_const_iobuf span;
assert(dest != NULL);
assert(src != NULL);
assert(dest != NULL);
assert(src != NULL);
cnh_iobuf_flip(&span, src);
cnh_iobuf_move(dest, &span);
cnh_iobuf_flip(&span, src);
cnh_iobuf_move(dest, &span);
memmove(src->bytes, &src->bytes[span.pos], span.nbytes - span.pos);
src->pos -= span.pos;
memmove(src->bytes, &src->bytes[span.pos], span.nbytes - span.pos);
src->pos -= span.pos;
return span.pos;
return span.pos;
}
enum cnh_result cnh_iobuf_read(struct cnh_const_iobuf *src, void *bytes, size_t nbytes)
enum cnh_result
cnh_iobuf_read(struct cnh_const_iobuf *src, void *bytes, size_t nbytes)
{
assert(src != NULL);
assert(bytes != NULL || nbytes == 0);
assert(src != NULL);
assert(bytes != NULL || nbytes == 0);
if (src->pos + nbytes > src->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
if (src->pos + nbytes > src->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
memcpy(bytes, &src->bytes[src->pos], nbytes);
src->pos += nbytes;
memcpy(bytes, &src->bytes[src->pos], nbytes);
src->pos += nbytes;
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
enum cnh_result cnh_iobuf_read_8(struct cnh_const_iobuf *src, uint8_t *out)
{
assert(src != NULL);
assert(out != NULL);
assert(src != NULL);
assert(out != NULL);
if (src->pos + sizeof(uint8_t) > src->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
if (src->pos + sizeof(uint8_t) > src->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
*out = src->bytes[src->pos++];
*out = src->bytes[src->pos++];
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
enum cnh_result cnh_iobuf_read_be16(struct cnh_const_iobuf *src, uint16_t *out)
{
uint16_t value;
uint16_t value;
assert(src != NULL);
assert(out != NULL);
assert(src != NULL);
assert(out != NULL);
if (src->pos + sizeof(uint16_t) > src->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
if (src->pos + sizeof(uint16_t) > src->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
value = src->bytes[src->pos++] << 8;
value |= src->bytes[src->pos++];
value = src->bytes[src->pos++] << 8;
value |= src->bytes[src->pos++];
*out = value;
*out = value;
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
enum cnh_result cnh_iobuf_read_be32(struct cnh_const_iobuf *src, uint32_t *out)
{
uint32_t value;
uint32_t value;
assert(src != NULL);
assert(out != NULL);
assert(src != NULL);
assert(out != NULL);
if (src->pos + sizeof(uint32_t) > src->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
if (src->pos + sizeof(uint32_t) > src->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
value = src->bytes[src->pos++] << 24;
value |= src->bytes[src->pos++] << 16;
value |= src->bytes[src->pos++] << 8;
value |= src->bytes[src->pos++];
value = src->bytes[src->pos++] << 24;
value |= src->bytes[src->pos++] << 16;
value |= src->bytes[src->pos++] << 8;
value |= src->bytes[src->pos++];
*out = value;
*out = value;
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
enum cnh_result cnh_iobuf_read_le16(struct cnh_const_iobuf *src, uint16_t *out)
{
uint16_t value;
uint16_t value;
assert(src != NULL);
assert(out != NULL);
assert(src != NULL);
assert(out != NULL);
if (src->pos + sizeof(uint16_t) > src->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
if (src->pos + sizeof(uint16_t) > src->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
value = src->bytes[src->pos++];
value |= src->bytes[src->pos++] << 8;
value = src->bytes[src->pos++];
value |= src->bytes[src->pos++] << 8;
*out = value;
*out = value;
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
enum cnh_result cnh_iobuf_read_le32(struct cnh_const_iobuf *src, uint32_t *out)
{
uint32_t value;
uint32_t value;
assert(src != NULL);
assert(out != NULL);
assert(src != NULL);
assert(out != NULL);
if (src->pos + sizeof(uint32_t) > src->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
if (src->pos + sizeof(uint32_t) > src->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
value = src->bytes[src->pos++];
value |= src->bytes[src->pos++] << 8;
value |= src->bytes[src->pos++] << 16;
value |= src->bytes[src->pos++] << 24;
value = src->bytes[src->pos++];
value |= src->bytes[src->pos++] << 8;
value |= src->bytes[src->pos++] << 16;
value |= src->bytes[src->pos++] << 24;
*out = value;
*out = value;
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
enum cnh_result cnh_iobuf_write(struct cnh_iobuf *dest, const void *bytes, size_t nbytes)
enum cnh_result
cnh_iobuf_write(struct cnh_iobuf *dest, const void *bytes, size_t nbytes)
{
assert(dest != NULL);
assert(bytes != NULL || nbytes == 0);
assert(dest != NULL);
assert(bytes != NULL || nbytes == 0);
if (dest->pos + nbytes > dest->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
if (dest->pos + nbytes > dest->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
memcpy(&dest->bytes[dest->pos], bytes, nbytes);
dest->pos += nbytes;
memcpy(&dest->bytes[dest->pos], bytes, nbytes);
dest->pos += nbytes;
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
enum cnh_result cnh_iobuf_write_8(struct cnh_iobuf *dest, uint8_t value)
{
assert(dest != NULL);
assert(dest != NULL);
if (dest->pos + sizeof(uint8_t) > dest->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
if (dest->pos + sizeof(uint8_t) > dest->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
dest->bytes[dest->pos++] = value;
dest->bytes[dest->pos++] = value;
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
enum cnh_result cnh_iobuf_write_be16(struct cnh_iobuf *dest, uint16_t value)
{
assert(dest != NULL);
assert(dest != NULL);
if (dest->pos + sizeof(uint16_t) > dest->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
if (dest->pos + sizeof(uint16_t) > dest->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
dest->bytes[dest->pos++] = (uint8_t) (value >> 8);
dest->bytes[dest->pos++] = (uint8_t) value;
dest->bytes[dest->pos++] = (uint8_t)(value >> 8);
dest->bytes[dest->pos++] = (uint8_t) value;
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
enum cnh_result cnh_iobuf_write_be32(struct cnh_iobuf *dest, uint32_t value)
{
assert(dest != NULL);
assert(dest != NULL);
if (dest->pos + sizeof(uint32_t) > dest->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
if (dest->pos + sizeof(uint32_t) > dest->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
dest->bytes[dest->pos++] = (uint8_t) (value >> 24);
dest->bytes[dest->pos++] = (uint8_t) (value >> 16);
dest->bytes[dest->pos++] = (uint8_t) (value >> 8);
dest->bytes[dest->pos++] = (uint8_t) value;
dest->bytes[dest->pos++] = (uint8_t)(value >> 24);
dest->bytes[dest->pos++] = (uint8_t)(value >> 16);
dest->bytes[dest->pos++] = (uint8_t)(value >> 8);
dest->bytes[dest->pos++] = (uint8_t) value;
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
enum cnh_result cnh_iobuf_write_le16(struct cnh_iobuf *dest, uint16_t value)
{
assert(dest != NULL);
assert(dest != NULL);
if (dest->pos + sizeof(uint16_t) > dest->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
if (dest->pos + sizeof(uint16_t) > dest->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
dest->bytes[dest->pos++] = (uint8_t) value;
dest->bytes[dest->pos++] = (uint8_t) (value >> 8);
dest->bytes[dest->pos++] = (uint8_t) value;
dest->bytes[dest->pos++] = (uint8_t)(value >> 8);
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
enum cnh_result cnh_iobuf_write_le32(struct cnh_iobuf *dest, uint32_t value)
{
assert(dest != NULL);
assert(dest != NULL);
if (dest->pos + sizeof(uint32_t) > dest->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
if (dest->pos + sizeof(uint32_t) > dest->nbytes) {
return CNH_RESULT_ERROR_INSUFFICIENT_BUFFER;
}
dest->bytes[dest->pos++] = (uint8_t) value;
dest->bytes[dest->pos++] = (uint8_t) (value >> 8);
dest->bytes[dest->pos++] = (uint8_t) (value >> 16);
dest->bytes[dest->pos++] = (uint8_t) (value >> 24);
dest->bytes[dest->pos++] = (uint8_t) value;
dest->bytes[dest->pos++] = (uint8_t)(value >> 8);
dest->bytes[dest->pos++] = (uint8_t)(value >> 16);
dest->bytes[dest->pos++] = (uint8_t)(value >> 24);
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
+22 -14
View File
@@ -16,18 +16,18 @@
* I/O buffer
*/
struct cnh_iobuf {
uint8_t *bytes;
size_t nbytes;
size_t pos;
uint8_t *bytes;
size_t nbytes;
size_t pos;
};
/**
* I/O buffer
*/
struct cnh_const_iobuf {
const uint8_t *bytes;
size_t nbytes;
size_t pos;
const uint8_t *bytes;
size_t nbytes;
size_t pos;
};
/**
@@ -39,10 +39,12 @@ struct cnh_const_iobuf {
void cnh_iobuf_flip(struct cnh_const_iobuf *child, struct cnh_iobuf *parent);
/**
* Move the contents currently enclosed by pos and end of an I/O buffer to a destination.
* Move the contents currently enclosed by pos and end of an I/O buffer to a
* destination.
*
* @param dest Destination buffer to move the source to, starting at current pos
* @param src Source to move to the destination, starting at current pos up to end of the buffer
* @param src Source to move to the destination, starting at current pos up to
* end of the buffer
* @return Number of bytes copied to destination
*/
size_t cnh_iobuf_move(struct cnh_iobuf *dest, struct cnh_const_iobuf *src);
@@ -57,7 +59,8 @@ size_t cnh_iobuf_shift(struct cnh_iobuf *dest, struct cnh_iobuf *src);
* @param nbytes Number of bytes to read
* @return Result of operation
*/
enum cnh_result cnh_iobuf_read(struct cnh_const_iobuf *src, void *bytes, size_t nbytes);
enum cnh_result
cnh_iobuf_read(struct cnh_const_iobuf *src, void *bytes, size_t nbytes);
/**
* Read a byte from an I/O buffer
@@ -75,7 +78,8 @@ enum cnh_result cnh_iobuf_read_8(struct cnh_const_iobuf *src, uint8_t *value);
* @param value Pointer to variable to read the data into
* @return Result of operation
*/
enum cnh_result cnh_iobuf_read_be16(struct cnh_const_iobuf *src, uint16_t *value);
enum cnh_result
cnh_iobuf_read_be16(struct cnh_const_iobuf *src, uint16_t *value);
/**
* Read a 4 byte value, big endian byte order, from an I/O buffer
@@ -84,7 +88,8 @@ enum cnh_result cnh_iobuf_read_be16(struct cnh_const_iobuf *src, uint16_t *value
* @param value Pointer to variable to read the data into
* @return Result of operation
*/
enum cnh_result cnh_iobuf_read_be32(struct cnh_const_iobuf *src, uint32_t *value);
enum cnh_result
cnh_iobuf_read_be32(struct cnh_const_iobuf *src, uint32_t *value);
/**
* Read a 2 byte value, little endian byte order, from an I/O buffer
@@ -93,7 +98,8 @@ enum cnh_result cnh_iobuf_read_be32(struct cnh_const_iobuf *src, uint32_t *value
* @param value Pointer to variable to read the data into
* @return Result of operation
*/
enum cnh_result cnh_iobuf_read_le16(struct cnh_const_iobuf *src, uint16_t *value);
enum cnh_result
cnh_iobuf_read_le16(struct cnh_const_iobuf *src, uint16_t *value);
/**
* Read a 4 byte value, little endian byte order, from an I/O buffer
@@ -102,7 +108,8 @@ enum cnh_result cnh_iobuf_read_le16(struct cnh_const_iobuf *src, uint16_t *value
* @param value Pointer to variable to read the data into
* @return Result of operation
*/
enum cnh_result cnh_iobuf_read_le32(struct cnh_const_iobuf *src, uint32_t *value);
enum cnh_result
cnh_iobuf_read_le32(struct cnh_const_iobuf *src, uint32_t *value);
/**
* Write data to an I/O buffer
@@ -112,7 +119,8 @@ enum cnh_result cnh_iobuf_read_le32(struct cnh_const_iobuf *src, uint32_t *value
* @param nbytes Number of bytes to write
* @return Result of operation
*/
enum cnh_result cnh_iobuf_write(struct cnh_iobuf *dest, const void *bytes, size_t nbytes);
enum cnh_result
cnh_iobuf_write(struct cnh_iobuf *dest, const void *bytes, size_t nbytes);
/**
* Write a byte to an I/O buffer
+332 -305
View File
@@ -15,36 +15,46 @@
#define INVALID_FILE_DEVICE (-1)
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Real funcs typedefs */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
typedef int (*cnh_iohook_open_t)(const char* path, int oflag);
typedef FILE* (*cnh_iohook_fdopen_t)(int fd, const char* mode);
typedef ssize_t (*cnh_iohook_write_t)(int fd, const void* buf, size_t count);
typedef ssize_t (*cnh_iohook_read_t)(int fd, void* buf, size_t count);
typedef int (*cnh_iohook_open_t)(const char *path, int oflag);
typedef FILE *(*cnh_iohook_fdopen_t)(int fd, const char *mode);
typedef ssize_t (*cnh_iohook_write_t)(int fd, const void *buf, size_t count);
typedef ssize_t (*cnh_iohook_read_t)(int fd, void *buf, size_t count);
typedef off_t (*cnh_iohook_lseek_t)(int fildes, off_t offset, int whence);
typedef int (*cnh_iohook_ioctl_t)(int fd, int request, void* data);
typedef int (*cnh_iohook_ioctl_t)(int fd, int request, void *data);
typedef int (*cnh_iohook_close_t)(int fd);
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Private helpers */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
static void _cnh_iohook_init(void);
static enum cnh_result _cnh_iohook_invoke_real(struct cnh_iohook_irp *irp);
static enum cnh_result _cnh_iohook_invoke_real_open(struct cnh_iohook_irp *irp);
static enum cnh_result _cnh_iohook_invoke_real_fdopen(struct cnh_iohook_irp *irp);
static enum cnh_result _cnh_iohook_invoke_real_close(struct cnh_iohook_irp *irp);
static enum cnh_result
_cnh_iohook_invoke_real_fdopen(struct cnh_iohook_irp *irp);
static enum cnh_result
_cnh_iohook_invoke_real_close(struct cnh_iohook_irp *irp);
static enum cnh_result _cnh_iohook_invoke_real_read(struct cnh_iohook_irp *irp);
static enum cnh_result _cnh_iohook_invoke_real_write(struct cnh_iohook_irp *irp);
static enum cnh_result
_cnh_iohook_invoke_real_write(struct cnh_iohook_irp *irp);
static enum cnh_result _cnh_iohook_invoke_real_seek(struct cnh_iohook_irp *irp);
static enum cnh_result _cnh_iohook_invoke_real_ioctl(struct cnh_iohook_irp *irp);
static enum cnh_result
_cnh_iohook_invoke_real_ioctl(struct cnh_iohook_irp *irp);
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Private state */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
static cnh_iohook_open_t _cnh_iohook_real_open;
static cnh_iohook_fdopen_t _cnh_iohook_real_fdopen;
@@ -70,483 +80,500 @@ static pthread_mutex_t _cnh_iohook_lock;
static cnh_iohook_fn_t *_cnh_iohook_handlers;
static size_t _cnh_iohook_nhandlers;
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Public module functions */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
enum cnh_result cnh_iohook_push_handler(cnh_iohook_fn_t fn)
{
cnh_iohook_fn_t *new_array;
size_t new_size;
enum cnh_result result;
cnh_iohook_fn_t *new_array;
size_t new_size;
enum cnh_result result;
assert(fn != NULL);
assert(fn != NULL);
_cnh_iohook_init();
pthread_mutex_lock(&_cnh_iohook_lock);
_cnh_iohook_init();
pthread_mutex_lock(&_cnh_iohook_lock);
new_size = _cnh_iohook_nhandlers + 1;
new_array = realloc(_cnh_iohook_handlers, new_size * sizeof(cnh_iohook_fn_t));
new_size = _cnh_iohook_nhandlers + 1;
new_array = realloc(_cnh_iohook_handlers, new_size * sizeof(cnh_iohook_fn_t));
if (new_array != NULL) {
_cnh_iohook_handlers = new_array;
_cnh_iohook_handlers[_cnh_iohook_nhandlers++] = fn;
result = CNH_RESULT_SUCCESS;
} else {
result = CNH_RESULT_OUT_OF_MEMORY;
}
if (new_array != NULL) {
_cnh_iohook_handlers = new_array;
_cnh_iohook_handlers[_cnh_iohook_nhandlers++] = fn;
result = CNH_RESULT_SUCCESS;
} else {
result = CNH_RESULT_OUT_OF_MEMORY;
}
pthread_mutex_unlock(&_cnh_iohook_lock);
pthread_mutex_unlock(&_cnh_iohook_lock);
return result;
return result;
}
enum cnh_result cnh_iohook_invoke_next(struct cnh_iohook_irp *irp)
{
cnh_iohook_fn_t handler;
enum cnh_result result;
cnh_iohook_fn_t handler;
enum cnh_result result;
assert(irp != NULL);
assert(_cnh_iohook_initted > 0);
assert(irp != NULL);
assert(_cnh_iohook_initted > 0);
pthread_mutex_lock(&_cnh_iohook_lock);
pthread_mutex_lock(&_cnh_iohook_lock);
assert(irp->next_handler <= _cnh_iohook_nhandlers);
assert(irp->next_handler <= _cnh_iohook_nhandlers);
if (irp->next_handler < _cnh_iohook_nhandlers) {
handler = _cnh_iohook_handlers[irp->next_handler];
irp->next_handler++;
} else {
handler = _cnh_iohook_invoke_real;
irp->next_handler = (size_t) -1;
}
if (irp->next_handler < _cnh_iohook_nhandlers) {
handler = _cnh_iohook_handlers[irp->next_handler];
irp->next_handler++;
} else {
handler = _cnh_iohook_invoke_real;
irp->next_handler = (size_t) -1;
}
pthread_mutex_unlock(&_cnh_iohook_lock);
pthread_mutex_unlock(&_cnh_iohook_lock);
result = handler(irp);
result = handler(irp);
if (result != CNH_RESULT_SUCCESS) {
irp->next_handler = (size_t) -1;
}
if (result != CNH_RESULT_SUCCESS) {
irp->next_handler = (size_t) -1;
}
return result;
return result;
}
int cnh_iohook_open_dummy_fd()
{
_cnh_iohook_init();
_cnh_iohook_init();
/* We need to return some sort of valid FD to the
caller, since we're simulating a device that
doesn't exist. Open an FD on /dev/null. */
/* We need to return some sort of valid FD to the
caller, since we're simulating a device that
doesn't exist. Open an FD on /dev/null. */
/* Open read only */
return _cnh_iohook_real_open("/dev/null", 0);
/* Open read only */
return _cnh_iohook_real_open("/dev/null", 0);
}
void cnh_iohook_close_dummy_fd(int fd)
{
_cnh_iohook_init();
_cnh_iohook_init();
/* Avoid hooking pipeline when using dummy handles */
_cnh_iohook_real_close(fd);
/* Avoid hooking pipeline when using dummy handles */
_cnh_iohook_real_close(fd);
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Hooked functions */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
int open(const char* path, int oflag)
int open(const char *path, int oflag)
{
struct cnh_iohook_irp irp;
enum cnh_result result;
struct cnh_iohook_irp irp;
enum cnh_result result;
/* Ensure module is initialized */
_cnh_iohook_init();
/* Ensure module is initialized */
_cnh_iohook_init();
if (path == NULL) {
errno = cnh_result_to_errno(CNH_RESULT_INVALID_PARAMETER);
return INVALID_FILE_DEVICE;
}
if (path == NULL) {
errno = cnh_result_to_errno(CNH_RESULT_INVALID_PARAMETER);
return INVALID_FILE_DEVICE;
}
memset(&irp, 0, sizeof(irp));
irp.op = CNH_IOHOOK_IRP_OP_OPEN;
irp.fd = INVALID_FILE_DEVICE;
irp.open_filename = path;
irp.open_flags = oflag;
memset(&irp, 0, sizeof(irp));
irp.op = CNH_IOHOOK_IRP_OP_OPEN;
irp.fd = INVALID_FILE_DEVICE;
irp.open_filename = path;
irp.open_flags = oflag;
result = cnh_iohook_invoke_next(&irp);
result = cnh_iohook_invoke_next(&irp);
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return INVALID_FILE_DEVICE;
}
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return INVALID_FILE_DEVICE;
}
errno = 0;
errno = 0;
return irp.fd;
return irp.fd;
}
FILE* fdopen(int fd, const char* mode)
FILE *fdopen(int fd, const char *mode)
{
struct cnh_iohook_irp irp;
enum cnh_result result;
struct cnh_iohook_irp irp;
enum cnh_result result;
/* Ensure module is initialized */
_cnh_iohook_init();
/* Ensure module is initialized */
_cnh_iohook_init();
if (fd == -1 || mode == NULL) {
errno = cnh_result_to_errno(CNH_RESULT_INVALID_PARAMETER);
return NULL;
}
if (fd == -1 || mode == NULL) {
errno = cnh_result_to_errno(CNH_RESULT_INVALID_PARAMETER);
return NULL;
}
memset(&irp, 0, sizeof(irp));
irp.op = CNH_IOHOOK_IRP_OP_FDOPEN;
irp.fdopen_fd = fd;
irp.fdopen_mode = mode;
irp.fdopen_res = NULL;
memset(&irp, 0, sizeof(irp));
irp.op = CNH_IOHOOK_IRP_OP_FDOPEN;
irp.fdopen_fd = fd;
irp.fdopen_mode = mode;
irp.fdopen_res = NULL;
result = cnh_iohook_invoke_next(&irp);
result = cnh_iohook_invoke_next(&irp);
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return NULL;
}
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return NULL;
}
errno = 0;
errno = 0;
return irp.fdopen_res;
return irp.fdopen_res;
}
int close(int fd)
{
struct cnh_iohook_irp irp;
enum cnh_result result;
struct cnh_iohook_irp irp;
enum cnh_result result;
/* Ensure module is initialized */
_cnh_iohook_init();
/* Ensure module is initialized */
_cnh_iohook_init();
if (fd == INVALID_FILE_DEVICE) {
errno = cnh_result_to_errno(CNH_RESULT_INVALID_PARAMETER);
return -1;
}
if (fd == INVALID_FILE_DEVICE) {
errno = cnh_result_to_errno(CNH_RESULT_INVALID_PARAMETER);
return -1;
}
memset(&irp, 0, sizeof(irp));
irp.op = CNH_IOHOOK_IRP_OP_CLOSE;
irp.fd = fd;
memset(&irp, 0, sizeof(irp));
irp.op = CNH_IOHOOK_IRP_OP_CLOSE;
irp.fd = fd;
result = cnh_iohook_invoke_next(&irp);
result = cnh_iohook_invoke_next(&irp);
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return -1;
}
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return -1;
}
errno = 0;
errno = 0;
return 0;
return 0;
}
ssize_t read(int fd, void* buf, size_t count)
ssize_t read(int fd, void *buf, size_t count)
{
struct cnh_iohook_irp irp;
enum cnh_result result;
struct cnh_iohook_irp irp;
enum cnh_result result;
/* Ensure module is initialized */
_cnh_iohook_init();
/* Ensure module is initialized */
_cnh_iohook_init();
if (fd == INVALID_FILE_DEVICE || buf == NULL) {
errno = cnh_result_to_errno(CNH_RESULT_INVALID_PARAMETER);
return -1;
}
if (fd == INVALID_FILE_DEVICE || buf == NULL) {
errno = cnh_result_to_errno(CNH_RESULT_INVALID_PARAMETER);
return -1;
}
memset(&irp, 0, sizeof(irp));
irp.op = CNH_IOHOOK_IRP_OP_READ;
irp.fd = fd;
irp.read.bytes = buf;
irp.read.nbytes = count;
irp.read.pos = 0;
memset(&irp, 0, sizeof(irp));
irp.op = CNH_IOHOOK_IRP_OP_READ;
irp.fd = fd;
irp.read.bytes = buf;
irp.read.nbytes = count;
irp.read.pos = 0;
result = cnh_iohook_invoke_next(&irp);
result = cnh_iohook_invoke_next(&irp);
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return -1;
}
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return -1;
}
assert(irp.read.pos <= irp.read.nbytes);
assert(irp.read.pos <= irp.read.nbytes);
errno = 0;
errno = 0;
return irp.read.pos;
return irp.read.pos;
}
ssize_t write(int fd, const void* buf, size_t count)
ssize_t write(int fd, const void *buf, size_t count)
{
struct cnh_iohook_irp irp;
enum cnh_result result;
struct cnh_iohook_irp irp;
enum cnh_result result;
/* Ensure module is initialized */
_cnh_iohook_init();
/* Ensure module is initialized */
_cnh_iohook_init();
if (fd == INVALID_FILE_DEVICE || buf == NULL) {
errno = cnh_result_to_errno(CNH_RESULT_INVALID_PARAMETER);
return -1;
}
if (fd == INVALID_FILE_DEVICE || buf == NULL) {
errno = cnh_result_to_errno(CNH_RESULT_INVALID_PARAMETER);
return -1;
}
memset(&irp, 0, sizeof(irp));
irp.op = CNH_IOHOOK_IRP_OP_WRITE;
irp.fd = fd;
irp.write.bytes = buf;
irp.write.nbytes = count;
irp.write.pos = 0;
memset(&irp, 0, sizeof(irp));
irp.op = CNH_IOHOOK_IRP_OP_WRITE;
irp.fd = fd;
irp.write.bytes = buf;
irp.write.nbytes = count;
irp.write.pos = 0;
result = cnh_iohook_invoke_next(&irp);
result = cnh_iohook_invoke_next(&irp);
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return -1;
}
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return -1;
}
assert(irp.write.pos <= irp.write.nbytes);
assert(irp.write.pos <= irp.write.nbytes);
errno = 0;
errno = 0;
return irp.write.pos;
return irp.write.pos;
}
off_t lseek(int fd, off_t offset, int whence)
{
struct cnh_iohook_irp irp;
enum cnh_result result;
struct cnh_iohook_irp irp;
enum cnh_result result;
/* Ensure module is initialized */
_cnh_iohook_init();
/* Ensure module is initialized */
_cnh_iohook_init();
if (fd == INVALID_FILE_DEVICE) {
errno = cnh_result_to_errno(CNH_RESULT_INVALID_PARAMETER);
return -1;
}
if (fd == INVALID_FILE_DEVICE) {
errno = cnh_result_to_errno(CNH_RESULT_INVALID_PARAMETER);
return -1;
}
memset(&irp, 0, sizeof(irp));
irp.op = CNH_IOHOOK_IRP_OP_SEEK;
irp.fd = fd;
irp.seek_origin = whence;
irp.seek_offset = offset;
memset(&irp, 0, sizeof(irp));
irp.op = CNH_IOHOOK_IRP_OP_SEEK;
irp.fd = fd;
irp.seek_origin = whence;
irp.seek_offset = offset;
result = cnh_iohook_invoke_next(&irp);
result = cnh_iohook_invoke_next(&irp);
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return -1;
}
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return -1;
}
errno = 0;
errno = 0;
return (off_t) irp.seek_pos;
return (off_t) irp.seek_pos;
}
int ioctl(int fd, int request, void* data)
int ioctl(int fd, int request, void *data)
{
struct cnh_iohook_irp irp;
enum cnh_result result;
struct cnh_iohook_irp irp;
enum cnh_result result;
/* Ensure module is initialized */
_cnh_iohook_init();
/* Ensure module is initialized */
_cnh_iohook_init();
if (fd == INVALID_FILE_DEVICE) {
errno = cnh_result_to_errno(CNH_RESULT_INVALID_PARAMETER);
return -1;
}
if (fd == INVALID_FILE_DEVICE) {
errno = cnh_result_to_errno(CNH_RESULT_INVALID_PARAMETER);
return -1;
}
memset(&irp, 0, sizeof(irp));
irp.op = CNH_IOHOOK_IRP_OP_IOCTL;
irp.fd = fd;
irp.ioctl_req = request;
irp.ioctl.bytes = data;
memset(&irp, 0, sizeof(irp));
irp.op = CNH_IOHOOK_IRP_OP_IOCTL;
irp.fd = fd;
irp.ioctl_req = request;
irp.ioctl.bytes = data;
result = cnh_iohook_invoke_next(&irp);
result = cnh_iohook_invoke_next(&irp);
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return -1;
}
if (result != CNH_RESULT_SUCCESS) {
errno = cnh_result_to_errno(result);
return -1;
}
errno = 0;
errno = 0;
return irp.ioctl.pos;
return irp.ioctl.pos;
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Helper functions */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
static void _cnh_iohook_init(void)
{
int expected;
int expected;
if (atomic_load(&_cnh_iohook_initted) > 0) {
return;
if (atomic_load(&_cnh_iohook_initted) > 0) {
return;
}
expected = 0;
if (!atomic_compare_exchange_strong(
&_cnh_iohook_init_in_progress, &expected, 1)) {
while (atomic_load(&_cnh_iohook_init_in_progress) > 1) {
util_time_sleep_us(100);
}
expected = 0;
return;
}
if (!atomic_compare_exchange_strong(&_cnh_iohook_init_in_progress, &expected, 1)) {
while (atomic_load(&_cnh_iohook_init_in_progress) > 1) {
util_time_sleep_us(100);
}
return;
}
/* Check again to ensure the current thread yielded between the init'd check and setting init in progress */
if (atomic_load(&_cnh_iohook_initted) > 0) {
/* Revert init in progress, because nothing to do anymore */
atomic_store(&_cnh_iohook_init_in_progress, 0);
return;
}
_cnh_iohook_real_open = (cnh_iohook_open_t) cnh_lib_get_func_addr("open");
_cnh_iohook_real_fdopen = (cnh_iohook_fdopen_t) cnh_lib_get_func_addr("fdopen");
_cnh_iohook_real_close = (cnh_iohook_close_t) cnh_lib_get_func_addr("close");
_cnh_iohook_real_read = (cnh_iohook_read_t) cnh_lib_get_func_addr("read");
_cnh_iohook_real_write = (cnh_iohook_write_t) cnh_lib_get_func_addr("write");
_cnh_iohook_real_lseek = (cnh_iohook_lseek_t) cnh_lib_get_func_addr("lseek");
_cnh_iohook_real_ioctl = (cnh_iohook_ioctl_t) cnh_lib_get_func_addr("ioctl");
pthread_mutex_init(&_cnh_iohook_lock, NULL);
atomic_store(&_cnh_iohook_initted, 1);
/* Check again to ensure the current thread yielded between the init'd check
* and setting init in progress */
if (atomic_load(&_cnh_iohook_initted) > 0) {
/* Revert init in progress, because nothing to do anymore */
atomic_store(&_cnh_iohook_init_in_progress, 0);
return;
}
_cnh_iohook_real_open = (cnh_iohook_open_t) cnh_lib_get_func_addr("open");
_cnh_iohook_real_fdopen =
(cnh_iohook_fdopen_t) cnh_lib_get_func_addr("fdopen");
_cnh_iohook_real_close = (cnh_iohook_close_t) cnh_lib_get_func_addr("close");
_cnh_iohook_real_read = (cnh_iohook_read_t) cnh_lib_get_func_addr("read");
_cnh_iohook_real_write = (cnh_iohook_write_t) cnh_lib_get_func_addr("write");
_cnh_iohook_real_lseek = (cnh_iohook_lseek_t) cnh_lib_get_func_addr("lseek");
_cnh_iohook_real_ioctl = (cnh_iohook_ioctl_t) cnh_lib_get_func_addr("ioctl");
pthread_mutex_init(&_cnh_iohook_lock, NULL);
atomic_store(&_cnh_iohook_initted, 1);
atomic_store(&_cnh_iohook_init_in_progress, 0);
}
static enum cnh_result _cnh_iohook_invoke_real(struct cnh_iohook_irp *irp)
{
cnh_iohook_fn_t handler;
cnh_iohook_fn_t handler;
assert(irp != NULL);
assert(irp->op < _countof(_cnh_iohook_real_handlers));
assert(irp != NULL);
assert(irp->op < _countof(_cnh_iohook_real_handlers));
handler = _cnh_iohook_real_handlers[irp->op];
handler = _cnh_iohook_real_handlers[irp->op];
assert(handler != NULL);
assert(handler != NULL);
return handler(irp);
return handler(irp);
}
static enum cnh_result _cnh_iohook_invoke_real_open(struct cnh_iohook_irp *irp)
{
int fd;
int fd;
assert(irp != NULL);
assert(irp != NULL);
fd = _cnh_iohook_real_open(irp->open_filename, irp->open_flags);
fd = _cnh_iohook_real_open(irp->open_filename, irp->open_flags);
if (fd == INVALID_FILE_DEVICE) {
return cnh_errno_to_result(errno);
}
if (fd == INVALID_FILE_DEVICE) {
return cnh_errno_to_result(errno);
}
irp->fd = fd;
irp->fd = fd;
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
static enum cnh_result _cnh_iohook_invoke_real_fdopen(struct cnh_iohook_irp *irp)
static enum cnh_result
_cnh_iohook_invoke_real_fdopen(struct cnh_iohook_irp *irp)
{
FILE* file;
FILE *file;
assert(irp != NULL);
assert(irp != NULL);
file = _cnh_iohook_real_fdopen(irp->fdopen_fd, irp->fdopen_mode);
file = _cnh_iohook_real_fdopen(irp->fdopen_fd, irp->fdopen_mode);
if (file == NULL) {
return cnh_errno_to_result(errno);
}
if (file == NULL) {
return cnh_errno_to_result(errno);
}
irp->fdopen_res = file;
irp->fdopen_res = file;
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
static enum cnh_result _cnh_iohook_invoke_real_close(struct cnh_iohook_irp *irp)
{
int ok;
int ok;
assert(irp != NULL);
assert(irp != NULL);
ok = _cnh_iohook_real_close(irp->fd);
ok = _cnh_iohook_real_close(irp->fd);
if (ok < 0) {
return cnh_errno_to_result(errno);
}
if (ok < 0) {
return cnh_errno_to_result(errno);
}
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
static enum cnh_result _cnh_iohook_invoke_real_read(struct cnh_iohook_irp *irp)
{
ssize_t read;
ssize_t read;
assert(irp != NULL);
assert(irp != NULL);
read = _cnh_iohook_real_read(irp->fd, &irp->read.bytes[irp->read.pos], irp->read.nbytes - irp->read.pos);
read = _cnh_iohook_real_read(
irp->fd,
&irp->read.bytes[irp->read.pos],
irp->read.nbytes - irp->read.pos);
if (read < 0) {
return cnh_errno_to_result(errno);
}
if (read < 0) {
return cnh_errno_to_result(errno);
}
irp->read.pos += read;
irp->read.pos += read;
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
static enum cnh_result _cnh_iohook_invoke_real_write(struct cnh_iohook_irp *irp)
{
ssize_t written;
ssize_t written;
assert(irp != NULL);
assert(irp != NULL);
written = _cnh_iohook_real_write(irp->fd, &irp->write.bytes[irp->write.pos], irp->write.nbytes - irp->write.pos);
written = _cnh_iohook_real_write(
irp->fd,
&irp->write.bytes[irp->write.pos],
irp->write.nbytes - irp->write.pos);
if (written < 0) {
return cnh_errno_to_result(errno);
}
if (written < 0) {
return cnh_errno_to_result(errno);
}
irp->write.pos += written;
irp->write.pos += written;
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
static enum cnh_result _cnh_iohook_invoke_real_seek(struct cnh_iohook_irp *irp)
{
off_t result;
off_t result;
assert(irp != NULL);
assert(irp != NULL);
result = _cnh_iohook_real_lseek(irp->fd, (off_t) irp->seek_offset, irp->seek_origin);
result = _cnh_iohook_real_lseek(
irp->fd, (off_t) irp->seek_offset, irp->seek_origin);
if (result < 0) {
return cnh_errno_to_result(errno);
}
if (result < 0) {
return cnh_errno_to_result(errno);
}
irp->seek_pos = result;
irp->seek_pos = result;
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
static enum cnh_result _cnh_iohook_invoke_real_ioctl(struct cnh_iohook_irp *irp)
{
int result;
int result;
assert(irp != NULL);
assert(irp != NULL);
result = _cnh_iohook_real_ioctl(irp->fd, irp->ioctl_req, irp->ioctl.bytes);
result = _cnh_iohook_real_ioctl(irp->fd, irp->ioctl_req, irp->ioctl.bytes);
if (result < 0) {
return cnh_errno_to_result(errno);
}
if (result < 0) {
return cnh_errno_to_result(errno);
}
irp->ioctl.pos = (size_t) result;
irp->ioctl.pos = (size_t) result;
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
+25 -24
View File
@@ -17,34 +17,34 @@
* Available operations to hook
*/
enum cnh_iohook_irp_op {
CNH_IOHOOK_IRP_OP_OPEN = 0,
CNH_IOHOOK_IRP_OP_FDOPEN = 1,
CNH_IOHOOK_IRP_OP_CLOSE = 2,
CNH_IOHOOK_IRP_OP_READ = 3,
CNH_IOHOOK_IRP_OP_WRITE = 4,
CNH_IOHOOK_IRP_OP_SEEK = 5,
CNH_IOHOOK_IRP_OP_IOCTL = 6,
CNH_IOHOOK_IRP_OP_OPEN = 0,
CNH_IOHOOK_IRP_OP_FDOPEN = 1,
CNH_IOHOOK_IRP_OP_CLOSE = 2,
CNH_IOHOOK_IRP_OP_READ = 3,
CNH_IOHOOK_IRP_OP_WRITE = 4,
CNH_IOHOOK_IRP_OP_SEEK = 5,
CNH_IOHOOK_IRP_OP_IOCTL = 6,
};
/**
* I/O request packet
*/
struct cnh_iohook_irp {
enum cnh_iohook_irp_op op;
size_t next_handler;
int fd;
const char *open_filename;
int open_flags;
int fdopen_fd;
const char* fdopen_mode;
FILE* fdopen_res;
struct cnh_iobuf read;
struct cnh_const_iobuf write;
int seek_origin;
int64_t seek_offset;
uint64_t seek_pos;
int ioctl_req;
struct cnh_iobuf ioctl;
enum cnh_iohook_irp_op op;
size_t next_handler;
int fd;
const char *open_filename;
int open_flags;
int fdopen_fd;
const char *fdopen_mode;
FILE *fdopen_res;
struct cnh_iobuf read;
struct cnh_const_iobuf write;
int seek_origin;
int64_t seek_offset;
uint64_t seek_pos;
int ioctl_req;
struct cnh_iobuf ioctl;
};
/**
@@ -80,8 +80,9 @@ enum cnh_result cnh_iohook_invoke_next(struct cnh_iohook_irp *irp);
int cnh_iohook_open_dummy_fd();
/**
* Close a dummy file handle. Make sure to free your previously allocated handles
* to avoid resource leaks. Do not free them using the real close function.
* Close a dummy file handle. Make sure to free your previously allocated
* handles to avoid resource leaks. Do not free them using the real close
* function.
*
* @param file Dummy file handle to free
*/
+64 -39
View File
@@ -6,52 +6,77 @@
#define CNH_LIB_MAIN_H
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include "util/log.h"
#define LIB_MAIN_CONSTRUCTOR(func) __attribute__((constructor)) void lib_constructor() { func(); }
#define LIB_MAIN_CONSTRUCTOR(func) \
__attribute__((constructor)) void lib_constructor() \
{ \
func(); \
}
#define LIB_MAIN_DESTRUCTOR(func) __attribute__((destructor)) void lib_destructor() { func(); }
#define LIB_MAIN_DESTRUCTOR(func) \
__attribute__((destructor)) void lib_destructor() \
{ \
func(); \
}
#define LIB_MAIN_TRAP_MAIN(func_before_main, func_after_main) \
typedef int (*func_libc_start_main_t)(int *(main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end)); \
typedef int* (*func_main_t)(int, char**, char**); \
typedef void (*func_init_t)(void); \
static func_main_t orig_main; \
static func_init_t orig_init; \
static bool trapped; \
\
int* trap_main(int argc, char** argv, char** envp) \
{ \
log_debug("Trap before main (%s): argc %d", argv[0], argc); \
func_before_main(argc, argv); \
log_debug("Calling orig_init"); \
orig_init(); \
log_debug("Calling real main (%s): argc %d", argv[0], argc); \
int* ret = orig_main(argc, argv, envp); \
log_debug("Calling cleanup after main (%s): ret %d", argv[0], ret); \
func_after_main(); \
return ret; \
} \
\
void dummy_init(void) {} \
\
int __libc_start_main(int *(main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end)) \
{ \
func_libc_start_main_t start = (func_libc_start_main_t) dlsym(RTLD_NEXT, "__libc_start_main"); \
if (start == NULL) { \
printf("ERROR finding orig func __libc_start_main\n"); \
} \
orig_main = main; \
main = trap_main; \
orig_init = init; \
init = dummy_init; \
trapped = true; \
return (*start)(main, argc, ubp_av, init, fini, rtld_fini, stack_end); \
}
#define LIB_MAIN_TRAP_MAIN(func_before_main, func_after_main) \
typedef int (*func_libc_start_main_t)( \
int *(main)(int, char **, char **), \
int argc, \
char **ubp_av, \
void (*init)(void), \
void (*fini)(void), \
void (*rtld_fini)(void), \
void(*stack_end)); \
typedef int *(*func_main_t)(int, char **, char **); \
typedef void (*func_init_t)(void); \
static func_main_t orig_main; \
static func_init_t orig_init; \
static bool trapped; \
\
int *trap_main(int argc, char **argv, char **envp) \
{ \
log_debug("Trap before main (%s): argc %d", argv[0], argc); \
func_before_main(argc, argv); \
log_debug("Calling orig_init"); \
orig_init(); \
log_debug("Calling real main (%s): argc %d", argv[0], argc); \
int *ret = orig_main(argc, argv, envp); \
log_debug("Calling cleanup after main (%s): ret %d", argv[0], ret); \
func_after_main(); \
return ret; \
} \
\
void dummy_init(void) \
{ \
} \
\
int __libc_start_main( \
int *(main)(int, char **, char **), \
int argc, \
char **ubp_av, \
void (*init)(void), \
void (*fini)(void), \
void (*rtld_fini)(void), \
void(*stack_end)) \
{ \
func_libc_start_main_t start = \
(func_libc_start_main_t) dlsym(RTLD_NEXT, "__libc_start_main"); \
if (start == NULL) { \
printf("ERROR finding orig func __libc_start_main\n"); \
} \
orig_main = main; \
main = trap_main; \
orig_init = init; \
init = dummy_init; \
trapped = true; \
return (*start)(main, argc, ubp_av, init, fini, rtld_fini, stack_end); \
}
#endif
+125 -118
View File
@@ -8,172 +8,179 @@
#include "util/mem.h"
#include "util/rand.h"
typedef void* (*cnh_lib_load_t)(const char* lib);
typedef void* (*cnh_lib_get_func_addr_handle_t)(void* lib_handle, const char* func_name);
typedef void (*cnh_lib_unload_t)(void* handle);
typedef void* (*cnh_lib_get_func_addr_t)(const char* func_name);
typedef void *(*cnh_lib_load_t)(const char *lib);
typedef void *(*cnh_lib_get_func_addr_handle_t)(
void *lib_handle, const char *func_name);
typedef void (*cnh_lib_unload_t)(void *handle);
typedef void *(*cnh_lib_get_func_addr_t)(const char *func_name);
static void* _cnh_lib_load(const char* lib);
static void* _cnh_lib_get_func_addr_handle(void* lib_handle, const char* func_name);
static void _cnh_lib_unload(void* handle);
static void* _cnh_lib_get_func_addr(const char* func_name);
static void *_cnh_lib_load(const char *lib);
static void *
_cnh_lib_get_func_addr_handle(void *lib_handle, const char *func_name);
static void _cnh_lib_unload(void *handle);
static void *_cnh_lib_get_func_addr(const char *func_name);
static void* _cnh_lib_load_test(const char* lib);
static void* _cnh_lib_get_func_addr_handle_test(void* lib_handle, const char* func_name);
static void _cnh_lib_unload_test(void* handle);
static void* _cnh_lib_get_func_addr_test(const char* func_name);
static void *_cnh_lib_load_test(const char *lib);
static void *
_cnh_lib_get_func_addr_handle_test(void *lib_handle, const char *func_name);
static void _cnh_lib_unload_test(void *handle);
static void *_cnh_lib_get_func_addr_test(const char *func_name);
struct cnh_lib_interface {
cnh_lib_load_t load;
cnh_lib_get_func_addr_handle_t get_func_addr_handle;
cnh_lib_unload_t unload;
cnh_lib_get_func_addr_t get_func_addr;
cnh_lib_load_t load;
cnh_lib_get_func_addr_handle_t get_func_addr_handle;
cnh_lib_unload_t unload;
cnh_lib_get_func_addr_t get_func_addr;
};
static struct cnh_lib_interface _cnh_lib_interface = {
.load = _cnh_lib_load,
.get_func_addr_handle = _cnh_lib_get_func_addr_handle,
.unload = _cnh_lib_unload,
.get_func_addr = _cnh_lib_get_func_addr,
.load = _cnh_lib_load,
.get_func_addr_handle = _cnh_lib_get_func_addr_handle,
.unload = _cnh_lib_unload,
.get_func_addr = _cnh_lib_get_func_addr,
};
static struct cnh_lib_unit_test_func_mocks* _cnh_lib_func_mocks;
static struct cnh_lib_unit_test_func_mocks *_cnh_lib_func_mocks;
size_t _cnh_lib_func_mocks_cnt;
static void* _cnh_lib_load(const char* lib)
static void *_cnh_lib_load(const char *lib)
{
void* so = dlopen(lib, RTLD_NOW);
void *so = dlopen(lib, RTLD_NOW);
if (so == NULL) {
log_warn("Failed to open library %s: %s", lib, dlerror());
} else {
log_debug("Opened lib %s, handle %p", lib, so);
}
if (so == NULL) {
log_warn("Failed to open library %s: %s", lib, dlerror());
} else {
log_debug("Opened lib %s, handle %p", lib, so);
}
return so;
return so;
}
static void* _cnh_lib_get_func_addr_handle(void* lib_handle, const char* func_name)
static void *
_cnh_lib_get_func_addr_handle(void *lib_handle, const char *func_name)
{
void* ret = dlsym(lib_handle, func_name);
void *ret = dlsym(lib_handle, func_name);
if (ret == NULL) {
log_warn("Could not find func %s in library %p", func_name, lib_handle);
if (ret == NULL) {
log_warn("Could not find func %s in library %p", func_name, lib_handle);
}
return ret;
}
static void _cnh_lib_unload(void *handle)
{
dlclose(handle);
log_debug("Closed lib handle %p", handle);
}
static void *_cnh_lib_get_func_addr(const char *func_name)
{
void *ret = dlsym(RTLD_NEXT, func_name);
if (ret == NULL) {
log_warn("Could not find func %s", func_name);
}
return ret;
}
static void *_cnh_lib_load_test(const char *lib)
{
log_warn("Loading lib %s not supported in test", lib);
if (sizeof(void *) == 4) {
return (void *) util_rand_gen_32();
} else {
log_die_illegal_state();
}
}
static void *
_cnh_lib_get_func_addr_handle_test(void *lib_handle, const char *func_name)
{
return _cnh_lib_get_func_addr_test(func_name);
}
static void _cnh_lib_unload_test(void *handle)
{
log_warn("Unloading lib %p not supported in test", handle);
}
static void *_cnh_lib_get_func_addr_test(const char *func_name)
{
for (size_t i = 0; i < _cnh_lib_func_mocks_cnt; i++) {
if (!strcmp(_cnh_lib_func_mocks[i].name, func_name)) {
return _cnh_lib_func_mocks->func;
}
}
return ret;
log_warn("Could not find func %s", func_name);
return NULL;
}
static void _cnh_lib_unload(void* handle)
struct cnh_lib_unit_test_func_mocks *cnh_lib_allocate_func_mocks(size_t count)
{
dlclose(handle);
log_debug("Closed lib handle %p", handle);
log_assert(count >= 0);
struct cnh_lib_unit_test_func_mocks *func_mocks;
func_mocks =
util_xmalloc(sizeof(struct cnh_lib_unit_test_func_mocks) * count);
memset(func_mocks, 0, sizeof(struct cnh_lib_unit_test_func_mocks) * count);
return func_mocks;
}
static void* _cnh_lib_get_func_addr(const char* func_name)
void cnh_lib_init_unit_test(
struct cnh_lib_unit_test_func_mocks *func_mocks, size_t func_mocks_cnt)
{
void* ret = dlsym(RTLD_NEXT, func_name);
log_warn("Setting up %d unit test func mocks", func_mocks_cnt);
if (ret == NULL) {
log_warn("Could not find func %s", func_name);
}
_cnh_lib_func_mocks = func_mocks;
_cnh_lib_func_mocks_cnt = func_mocks_cnt;
return ret;
}
static void* _cnh_lib_load_test(const char* lib)
{
log_warn("Loading lib %s not supported in test", lib);
if (sizeof(void*) == 4) {
return (void*) util_rand_gen_32();
} else {
log_die_illegal_state();
}
}
static void* _cnh_lib_get_func_addr_handle_test(void* lib_handle, const char* func_name)
{
return _cnh_lib_get_func_addr_test(func_name);
}
static void _cnh_lib_unload_test(void* handle)
{
log_warn("Unloading lib %p not supported in test", handle);
}
static void* _cnh_lib_get_func_addr_test(const char* func_name)
{
for (size_t i = 0; i < _cnh_lib_func_mocks_cnt; i++) {
if (!strcmp(_cnh_lib_func_mocks[i].name, func_name)) {
return _cnh_lib_func_mocks->func;
}
}
log_warn("Could not find func %s", func_name);
return NULL;
}
struct cnh_lib_unit_test_func_mocks* cnh_lib_allocate_func_mocks(size_t count)
{
log_assert(count >= 0);
struct cnh_lib_unit_test_func_mocks* func_mocks;
func_mocks = util_xmalloc(sizeof(struct cnh_lib_unit_test_func_mocks) * count);
memset(func_mocks, 0, sizeof(struct cnh_lib_unit_test_func_mocks) * count);
return func_mocks;
}
void cnh_lib_init_unit_test(struct cnh_lib_unit_test_func_mocks* func_mocks, size_t func_mocks_cnt)
{
log_warn("Setting up %d unit test func mocks", func_mocks_cnt);
_cnh_lib_func_mocks = func_mocks;
_cnh_lib_func_mocks_cnt = func_mocks_cnt;
_cnh_lib_interface.load = _cnh_lib_load_test;
_cnh_lib_interface.get_func_addr_handle = _cnh_lib_get_func_addr_handle_test;
_cnh_lib_interface.unload = _cnh_lib_unload_test;
_cnh_lib_interface.get_func_addr = _cnh_lib_get_func_addr_test;
_cnh_lib_interface.load = _cnh_lib_load_test;
_cnh_lib_interface.get_func_addr_handle = _cnh_lib_get_func_addr_handle_test;
_cnh_lib_interface.unload = _cnh_lib_unload_test;
_cnh_lib_interface.get_func_addr = _cnh_lib_get_func_addr_test;
}
void cnh_lib_init()
{
log_warn("Setting up real interface");
log_warn("Setting up real interface");
_cnh_lib_interface.load = _cnh_lib_load;
_cnh_lib_interface.get_func_addr_handle = _cnh_lib_get_func_addr_handle;
_cnh_lib_interface.unload = _cnh_lib_unload;
_cnh_lib_interface.get_func_addr = _cnh_lib_get_func_addr;
_cnh_lib_interface.load = _cnh_lib_load;
_cnh_lib_interface.get_func_addr_handle = _cnh_lib_get_func_addr_handle;
_cnh_lib_interface.unload = _cnh_lib_unload;
_cnh_lib_interface.get_func_addr = _cnh_lib_get_func_addr;
}
void cnh_lib_shutdown_unit_test()
{
log_assert(_cnh_lib_func_mocks);
log_assert(_cnh_lib_func_mocks);
util_xfree((void**) &_cnh_lib_func_mocks);
util_xfree((void **) &_cnh_lib_func_mocks);
}
void* cnh_lib_load(const char* lib)
void *cnh_lib_load(const char *lib)
{
return _cnh_lib_interface.load(lib);
return _cnh_lib_interface.load(lib);
}
void* cnh_lib_get_func_addr_handle(void* lib_handle, const char* func_name)
void *cnh_lib_get_func_addr_handle(void *lib_handle, const char *func_name)
{
return _cnh_lib_interface.get_func_addr_handle(lib_handle, func_name);
return _cnh_lib_interface.get_func_addr_handle(lib_handle, func_name);
}
void cnh_lib_unload(void* handle)
void cnh_lib_unload(void *handle)
{
_cnh_lib_interface.unload(handle);
_cnh_lib_interface.unload(handle);
}
void* cnh_lib_get_func_addr(const char* func_name)
void *cnh_lib_get_func_addr(const char *func_name)
{
return _cnh_lib_interface.get_func_addr(func_name);
return _cnh_lib_interface.get_func_addr(func_name);
}
+26 -19
View File
@@ -7,38 +7,45 @@
#include <stdlib.h>
/**
* Provide a mock function key'd by it's name and pointing to your actual mock implementation.
* Provide a mock function key'd by it's name and pointing to your actual mock
* implementation.
*/
struct cnh_lib_unit_test_func_mocks {
const char* name;
void* func;
const char *name;
void *func;
};
/**
* Allocate memory for a list of mock functions to pass to cnh_lib_init_unit_test.
* Allocate memory for a list of mock functions to pass to
* cnh_lib_init_unit_test.
*
* @param count The size of the list.
* @return Allocated memory with the specified number of entries.
*/
struct cnh_lib_unit_test_func_mocks* cnh_lib_allocate_func_mocks(size_t count);
struct cnh_lib_unit_test_func_mocks *cnh_lib_allocate_func_mocks(size_t count);
/**
* Initialize this module when using it in a unit-test. This allows you to add function mocks that are returned on the
* various calls to get function pointers from real library functions. Use this to mock them to test various patching
* modules.
* Initialize this module when using it in a unit-test. This allows you to add
* function mocks that are returned on the various calls to get function
* pointers from real library functions. Use this to mock them to test various
* patching modules.
*
* Use the cnh_lib_allocate_func_mocks function to allocate a list that you can fill in.
* Use the cnh_lib_allocate_func_mocks function to allocate a list that you can
* fill in.
*
* @param func_mocks A list of functions mocks with function names and pointers to the test mocks you set up. Ensure
* that the function signatures match, otherwise things might crash when getting called. The module
* will cleanup the memory allocated of this for you.
* @param func_mocks A list of functions mocks with function names and pointers
* to the test mocks you set up. Ensure that the function signatures match,
* otherwise things might crash when getting called. The module will cleanup the
* memory allocated of this for you.
* @param func_mocks_cnt The length of the list of func_mocks.
*/
void cnh_lib_init_unit_test(struct cnh_lib_unit_test_func_mocks* func_mocks, size_t func_mocks_cnt);
void cnh_lib_init_unit_test(
struct cnh_lib_unit_test_func_mocks *func_mocks, size_t func_mocks_cnt);
/**
* Optional, used for unit testing. Switch to the default backend that utilizes loading real libraries and getting real
* function pointers from them. This is enabled by default.
* Optional, used for unit testing. Switch to the default backend that utilizes
* loading real libraries and getting real function pointers from them. This is
* enabled by default.
*/
void cnh_lib_init();
@@ -53,7 +60,7 @@ void cnh_lib_shutdown_unit_test();
* @param lib Path to library file to load
* @return Pointer to a handle on success, NULL on failure
*/
void* cnh_lib_load(const char* lib);
void *cnh_lib_load(const char *lib);
/**
* Get the address of a function from a library
@@ -62,14 +69,14 @@ void* cnh_lib_load(const char* lib);
* @param func_name Name of the function to get
* @return Function ptr on success, false on error (function not found)
*/
void*cnh_lib_get_func_addr_handle(void* lib_handle, const char* func_name);
void *cnh_lib_get_func_addr_handle(void *lib_handle, const char *func_name);
/**
* Unload a loaded dynamic library
*
* @param handle Handle of the loaded lib to unload
*/
void cnh_lib_unload(void* handle);
void cnh_lib_unload(void *handle);
/**
* Get the adress of a function (from a dynamic library)
@@ -79,6 +86,6 @@ void cnh_lib_unload(void* handle);
* @param func_name Name of the function
* @return Valid ptr to function on success, false on error (not found)
*/
void* cnh_lib_get_func_addr(const char* func_name);
void *cnh_lib_get_func_addr(const char *func_name);
#endif
+92 -88
View File
@@ -8,96 +8,100 @@
int cnh_result_to_errno(enum cnh_result result)
{
switch (result) {
case CNH_RESULT_SUCCESS:
return 0;
case CNH_RESULT_ERROR_INSUFFICIENT_BUFFER:
return EIO;
case CNH_RESULT_INVALID_PARAMETER:
return EINVAL;
case CNH_RESULT_OUT_OF_MEMORY:
return ENOMEM;
case CNH_RESULT_REPEAT_OPERATION:
return EAGAIN;
case CNH_RESULT_NO_SUCH_FILE_OR_DIR:
return ENOENT;
case CNH_RESULT_NOT_TTY:
return ENOTTY;
case CNH_RESULT_BUSY:
return EBUSY;
case CNH_RESULT_IS_A_DIRECTORY:
return EISDIR;
case CNH_RESULT_PERMISSION_DENIED:
return EACCES;
case CNH_RESULT_DIRECTORY_NOT_EMPTY:
return ENOTEMPTY;
case CNH_RESULT_OPERATION_NOT_PERMITTED:
return EPERM;
case CNH_RESULT_NO_SUCH_DEVICE:
return ENODEV;
case CNH_RESULT_BAD_FILE_NUMBER:
return EBADF;
case CNH_RESULT_FILE_DESCRIPTOR_IN_BAD_STATE:
return EBADFD;
case CNH_RESULT_VALUE_TOO_LARGE_FOR_DEFINED_DATATYPE:
return EOVERFLOW;
case CNH_RESULT_NO_SUCH_DEVICE_OR_ADDRESS:
return ENXIO;
case CNH_RESULT_BROKEN_PIPE:
return EPIPE;
case CNH_RESULT_TIMER_EXPIRED:
return ETIME;
case CNH_RESULT_NO_DATA_AVAILABLE:
return ENODATA;
default:
log_warn("Unhandled other error %d to errno convert might cause bugs", result);
return EIO;
}
switch (result) {
case CNH_RESULT_SUCCESS:
return 0;
case CNH_RESULT_ERROR_INSUFFICIENT_BUFFER:
return EIO;
case CNH_RESULT_INVALID_PARAMETER:
return EINVAL;
case CNH_RESULT_OUT_OF_MEMORY:
return ENOMEM;
case CNH_RESULT_REPEAT_OPERATION:
return EAGAIN;
case CNH_RESULT_NO_SUCH_FILE_OR_DIR:
return ENOENT;
case CNH_RESULT_NOT_TTY:
return ENOTTY;
case CNH_RESULT_BUSY:
return EBUSY;
case CNH_RESULT_IS_A_DIRECTORY:
return EISDIR;
case CNH_RESULT_PERMISSION_DENIED:
return EACCES;
case CNH_RESULT_DIRECTORY_NOT_EMPTY:
return ENOTEMPTY;
case CNH_RESULT_OPERATION_NOT_PERMITTED:
return EPERM;
case CNH_RESULT_NO_SUCH_DEVICE:
return ENODEV;
case CNH_RESULT_BAD_FILE_NUMBER:
return EBADF;
case CNH_RESULT_FILE_DESCRIPTOR_IN_BAD_STATE:
return EBADFD;
case CNH_RESULT_VALUE_TOO_LARGE_FOR_DEFINED_DATATYPE:
return EOVERFLOW;
case CNH_RESULT_NO_SUCH_DEVICE_OR_ADDRESS:
return ENXIO;
case CNH_RESULT_BROKEN_PIPE:
return EPIPE;
case CNH_RESULT_TIMER_EXPIRED:
return ETIME;
case CNH_RESULT_NO_DATA_AVAILABLE:
return ENODATA;
default:
log_warn(
"Unhandled other error %d to errno convert might cause bugs", result);
return EIO;
}
}
enum cnh_result cnh_errno_to_result(int errn)
{
switch (errn) {
case 0:
return CNH_RESULT_SUCCESS;
case EINVAL:
return CNH_RESULT_INVALID_PARAMETER;
case ENOMEM:
return CNH_RESULT_OUT_OF_MEMORY;
case EAGAIN:
return CNH_RESULT_REPEAT_OPERATION;
case ENOENT:
return CNH_RESULT_NO_SUCH_FILE_OR_DIR;
case ENOTTY:
return CNH_RESULT_NOT_TTY;
case EBUSY:
return CNH_RESULT_BUSY;
case EISDIR:
return CNH_RESULT_IS_A_DIRECTORY;
case EACCES:
return CNH_RESULT_PERMISSION_DENIED;
case ENOTEMPTY:
return CNH_RESULT_DIRECTORY_NOT_EMPTY;
case EPERM:
return CNH_RESULT_OPERATION_NOT_PERMITTED;
case ENODEV:
return CNH_RESULT_NO_SUCH_DEVICE;
case EBADF:
return CNH_RESULT_BAD_FILE_NUMBER;
case EBADFD:
return CNH_RESULT_FILE_DESCRIPTOR_IN_BAD_STATE;
case EOVERFLOW:
return CNH_RESULT_VALUE_TOO_LARGE_FOR_DEFINED_DATATYPE;
case ENXIO:
return CNH_RESULT_NO_SUCH_DEVICE_OR_ADDRESS;
case EPIPE:
return CNH_RESULT_BROKEN_PIPE;
case ETIME:
return CNH_RESULT_TIMER_EXPIRED;
case ENODATA:
return CNH_RESULT_NO_DATA_AVAILABLE;
default:
log_warn("Unhandled errno to general error convert might cause bugs, errno: %d", errn);
return CNH_RESULT_OTHER_ERROR;
}
switch (errn) {
case 0:
return CNH_RESULT_SUCCESS;
case EINVAL:
return CNH_RESULT_INVALID_PARAMETER;
case ENOMEM:
return CNH_RESULT_OUT_OF_MEMORY;
case EAGAIN:
return CNH_RESULT_REPEAT_OPERATION;
case ENOENT:
return CNH_RESULT_NO_SUCH_FILE_OR_DIR;
case ENOTTY:
return CNH_RESULT_NOT_TTY;
case EBUSY:
return CNH_RESULT_BUSY;
case EISDIR:
return CNH_RESULT_IS_A_DIRECTORY;
case EACCES:
return CNH_RESULT_PERMISSION_DENIED;
case ENOTEMPTY:
return CNH_RESULT_DIRECTORY_NOT_EMPTY;
case EPERM:
return CNH_RESULT_OPERATION_NOT_PERMITTED;
case ENODEV:
return CNH_RESULT_NO_SUCH_DEVICE;
case EBADF:
return CNH_RESULT_BAD_FILE_NUMBER;
case EBADFD:
return CNH_RESULT_FILE_DESCRIPTOR_IN_BAD_STATE;
case EOVERFLOW:
return CNH_RESULT_VALUE_TOO_LARGE_FOR_DEFINED_DATATYPE;
case ENXIO:
return CNH_RESULT_NO_SUCH_DEVICE_OR_ADDRESS;
case EPIPE:
return CNH_RESULT_BROKEN_PIPE;
case ETIME:
return CNH_RESULT_TIMER_EXPIRED;
case ENODATA:
return CNH_RESULT_NO_DATA_AVAILABLE;
default:
log_warn(
"Unhandled errno to general error convert might cause bugs, errno: "
"%d",
errn);
return CNH_RESULT_OTHER_ERROR;
}
}
+23 -22
View File
@@ -1,5 +1,6 @@
/**
* Results for returning errors on hook modules, converting them to errno and vice versa
* Results for returning errors on hook modules, converting them to errno and
* vice versa
*
* Based on original capnhook code for windows by decafcode:
* https://github.com/decafcode/capnhook
@@ -11,27 +12,27 @@
* Result values for hook functions
*/
enum cnh_result {
CNH_RESULT_SUCCESS = 0,
CNH_RESULT_ERROR_INSUFFICIENT_BUFFER = 1,
CNH_RESULT_INVALID_PARAMETER = 2,
CNH_RESULT_OUT_OF_MEMORY = 3,
CNH_RESULT_REPEAT_OPERATION = 4,
CNH_RESULT_NO_SUCH_FILE_OR_DIR = 5,
CNH_RESULT_OTHER_ERROR = 6,
CNH_RESULT_NOT_TTY = 7,
CNH_RESULT_BUSY = 8,
CNH_RESULT_IS_A_DIRECTORY = 9,
CNH_RESULT_PERMISSION_DENIED = 10,
CNH_RESULT_DIRECTORY_NOT_EMPTY = 11,
CNH_RESULT_OPERATION_NOT_PERMITTED = 12,
CNH_RESULT_NO_SUCH_DEVICE = 13,
CNH_RESULT_BAD_FILE_NUMBER = 14,
CNH_RESULT_FILE_DESCRIPTOR_IN_BAD_STATE = 15,
CNH_RESULT_VALUE_TOO_LARGE_FOR_DEFINED_DATATYPE = 16,
CNH_RESULT_NO_SUCH_DEVICE_OR_ADDRESS = 17,
CNH_RESULT_BROKEN_PIPE = 18,
CNH_RESULT_TIMER_EXPIRED = 19,
CNH_RESULT_NO_DATA_AVAILABLE = 20,
CNH_RESULT_SUCCESS = 0,
CNH_RESULT_ERROR_INSUFFICIENT_BUFFER = 1,
CNH_RESULT_INVALID_PARAMETER = 2,
CNH_RESULT_OUT_OF_MEMORY = 3,
CNH_RESULT_REPEAT_OPERATION = 4,
CNH_RESULT_NO_SUCH_FILE_OR_DIR = 5,
CNH_RESULT_OTHER_ERROR = 6,
CNH_RESULT_NOT_TTY = 7,
CNH_RESULT_BUSY = 8,
CNH_RESULT_IS_A_DIRECTORY = 9,
CNH_RESULT_PERMISSION_DENIED = 10,
CNH_RESULT_DIRECTORY_NOT_EMPTY = 11,
CNH_RESULT_OPERATION_NOT_PERMITTED = 12,
CNH_RESULT_NO_SUCH_DEVICE = 13,
CNH_RESULT_BAD_FILE_NUMBER = 14,
CNH_RESULT_FILE_DESCRIPTOR_IN_BAD_STATE = 15,
CNH_RESULT_VALUE_TOO_LARGE_FOR_DEFINED_DATATYPE = 16,
CNH_RESULT_NO_SUCH_DEVICE_OR_ADDRESS = 17,
CNH_RESULT_BROKEN_PIPE = 18,
CNH_RESULT_TIMER_EXPIRED = 19,
CNH_RESULT_NO_DATA_AVAILABLE = 20,
};
/**
+32 -26
View File
@@ -1,11 +1,12 @@
#define LOG_MODULE "cnh-sig"
#include "capnhook/hook/lib.h"
#include "capnhook/hook/sig.h"
#include "capnhook/hook/lib.h"
#include "util/log.h"
typedef int (*cnh_sig_handler_sigaction_t) (int sig, const struct sigaction* act, struct sigaction* oact);
typedef int (*cnh_sig_handler_sigaction_t)(
int sig, const struct sigaction *act, struct sigaction *oact);
static void _cnh_signal_handler(int sig);
@@ -16,43 +17,48 @@ static __sighandler_t _cnh_signal_orig_handlers[32];
void cnh_sig_install(int sig, cnh_sig_handler_t handler)
{
if (sig < 0 || sig >= 32) {
log_die("Can't register handler for invalid signal number %d", sig);
}
if (sig < 0 || sig >= 32) {
log_die("Can't register handler for invalid signal number %d", sig);
}
/* Ensure that the application does not install it's own handler */
_cnh_signal_handlers[sig] = handler;
/* Ensure that the application does not install it's own handler */
_cnh_signal_handlers[sig] = handler;
/* Install a little detour as our signal handler */
signal(sig, _cnh_signal_handler);
/* Install a little detour as our signal handler */
signal(sig, _cnh_signal_handler);
log_info("Installed signal handler %p for %d", handler, sig);
log_info("Installed signal handler %p for %d", handler, sig);
}
int sigaction(int sig, const struct sigaction* act, struct sigaction* oact)
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
{
if (_cnh_signal_handlers[sig]) {
log_info("Enforce own signal handler on signal: %d", sig);
if (_cnh_signal_handlers[sig]) {
log_info("Enforce own signal handler on signal: %d", sig);
/* save the original handler, we might need it */
_cnh_signal_orig_handlers[sig] = ((struct sigaction*) act)->sa_handler;
/* save the original handler, we might need it */
_cnh_signal_orig_handlers[sig] = ((struct sigaction *) act)->sa_handler;
/* swap */
((struct sigaction*) act)->sa_handler = (__sighandler_t) _cnh_signal_handler;
/* swap */
((struct sigaction *) act)->sa_handler =
(__sighandler_t) _cnh_signal_handler;
log_debug("Original handler %p for signal %d", _cnh_signal_orig_handlers[sig], sig);
}
log_debug(
"Original handler %p for signal %d",
_cnh_signal_orig_handlers[sig],
sig);
}
if (!_cnh_sig_handler_real_sigaction) {
_cnh_sig_handler_real_sigaction = (cnh_sig_handler_sigaction_t) cnh_lib_get_func_addr("sigaction");
}
if (!_cnh_sig_handler_real_sigaction) {
_cnh_sig_handler_real_sigaction =
(cnh_sig_handler_sigaction_t) cnh_lib_get_func_addr("sigaction");
}
return _cnh_sig_handler_real_sigaction(sig, act, oact);
return _cnh_sig_handler_real_sigaction(sig, act, oact);
}
static void _cnh_signal_handler(int sig)
{
if (_cnh_signal_handlers[sig]) {
_cnh_signal_handlers[sig](sig, _cnh_signal_orig_handlers[sig]);
}
if (_cnh_signal_handlers[sig]) {
_cnh_signal_handlers[sig](sig, _cnh_signal_orig_handlers[sig]);
}
}
File diff suppressed because it is too large Load Diff
+27 -26
View File
@@ -15,37 +15,37 @@
* Available operations to hook
*/
enum cnh_usbhook_irp_op {
CNH_USBHOOK_IRP_OP_INIT = 0,
CNH_USBHOOK_IRP_OP_FIND_BUSSES = 1,
CNH_USBHOOK_IRP_OP_FIND_DEVICES = 2,
CNH_USBHOOK_IRP_OP_OPEN = 3,
CNH_USBHOOK_IRP_OP_CLOSE = 4,
CNH_USBHOOK_IRP_OP_RESET = 5,
CNH_USBHOOK_IRP_OP_SET_ALTINTERFACE = 6,
CNH_USBHOOK_IRP_OP_SET_CONFIGURATION = 7,
CNH_USBHOOK_IRP_OP_CLAIM_INTERFACE = 8,
CNH_USBHOOK_IRP_OP_CTRL_MSG = 9
CNH_USBHOOK_IRP_OP_INIT = 0,
CNH_USBHOOK_IRP_OP_FIND_BUSSES = 1,
CNH_USBHOOK_IRP_OP_FIND_DEVICES = 2,
CNH_USBHOOK_IRP_OP_OPEN = 3,
CNH_USBHOOK_IRP_OP_CLOSE = 4,
CNH_USBHOOK_IRP_OP_RESET = 5,
CNH_USBHOOK_IRP_OP_SET_ALTINTERFACE = 6,
CNH_USBHOOK_IRP_OP_SET_CONFIGURATION = 7,
CNH_USBHOOK_IRP_OP_CLAIM_INTERFACE = 8,
CNH_USBHOOK_IRP_OP_CTRL_MSG = 9
};
/**
* I/O request packet
*/
struct cnh_usbhook_irp {
enum cnh_usbhook_irp_op op;
size_t next_handler;
int find_busses_res_num_busses;
int find_devices_res_num_devices;
struct usb_device* open_usb_dev;
usb_dev_handle* handle;
int set_altinterface;
int set_configuration;
int claim_interface;
int ctrl_req_type;
int ctrl_req;
int ctrl_value;
int ctrl_index;
struct cnh_iobuf ctrl_buffer;
int ctrl_timeout;
enum cnh_usbhook_irp_op op;
size_t next_handler;
int find_busses_res_num_busses;
int find_devices_res_num_devices;
struct usb_device *open_usb_dev;
usb_dev_handle *handle;
int set_altinterface;
int set_configuration;
int claim_interface;
int ctrl_req_type;
int ctrl_req;
int ctrl_value;
int ctrl_index;
struct cnh_iobuf ctrl_buffer;
int ctrl_timeout;
};
/**
@@ -90,6 +90,7 @@ enum cnh_result cnh_usbhook_invoke_next(struct cnh_usbhook_irp *irp);
* @param irp I/O request package to dispatch
* @return Result of the following function dispatching the request package
*/
enum cnh_result cnh_usbhook_invoke_next_reset_advance(struct cnh_usbhook_irp *irp);
enum cnh_result
cnh_usbhook_invoke_next_reset_advance(struct cnh_usbhook_irp *irp);
#endif
+84 -42
View File
@@ -4,54 +4,96 @@
#include "util/log.h"
static const char* _cnh_filehook_mon_str_empty = "";
static const char* _cnh_filehook_mon_irp_op_str[] = {
"fopen",
"fclose",
"fread",
"fwrite",
"fgets",
"fseek",
"ftell",
"feof"
};
static const char *_cnh_filehook_mon_str_empty = "";
static const char *_cnh_filehook_mon_irp_op_str[] = {
"fopen", "fclose", "fread", "fwrite", "fgets", "fseek", "ftell", "feof"};
enum cnh_result cnh_filehook_mon(struct cnh_filehook_irp *irp)
{
enum cnh_result result;
enum cnh_result result;
/* Skip writes to log file because this results in infinite recursion */
if (irp->file == util_log_get_file_handle()) {
return cnh_filehook_invoke_next(irp);
}
/* Skip writes to log file because this results in infinite recursion */
if (irp->file == util_log_get_file_handle()) {
return cnh_filehook_invoke_next(irp);
}
log_debug("[before][%s] next_handler %d, file %p, open_filename %s, open_mode %s, read(bytes %p, nbytes %d, pos %d)"
", write(bytes %p, nbytes %d, pos %d), orig_read_write_size %d, orig_read_write_nmemb %d, seek_origin %d, "
"seek_offset %d, tell_offset %llu, eof %d", _cnh_filehook_mon_irp_op_str[irp->op], irp->next_handler,
irp->file, irp->open_filename ? irp->open_filename : _cnh_filehook_mon_str_empty,
irp->open_mode ? irp->open_mode : _cnh_filehook_mon_str_empty, irp->read.bytes, irp->read.nbytes,
irp->read.pos, irp->write.bytes, irp->write.nbytes, irp->write.pos, irp->orig_read_write_size,
irp->orig_read_write_nmemb, irp->seek_origin, irp->seek_offset, irp->tell_offset, irp->eof);
log_debug(
"[before][%s] next_handler %d, file %p, open_filename %s, open_mode %s, "
"read(bytes %p, nbytes %d, pos %d)"
", write(bytes %p, nbytes %d, pos %d), orig_read_write_size %d, "
"orig_read_write_nmemb %d, seek_origin %d, "
"seek_offset %d, tell_offset %llu, eof %d",
_cnh_filehook_mon_irp_op_str[irp->op],
irp->next_handler,
irp->file,
irp->open_filename ? irp->open_filename : _cnh_filehook_mon_str_empty,
irp->open_mode ? irp->open_mode : _cnh_filehook_mon_str_empty,
irp->read.bytes,
irp->read.nbytes,
irp->read.pos,
irp->write.bytes,
irp->write.nbytes,
irp->write.pos,
irp->orig_read_write_size,
irp->orig_read_write_nmemb,
irp->seek_origin,
irp->seek_offset,
irp->tell_offset,
irp->eof);
result = cnh_filehook_invoke_next(irp);
result = cnh_filehook_invoke_next(irp);
if (result != CNH_RESULT_SUCCESS) {
log_error("[after][%s] result %d, next_handler %d, file %p, open_filename %s, open_mode %s, read(bytes %p, "
"nbytes %d, pos %d), write(bytes %p, nbytes %d, pos %d), orig_read_write_size %d, orig_read_write_nmemb %d,"
" seek_origin %d, seek_offset %d, tell_offset %llu, eof %d", _cnh_filehook_mon_irp_op_str[irp->op],
result, irp->next_handler, irp->file, irp->open_filename ? irp->open_filename : _cnh_filehook_mon_str_empty,
irp->open_mode ? irp->open_mode : _cnh_filehook_mon_str_empty, irp->read.bytes, irp->read.nbytes,
irp->read.pos, irp->write.bytes, irp->write.nbytes, irp->write.pos, irp->orig_read_write_size,
irp->orig_read_write_nmemb, irp->seek_origin, irp->seek_offset, irp->tell_offset, irp->eof);
} else {
log_debug("[after][%s] result %d, next_handler %d, file %p, open_filename %s, open_mode %s, read(bytes %p, "
"nbytes %d, pos %d), write(bytes %p, nbytes %d, pos %d), orig_read_write_size %d, orig_read_write_nmemb %d,"
" seek_origin %d, seek_offset %d, tell_offset %llu, eof %d", _cnh_filehook_mon_irp_op_str[irp->op],
result, irp->next_handler, irp->file, irp->open_filename ? irp->open_filename : _cnh_filehook_mon_str_empty,
irp->open_mode ? irp->open_mode : _cnh_filehook_mon_str_empty, irp->read.bytes, irp->read.nbytes,
irp->read.pos, irp->write.bytes, irp->write.nbytes, irp->write.pos, irp->orig_read_write_size,
irp->orig_read_write_nmemb, irp->seek_origin, irp->seek_offset, irp->tell_offset, irp->eof);
}
if (result != CNH_RESULT_SUCCESS) {
log_error(
"[after][%s] result %d, next_handler %d, file %p, open_filename %s, "
"open_mode %s, read(bytes %p, "
"nbytes %d, pos %d), write(bytes %p, nbytes %d, pos %d), "
"orig_read_write_size %d, orig_read_write_nmemb %d,"
" seek_origin %d, seek_offset %d, tell_offset %llu, eof %d",
_cnh_filehook_mon_irp_op_str[irp->op],
result,
irp->next_handler,
irp->file,
irp->open_filename ? irp->open_filename : _cnh_filehook_mon_str_empty,
irp->open_mode ? irp->open_mode : _cnh_filehook_mon_str_empty,
irp->read.bytes,
irp->read.nbytes,
irp->read.pos,
irp->write.bytes,
irp->write.nbytes,
irp->write.pos,
irp->orig_read_write_size,
irp->orig_read_write_nmemb,
irp->seek_origin,
irp->seek_offset,
irp->tell_offset,
irp->eof);
} else {
log_debug(
"[after][%s] result %d, next_handler %d, file %p, open_filename %s, "
"open_mode %s, read(bytes %p, "
"nbytes %d, pos %d), write(bytes %p, nbytes %d, pos %d), "
"orig_read_write_size %d, orig_read_write_nmemb %d,"
" seek_origin %d, seek_offset %d, tell_offset %llu, eof %d",
_cnh_filehook_mon_irp_op_str[irp->op],
result,
irp->next_handler,
irp->file,
irp->open_filename ? irp->open_filename : _cnh_filehook_mon_str_empty,
irp->open_mode ? irp->open_mode : _cnh_filehook_mon_str_empty,
irp->read.bytes,
irp->read.nbytes,
irp->read.pos,
irp->write.bytes,
irp->write.nbytes,
irp->write.pos,
irp->orig_read_write_size,
irp->orig_read_write_nmemb,
irp->seek_origin,
irp->seek_offset,
irp->tell_offset,
irp->eof);
}
return result;
return result;
}
+2 -1
View File
@@ -1,5 +1,6 @@
/**
* Hook implementation to monitor file related calls, e.g. fopen, fread, fwrite etc.
* Hook implementation to monitor file related calls, e.g. fopen, fread, fwrite
* etc.
*/
#ifndef CAPNHOOK_FILEHOOK_MON_H
#define CAPNHOOK_FILEHOOK_MON_H
+81 -67
View File
@@ -6,91 +6,105 @@
enum cnh_result cnh_fileopen_mon_filehook(struct cnh_filehook_irp *irp)
{
enum cnh_result result;
enum cnh_result result;
if (irp->op == CNH_FILEHOOK_IRP_OP_OPEN) {
log_debug("[before][fopen]: %s %s", irp->open_filename, irp->open_mode);
if (irp->op == CNH_FILEHOOK_IRP_OP_OPEN) {
log_debug("[before][fopen]: %s %s", irp->open_filename, irp->open_mode);
result = cnh_filehook_invoke_next(irp);
result = cnh_filehook_invoke_next(irp);
log_debug("[after][fopen]: %s %s -> %d (%d)", irp->open_filename, irp->open_mode, irp->file, result);
} else {
result = cnh_filehook_invoke_next(irp);
}
log_debug(
"[after][fopen]: %s %s -> %d (%d)",
irp->open_filename,
irp->open_mode,
irp->file,
result);
} else {
result = cnh_filehook_invoke_next(irp);
}
return result;
return result;
}
enum cnh_result cnh_fileopen_mon_fshook(struct cnh_fshook_irp *irp)
{
enum cnh_result result;
enum cnh_result result;
switch (irp->op) {
case CNH_FSHOOK_IRP_OP_DIR_OPEN:
log_debug("[before][diropen]: %s", irp->opendir_name);
break;
case CNH_FSHOOK_IRP_OP_LXSTAT:
log_debug("[before][lxstat]: %s", irp->xstat_file);
break;
case CNH_FSHOOK_IRP_OP_XSTAT:
log_debug("[before][xstat]: %s", irp->xstat_file);
break;
case CNH_FSHOOK_IRP_OP_RENAME:
log_debug("[before][rename]: %s %s", irp->rename_old, irp->rename_new);
break;
case CNH_FSHOOK_IRP_OP_REMOVE:
log_debug("[before][remove]: %s", irp->remove_pathname);
break;
case CNH_FSHOOK_IRP_OP_ACCESS:
log_debug("[before][access]: %s", irp->access_path);
break;
default:
log_die("Unhandled case: %d", irp->op);
break;
}
switch (irp->op) {
case CNH_FSHOOK_IRP_OP_DIR_OPEN:
log_debug("[before][diropen]: %s", irp->opendir_name);
break;
case CNH_FSHOOK_IRP_OP_LXSTAT:
log_debug("[before][lxstat]: %s", irp->xstat_file);
break;
case CNH_FSHOOK_IRP_OP_XSTAT:
log_debug("[before][xstat]: %s", irp->xstat_file);
break;
case CNH_FSHOOK_IRP_OP_RENAME:
log_debug("[before][rename]: %s %s", irp->rename_old, irp->rename_new);
break;
case CNH_FSHOOK_IRP_OP_REMOVE:
log_debug("[before][remove]: %s", irp->remove_pathname);
break;
case CNH_FSHOOK_IRP_OP_ACCESS:
log_debug("[before][access]: %s", irp->access_path);
break;
default:
log_die("Unhandled case: %d", irp->op);
break;
}
result = cnh_fshook_invoke_next(irp);
result = cnh_fshook_invoke_next(irp);
switch (irp->op) {
case CNH_FSHOOK_IRP_OP_DIR_OPEN:
log_debug("[after][diropen]: %s -> %d", irp->opendir_name, result);
break;
case CNH_FSHOOK_IRP_OP_LXSTAT:
log_debug("[after][lxstat]: %s -> %d", irp->xstat_file, result);
break;
case CNH_FSHOOK_IRP_OP_XSTAT:
log_debug("[after][xstat]: %s -> %d", irp->xstat_file, result);
break;
case CNH_FSHOOK_IRP_OP_RENAME:
log_debug("[after][rename]: %s %s -> %d", irp->rename_old, irp->rename_new, result);
break;
case CNH_FSHOOK_IRP_OP_REMOVE:
log_debug("[after][remove]: %s -> %d", irp->remove_pathname, result);
break;
case CNH_FSHOOK_IRP_OP_ACCESS:
log_debug("[after][access]: %s -> %d", irp->access_path, result);
break;
default:
log_die("Unhandled case: %d", irp->op);
break;
}
switch (irp->op) {
case CNH_FSHOOK_IRP_OP_DIR_OPEN:
log_debug("[after][diropen]: %s -> %d", irp->opendir_name, result);
break;
case CNH_FSHOOK_IRP_OP_LXSTAT:
log_debug("[after][lxstat]: %s -> %d", irp->xstat_file, result);
break;
case CNH_FSHOOK_IRP_OP_XSTAT:
log_debug("[after][xstat]: %s -> %d", irp->xstat_file, result);
break;
case CNH_FSHOOK_IRP_OP_RENAME:
log_debug(
"[after][rename]: %s %s -> %d",
irp->rename_old,
irp->rename_new,
result);
break;
case CNH_FSHOOK_IRP_OP_REMOVE:
log_debug("[after][remove]: %s -> %d", irp->remove_pathname, result);
break;
case CNH_FSHOOK_IRP_OP_ACCESS:
log_debug("[after][access]: %s -> %d", irp->access_path, result);
break;
default:
log_die("Unhandled case: %d", irp->op);
break;
}
return result;
return result;
}
enum cnh_result cnh_fileopen_mon_iohook(struct cnh_iohook_irp *irp)
{
enum cnh_result result;
enum cnh_result result;
if (irp->op == CNH_IOHOOK_IRP_OP_OPEN) {
log_debug("[before][open]: %s %d", irp->open_filename, irp->open_flags);
if (irp->op == CNH_IOHOOK_IRP_OP_OPEN) {
log_debug("[before][open]: %s %d", irp->open_filename, irp->open_flags);
result = cnh_iohook_invoke_next(irp);
result = cnh_iohook_invoke_next(irp);
log_debug("[after][open]: %s %d -> %d (%d)", irp->open_filename, irp->open_flags, irp->fd, result);
} else {
result = cnh_iohook_invoke_next(irp);
}
log_debug(
"[after][open]: %s %d -> %d (%d)",
irp->open_filename,
irp->open_flags,
irp->fd,
result);
} else {
result = cnh_iohook_invoke_next(irp);
}
return result;
return result;
}
+6 -3
View File
@@ -9,7 +9,8 @@
#include "capnhook/hook/iohook.h"
/**
* Hook function to add to the hook module for monitoring open file calls on file operations
* Hook function to add to the hook module for monitoring open file calls on
* file operations
*
* @param irp I/O request package of hook module received
* @return Result of operation
@@ -17,7 +18,8 @@
enum cnh_result cnh_fileopen_mon_filehook(struct cnh_filehook_irp *irp);
/**
* Hook function to add to the hook module for monitoring open file calls on file system related operations
* Hook function to add to the hook module for monitoring open file calls on
* file system related operations
*
* @param irp I/O request package of hook module received
* @return Result of operation
@@ -25,7 +27,8 @@ enum cnh_result cnh_fileopen_mon_filehook(struct cnh_filehook_irp *irp);
enum cnh_result cnh_fileopen_mon_fshook(struct cnh_fshook_irp *irp);
/**
* Hook function to add to the hook module for monitoring open file/device calls on I/O operations
* Hook function to add to the hook module for monitoring open file/device calls
* on I/O operations
*
* @param irp I/O request package of hook module received
* @return Result of operation
+63 -29
View File
@@ -4,40 +4,74 @@
#include "util/log.h"
static const char* _cnh_fshook_mon_irp_op_str[] = {
"diropen",
"lxstat",
"xstat",
"rename",
"remove",
"access"
};
static const char *_cnh_fshook_mon_irp_op_str[] = {
"diropen", "lxstat", "xstat", "rename", "remove", "access"};
enum cnh_result cnh_fshook_mon(struct cnh_fshook_irp *irp)
{
enum cnh_result result;
enum cnh_result result;
log_debug("[before][%s] next_handler %d, opendir_name %s, opendir_ret %p, xstat_version %d, xstat_file %s, "
"xstat_buf %p, rename_old %s, rename_new %s, remove_pathname %s, access_path %s, access_amode %d",
_cnh_fshook_mon_irp_op_str[irp->op], irp->next_handler, irp->opendir_name, irp->opendir_ret,
irp->xstat_version, irp->xstat_file, irp->xstat_buf, irp->rename_old, irp->rename_new, irp->remove_pathname,
irp->access_path, irp->access_amode);
log_debug(
"[before][%s] next_handler %d, opendir_name %s, opendir_ret %p, "
"xstat_version %d, xstat_file %s, "
"xstat_buf %p, rename_old %s, rename_new %s, remove_pathname %s, "
"access_path %s, access_amode %d",
_cnh_fshook_mon_irp_op_str[irp->op],
irp->next_handler,
irp->opendir_name,
irp->opendir_ret,
irp->xstat_version,
irp->xstat_file,
irp->xstat_buf,
irp->rename_old,
irp->rename_new,
irp->remove_pathname,
irp->access_path,
irp->access_amode);
result = cnh_fshook_invoke_next(irp);
result = cnh_fshook_invoke_next(irp);
if (result != CNH_RESULT_SUCCESS) {
log_error("[before][%s] result %d, next_handler %d, opendir_name %s, opendir_ret %p, xstat_version %d, "
"xstat_file %s, xstat_buf %p, rename_old %s, rename_new %s, remove_pathname %s, access_path %s, "
"access_amode %d", _cnh_fshook_mon_irp_op_str[irp->op], result, irp->next_handler, irp->opendir_name,
irp->opendir_ret, irp->xstat_version, irp->xstat_file, irp->xstat_buf, irp->rename_old, irp->rename_new,
irp->remove_pathname, irp->access_path, irp->access_amode);
} else {
log_debug("[before][%s] result %d, next_handler %d, opendir_name %s, opendir_ret %p, xstat_version %d, "
"xstat_file %s, xstat_buf %p, rename_old %s, rename_new %s, remove_pathname %s, access_path %s, "
"access_amode %d", _cnh_fshook_mon_irp_op_str[irp->op], result, irp->next_handler, irp->opendir_name,
irp->opendir_ret, irp->xstat_version, irp->xstat_file, irp->xstat_buf, irp->rename_old, irp->rename_new,
irp->remove_pathname, irp->access_path, irp->access_amode);
}
if (result != CNH_RESULT_SUCCESS) {
log_error(
"[before][%s] result %d, next_handler %d, opendir_name %s, opendir_ret "
"%p, xstat_version %d, "
"xstat_file %s, xstat_buf %p, rename_old %s, rename_new %s, "
"remove_pathname %s, access_path %s, "
"access_amode %d",
_cnh_fshook_mon_irp_op_str[irp->op],
result,
irp->next_handler,
irp->opendir_name,
irp->opendir_ret,
irp->xstat_version,
irp->xstat_file,
irp->xstat_buf,
irp->rename_old,
irp->rename_new,
irp->remove_pathname,
irp->access_path,
irp->access_amode);
} else {
log_debug(
"[before][%s] result %d, next_handler %d, opendir_name %s, opendir_ret "
"%p, xstat_version %d, "
"xstat_file %s, xstat_buf %p, rename_old %s, rename_new %s, "
"remove_pathname %s, access_path %s, "
"access_amode %d",
_cnh_fshook_mon_irp_op_str[irp->op],
result,
irp->next_handler,
irp->opendir_name,
irp->opendir_ret,
irp->xstat_version,
irp->xstat_file,
irp->xstat_buf,
irp->rename_old,
irp->rename_new,
irp->remove_pathname,
irp->access_path,
irp->access_amode);
}
return result;
return result;
}
+2 -1
View File
@@ -7,7 +7,8 @@
#include "capnhook/hook/fshook.h"
/**
* Hook function to add to the hook module for monitoring file system related calls
* Hook function to add to the hook module for monitoring file system related
* calls
*
* @param irp I/O request package of hook module received
* @return Result of operation
+95 -40
View File
@@ -4,51 +4,106 @@
#include "util/log.h"
static const char* _cnh_iohook_mon_str_empty = "";
static const char* _cnh_iohook_mon_irp_op_str[] = {
"open",
"fdopen",
"close",
"read",
"write",
"seek",
"ioctl"
};
static const char *_cnh_iohook_mon_str_empty = "";
static const char *_cnh_iohook_mon_irp_op_str[] = {
"open", "fdopen", "close", "read", "write", "seek", "ioctl"};
enum cnh_result cnh_iohook_mon(struct cnh_iohook_irp *irp)
{
enum cnh_result result;
enum cnh_result result;
log_debug("[before][%s] next_handler %d, fd %d, open_filename %s, open_flags %d, fdopen_fd %d, fdopen_mode %s, "
"fdopen_res %p, read(bytes %p, nbytes %d, pos %d), write(bytes %p, nbytes %d, pos %d), seek_origin %d, "
"seek_offset %d, seek_pos %llu, ioctl_req %d, ioctl(bytes %p, nbytes %d, pos %d)",
_cnh_iohook_mon_irp_op_str[irp->op], irp->next_handler, irp->fd,
irp->open_filename ? irp->open_filename : _cnh_iohook_mon_str_empty, irp->open_flags, irp->fdopen_fd,
irp->fdopen_mode ? irp->fdopen_mode : _cnh_iohook_mon_str_empty, irp->fdopen_res, irp->read.bytes,
irp->read.nbytes, irp->read.pos, irp->write.bytes, irp->write.nbytes, irp->write.pos, irp->seek_origin,
irp->seek_offset, irp->seek_pos, irp->ioctl_req, irp->ioctl.bytes, irp->ioctl.nbytes, irp->ioctl.pos);
log_debug(
"[before][%s] next_handler %d, fd %d, open_filename %s, open_flags %d, "
"fdopen_fd %d, fdopen_mode %s, "
"fdopen_res %p, read(bytes %p, nbytes %d, pos %d), write(bytes %p, "
"nbytes %d, pos %d), seek_origin %d, "
"seek_offset %d, seek_pos %llu, ioctl_req %d, ioctl(bytes %p, nbytes %d, "
"pos %d)",
_cnh_iohook_mon_irp_op_str[irp->op],
irp->next_handler,
irp->fd,
irp->open_filename ? irp->open_filename : _cnh_iohook_mon_str_empty,
irp->open_flags,
irp->fdopen_fd,
irp->fdopen_mode ? irp->fdopen_mode : _cnh_iohook_mon_str_empty,
irp->fdopen_res,
irp->read.bytes,
irp->read.nbytes,
irp->read.pos,
irp->write.bytes,
irp->write.nbytes,
irp->write.pos,
irp->seek_origin,
irp->seek_offset,
irp->seek_pos,
irp->ioctl_req,
irp->ioctl.bytes,
irp->ioctl.nbytes,
irp->ioctl.pos);
result = cnh_iohook_invoke_next(irp);
result = cnh_iohook_invoke_next(irp);
if (result != CNH_RESULT_SUCCESS) {
log_error("[after][%s] next_handler %d, res: %d, fd %d, open_filename %s, open_flags %d, fdopen_fd %d, "
"fdopen_mode %s, fdopen_res %p, read(bytes %p, nbytes %d, pos %d), write(bytes %p, nbytes %d, pos %d), "
"seek_origin %d, seek_offset %d, seek_pos %llu, ioctl_req %d, ioctl(bytes %p, nbytes %d, pos %d)",
_cnh_iohook_mon_irp_op_str[irp->op], irp->next_handler, result, irp->fd,
irp->open_filename ? irp->open_filename : _cnh_iohook_mon_str_empty, irp->open_flags, irp->fdopen_fd,
irp->fdopen_mode ? irp->fdopen_mode : _cnh_iohook_mon_str_empty, irp->fdopen_res, irp->read.bytes,
irp->read.nbytes, irp->read.pos, irp->write.bytes, irp->write.nbytes, irp->write.pos, irp->seek_origin,
irp->seek_offset, irp->seek_pos, irp->ioctl_req, irp->ioctl.bytes, irp->ioctl.nbytes, irp->ioctl.pos);
} else {
log_debug("[after][%s] next_handler %d, res %d, fd %d, open_filename %s, open_flags %d, fdopen_fd %d, "
"fdopen_mode %s, fdopen_res %p, read(bytes %p, nbytes %d, pos %d), write(bytes %p, nbytes %d, pos %d), "
"seek_origin %d, seek_offset %d, seek_pos %llu, ioctl_req %d, ioctl(bytes %p, nbytes %d, pos %d)",
_cnh_iohook_mon_irp_op_str[irp->op], irp->next_handler, result, irp->fd,
irp->open_filename ? irp->open_filename : _cnh_iohook_mon_str_empty, irp->open_flags, irp->fdopen_fd,
irp->fdopen_mode ? irp->fdopen_mode : _cnh_iohook_mon_str_empty, irp->fdopen_res, irp->read.bytes,
irp->read.nbytes, irp->read.pos, irp->write.bytes, irp->write.nbytes, irp->write.pos, irp->seek_origin,
irp->seek_offset, irp->seek_pos, irp->ioctl_req, irp->ioctl.bytes, irp->ioctl.nbytes, irp->ioctl.pos);
}
if (result != CNH_RESULT_SUCCESS) {
log_error(
"[after][%s] next_handler %d, res: %d, fd %d, open_filename %s, "
"open_flags %d, fdopen_fd %d, "
"fdopen_mode %s, fdopen_res %p, read(bytes %p, nbytes %d, pos %d), "
"write(bytes %p, nbytes %d, pos %d), "
"seek_origin %d, seek_offset %d, seek_pos %llu, ioctl_req %d, "
"ioctl(bytes %p, nbytes %d, pos %d)",
_cnh_iohook_mon_irp_op_str[irp->op],
irp->next_handler,
result,
irp->fd,
irp->open_filename ? irp->open_filename : _cnh_iohook_mon_str_empty,
irp->open_flags,
irp->fdopen_fd,
irp->fdopen_mode ? irp->fdopen_mode : _cnh_iohook_mon_str_empty,
irp->fdopen_res,
irp->read.bytes,
irp->read.nbytes,
irp->read.pos,
irp->write.bytes,
irp->write.nbytes,
irp->write.pos,
irp->seek_origin,
irp->seek_offset,
irp->seek_pos,
irp->ioctl_req,
irp->ioctl.bytes,
irp->ioctl.nbytes,
irp->ioctl.pos);
} else {
log_debug(
"[after][%s] next_handler %d, res %d, fd %d, open_filename %s, "
"open_flags %d, fdopen_fd %d, "
"fdopen_mode %s, fdopen_res %p, read(bytes %p, nbytes %d, pos %d), "
"write(bytes %p, nbytes %d, pos %d), "
"seek_origin %d, seek_offset %d, seek_pos %llu, ioctl_req %d, "
"ioctl(bytes %p, nbytes %d, pos %d)",
_cnh_iohook_mon_irp_op_str[irp->op],
irp->next_handler,
result,
irp->fd,
irp->open_filename ? irp->open_filename : _cnh_iohook_mon_str_empty,
irp->open_flags,
irp->fdopen_fd,
irp->fdopen_mode ? irp->fdopen_mode : _cnh_iohook_mon_str_empty,
irp->fdopen_res,
irp->read.bytes,
irp->read.nbytes,
irp->read.pos,
irp->write.bytes,
irp->write.nbytes,
irp->write.pos,
irp->seek_origin,
irp->seek_offset,
irp->seek_pos,
irp->ioctl_req,
irp->ioctl.bytes,
irp->ioctl.nbytes,
irp->ioctl.pos);
}
return result;
return result;
}
+189 -167
View File
@@ -4,17 +4,19 @@
#include <stdlib.h>
#include <string.h>
#include "capnhook/hook/fshook.h"
#include "capnhook/hook/filehook.h"
#include "capnhook/hook/fshook.h"
#include "capnhook/hook/iohook.h"
#include "util/log.h"
#include "util/str.h"
#include "util/time.h"
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Hooks to fshook module */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
static enum cnh_result _cnh_redir_fshook_diropen(struct cnh_fshook_irp *irp);
static enum cnh_result _cnh_redir_fshook_lxstat(struct cnh_fshook_irp *irp);
@@ -32,11 +34,14 @@ static const cnh_fshook_fn_t _cnh_redir_fshook_handlers[6] = {
[CNH_FSHOOK_IRP_OP_ACCESS] = _cnh_redir_fshook_access,
};
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Hooks to filehook module */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
static enum cnh_result _cnh_redir_filehook_default(struct cnh_filehook_irp *irp);
static enum cnh_result
_cnh_redir_filehook_default(struct cnh_filehook_irp *irp);
static enum cnh_result _cnh_redir_filehook_fopen(struct cnh_filehook_irp *irp);
static const cnh_filehook_fn_t _cnh_redir_filehook_handlers[8] = {
@@ -50,9 +55,11 @@ static const cnh_filehook_fn_t _cnh_redir_filehook_handlers[8] = {
[CNH_FILEHOOK_IRP_OP_EOF] = _cnh_redir_filehook_default,
};
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Hooks to iohook module */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
static enum cnh_result _cnh_redir_iohook_default(struct cnh_iohook_irp *irp);
static enum cnh_result _cnh_redir_iohook_open(struct cnh_iohook_irp *irp);
@@ -67,305 +74,320 @@ static const cnh_iohook_fn_t _cnh_redir_iohook_handlers[7] = {
[CNH_IOHOOK_IRP_OP_IOCTL] = _cnh_redir_iohook_default,
};
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Private state */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
struct cnh_redir_redir {
char* src;
char* dest;
char *src;
char *dest;
};
static atomic_int _cnh_redir_initted = ATOMIC_VAR_INIT(0);
static atomic_int _cnh_redir_init_in_progress = ATOMIC_VAR_INIT(0);
static pthread_mutex_t _cnh_redir_lock;
static struct cnh_redir_redir* _cnh_redir_redirs;
static struct cnh_redir_redir *_cnh_redir_redirs;
static size_t _cnh_redir_nredirs;
static void _cnh_redir_init();
static char* _cnh_redir_check(const char* src);
static char *_cnh_redir_check(const char *src);
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Public module functions */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
void cnh_redir_add(const char* src, const char* dest)
void cnh_redir_add(const char *src, const char *dest)
{
struct cnh_redir_redir *new_array;
size_t new_size;
struct cnh_redir_redir *new_array;
size_t new_size;
assert(src != NULL);
assert(dest != NULL);
assert(src != NULL);
assert(dest != NULL);
/* Ensure module is initialized */
_cnh_redir_init();
/* Ensure module is initialized */
_cnh_redir_init();
pthread_mutex_lock(&_cnh_redir_lock);
pthread_mutex_lock(&_cnh_redir_lock);
new_size = _cnh_redir_nredirs + 1;
new_array = realloc(_cnh_redir_redirs, new_size * sizeof(struct cnh_redir_redir));
new_size = _cnh_redir_nredirs + 1;
new_array =
realloc(_cnh_redir_redirs, new_size * sizeof(struct cnh_redir_redir));
if (new_array != NULL) {
_cnh_redir_redirs = new_array;
}
if (new_array != NULL) {
_cnh_redir_redirs = new_array;
}
_cnh_redir_redirs[_cnh_redir_nredirs].src = util_str_dup(src);
_cnh_redir_redirs[_cnh_redir_nredirs].dest = util_str_dup(dest);
_cnh_redir_redirs[_cnh_redir_nredirs].src = util_str_dup(src);
_cnh_redir_redirs[_cnh_redir_nredirs].dest = util_str_dup(dest);
_cnh_redir_nredirs++;
_cnh_redir_nredirs++;
pthread_mutex_unlock(&_cnh_redir_lock);
pthread_mutex_unlock(&_cnh_redir_lock);
log_info("Added path redirect %s -> %s", src, dest);
log_info("Added path redirect %s -> %s", src, dest);
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Hooks to fshook module */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
enum cnh_result cnh_redir_fshook(struct cnh_fshook_irp* irp)
enum cnh_result cnh_redir_fshook(struct cnh_fshook_irp *irp)
{
cnh_fshook_fn_t handler;
cnh_fshook_fn_t handler;
handler = _cnh_redir_fshook_handlers[irp->op];
handler = _cnh_redir_fshook_handlers[irp->op];
assert(handler != NULL);
assert(handler != NULL);
return handler(irp);
return handler(irp);
}
static enum cnh_result _cnh_redir_fshook_diropen(struct cnh_fshook_irp *irp)
{
char* res;
char *res;
/* Ensure module is initialized */
_cnh_redir_init();
/* Ensure module is initialized */
_cnh_redir_init();
res = _cnh_redir_check(irp->opendir_name);
res = _cnh_redir_check(irp->opendir_name);
if (res != NULL) {
irp->opendir_name = res;
}
if (res != NULL) {
irp->opendir_name = res;
}
return cnh_fshook_invoke_next(irp);
return cnh_fshook_invoke_next(irp);
}
static enum cnh_result _cnh_redir_fshook_lxstat(struct cnh_fshook_irp *irp)
{
char* res;
char *res;
/* Ensure module is initialized */
_cnh_redir_init();
/* Ensure module is initialized */
_cnh_redir_init();
res = _cnh_redir_check(irp->xstat_file);
res = _cnh_redir_check(irp->xstat_file);
if (res != NULL) {
irp->xstat_file = res;
}
if (res != NULL) {
irp->xstat_file = res;
}
return cnh_fshook_invoke_next(irp);
return cnh_fshook_invoke_next(irp);
}
static enum cnh_result _cnh_redir_fshook_xstat(struct cnh_fshook_irp *irp)
{
char* res;
char *res;
/* Ensure module is initialized */
_cnh_redir_init();
/* Ensure module is initialized */
_cnh_redir_init();
res = _cnh_redir_check(irp->xstat_file);
res = _cnh_redir_check(irp->xstat_file);
if (res != NULL) {
irp->xstat_file = res;
}
if (res != NULL) {
irp->xstat_file = res;
}
return cnh_fshook_invoke_next(irp);
return cnh_fshook_invoke_next(irp);
}
static enum cnh_result _cnh_redir_fshook_rename(struct cnh_fshook_irp *irp)
{
char* res_old;
char* res_new;
char *res_old;
char *res_new;
/* Ensure module is initialized */
_cnh_redir_init();
/* Ensure module is initialized */
_cnh_redir_init();
res_old = _cnh_redir_check(irp->rename_old);
res_new = _cnh_redir_check(irp->rename_old);
res_old = _cnh_redir_check(irp->rename_old);
res_new = _cnh_redir_check(irp->rename_old);
if (res_old != NULL) {
irp->rename_old = res_old;
}
if (res_old != NULL) {
irp->rename_old = res_old;
}
if (res_new != NULL) {
irp->rename_new = res_new;
}
if (res_new != NULL) {
irp->rename_new = res_new;
}
return cnh_fshook_invoke_next(irp);
return cnh_fshook_invoke_next(irp);
}
static enum cnh_result _cnh_redir_fshook_remove(struct cnh_fshook_irp *irp)
{
char* res;
char *res;
/* Ensure module is initialized */
_cnh_redir_init();
/* Ensure module is initialized */
_cnh_redir_init();
res = _cnh_redir_check(irp->remove_pathname);
res = _cnh_redir_check(irp->remove_pathname);
if (res != NULL) {
irp->remove_pathname = res;
}
if (res != NULL) {
irp->remove_pathname = res;
}
return cnh_fshook_invoke_next(irp);
return cnh_fshook_invoke_next(irp);
}
static enum cnh_result _cnh_redir_fshook_access(struct cnh_fshook_irp *irp)
{
char* res;
char *res;
/* Ensure module is initialized */
_cnh_redir_init();
/* Ensure module is initialized */
_cnh_redir_init();
res = _cnh_redir_check(irp->access_path);
res = _cnh_redir_check(irp->access_path);
if (res != NULL) {
irp->access_path = res;
}
if (res != NULL) {
irp->access_path = res;
}
return cnh_fshook_invoke_next(irp);
return cnh_fshook_invoke_next(irp);
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Hooks to iohook module */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
enum cnh_result cnh_redir_iohook(struct cnh_iohook_irp* irp)
enum cnh_result cnh_redir_iohook(struct cnh_iohook_irp *irp)
{
cnh_iohook_fn_t handler;
cnh_iohook_fn_t handler;
handler = _cnh_redir_iohook_handlers[irp->op];
handler = _cnh_redir_iohook_handlers[irp->op];
assert(handler != NULL);
assert(handler != NULL);
return handler(irp);
return handler(irp);
}
static enum cnh_result _cnh_redir_iohook_default(struct cnh_iohook_irp *irp)
{
return cnh_iohook_invoke_next(irp);
return cnh_iohook_invoke_next(irp);
}
static enum cnh_result _cnh_redir_iohook_open(struct cnh_iohook_irp *irp)
{
char* res;
char *res;
/* Ensure module is initialized */
_cnh_redir_init();
/* Ensure module is initialized */
_cnh_redir_init();
res = _cnh_redir_check(irp->open_filename);
res = _cnh_redir_check(irp->open_filename);
if (res != NULL) {
irp->open_filename = res;
}
if (res != NULL) {
irp->open_filename = res;
}
return cnh_iohook_invoke_next(irp);
return cnh_iohook_invoke_next(irp);
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Hooks to filehook module */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
enum cnh_result cnh_redir_filehook(struct cnh_filehook_irp* irp)
enum cnh_result cnh_redir_filehook(struct cnh_filehook_irp *irp)
{
cnh_filehook_fn_t handler;
cnh_filehook_fn_t handler;
handler = _cnh_redir_filehook_handlers[irp->op];
handler = _cnh_redir_filehook_handlers[irp->op];
assert(handler != NULL);
assert(handler != NULL);
return handler(irp);
return handler(irp);
}
static enum cnh_result _cnh_redir_filehook_default(struct cnh_filehook_irp *irp)
{
return cnh_filehook_invoke_next(irp);
return cnh_filehook_invoke_next(irp);
}
static enum cnh_result _cnh_redir_filehook_fopen(struct cnh_filehook_irp *irp)
{
char* res;
char *res;
/* Ensure module is initialized */
_cnh_redir_init();
/* Ensure module is initialized */
_cnh_redir_init();
res = _cnh_redir_check(irp->open_filename);
res = _cnh_redir_check(irp->open_filename);
if (res != NULL) {
irp->open_filename = res;
}
if (res != NULL) {
irp->open_filename = res;
}
return cnh_filehook_invoke_next(irp);
return cnh_filehook_invoke_next(irp);
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Helper functions */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
static void _cnh_redir_init()
{
int expected;
int expected;
if (atomic_load(&_cnh_redir_initted) > 0) {
return;
if (atomic_load(&_cnh_redir_initted) > 0) {
return;
}
expected = 0;
if (!atomic_compare_exchange_strong(
&_cnh_redir_init_in_progress, &expected, 1)) {
while (atomic_load(&_cnh_redir_init_in_progress) > 1) {
util_time_sleep_us(100);
}
expected = 0;
return;
}
if (!atomic_compare_exchange_strong(&_cnh_redir_init_in_progress, &expected, 1)) {
while (atomic_load(&_cnh_redir_init_in_progress) > 1) {
util_time_sleep_us(100);
}
return;
}
/* Check again to ensure the current thread yielded between the init'd check and setting init in progress */
if (atomic_load(&_cnh_redir_initted) > 0) {
/* Revert init in progress, because nothing to do anymore */
atomic_store(&_cnh_redir_init_in_progress, 0);
return;
}
pthread_mutex_init(&_cnh_redir_lock, NULL);
atomic_store(&_cnh_redir_initted, 1);
/* Check again to ensure the current thread yielded between the init'd check
* and setting init in progress */
if (atomic_load(&_cnh_redir_initted) > 0) {
/* Revert init in progress, because nothing to do anymore */
atomic_store(&_cnh_redir_init_in_progress, 0);
return;
}
pthread_mutex_init(&_cnh_redir_lock, NULL);
atomic_store(&_cnh_redir_initted, 1);
atomic_store(&_cnh_redir_init_in_progress, 0);
}
static char* _cnh_redir_check(const char* src)
static char *_cnh_redir_check(const char *src)
{
const char* redir_src;
const char* redir_dest;
char* res;
const char *redir_src;
const char *redir_dest;
char *res;
res = NULL;
res = NULL;
pthread_mutex_lock(&_cnh_redir_lock);
pthread_mutex_lock(&_cnh_redir_lock);
for (size_t i = 0; i < _cnh_redir_nredirs; i++) {
redir_src = _cnh_redir_redirs[i].src;
redir_dest = _cnh_redir_redirs[i].dest;
for (size_t i = 0; i < _cnh_redir_nredirs; i++) {
redir_src = _cnh_redir_redirs[i].src;
redir_dest = _cnh_redir_redirs[i].dest;
if (strncmp(src, redir_src, strlen(redir_src)) == 0) {
// FIXME memory leak
res = util_str_merge(redir_dest, &src[strlen(redir_src)]);
log_debug("Redirect %s -> %s", src, res);
break;
}
if (strncmp(src, redir_src, strlen(redir_src)) == 0) {
// FIXME memory leak
res = util_str_merge(redir_dest, &src[strlen(redir_src)]);
log_debug("Redirect %s -> %s", src, res);
break;
}
}
pthread_mutex_unlock(&_cnh_redir_lock);
pthread_mutex_unlock(&_cnh_redir_lock);
return res;
return res;
}
+13 -10
View File
@@ -1,29 +1,32 @@
/**
* Hook implementation to redirect files/paths passed as parameters on various file, file system and I/O calls
* Hook implementation to redirect files/paths passed as parameters on various
* file, file system and I/O calls
*/
#ifndef CAPNHOOK_REDIR_H
#define CAPNHOOK_REDIR_H
#include "capnhook/hook/fshook.h"
#include "capnhook/hook/filehook.h"
#include "capnhook/hook/fshook.h"
#include "capnhook/hook/iohook.h"
/**
* Add a new path/file redirect to the module
*
* @param src Source path/file to redirect. This does not have to match the full path.
* Postfix, e.g. just the filename is sufficient as well
* @param dest Destination to redirect the original path to. Recommended to use absolute paths here.
* @param src Source path/file to redirect. This does not have to match the full
* path. Postfix, e.g. just the filename is sufficient as well
* @param dest Destination to redirect the original path to. Recommended to use
* absolute paths here.
*/
void cnh_redir_add(const char* src, const char* dest);
void cnh_redir_add(const char *src, const char *dest);
/**
* Hook function to add to the hook module for redirecting file system related calls
* Hook function to add to the hook module for redirecting file system related
* calls
*
* @param irp I/O request package of hook module received
* @return Result of operation
*/
enum cnh_result cnh_redir_fshook(struct cnh_fshook_irp* irp);
enum cnh_result cnh_redir_fshook(struct cnh_fshook_irp *irp);
/**
* Hook function to add to the hook module for redirecting I/O calls
@@ -31,7 +34,7 @@ enum cnh_result cnh_redir_fshook(struct cnh_fshook_irp* irp);
* @param irp I/O request package of hook module received
* @return Result of operation
*/
enum cnh_result cnh_redir_iohook(struct cnh_iohook_irp* irp);
enum cnh_result cnh_redir_iohook(struct cnh_iohook_irp *irp);
/**
* Hook function to add to the hook module for redirecting file related calls
@@ -39,6 +42,6 @@ enum cnh_result cnh_redir_iohook(struct cnh_iohook_irp* irp);
* @param irp I/O request package of hook module received
* @return Result of operation
*/
enum cnh_result cnh_redir_filehook(struct cnh_filehook_irp* irp);
enum cnh_result cnh_redir_filehook(struct cnh_filehook_irp *irp);
#endif
+353 -300
View File
@@ -10,24 +10,32 @@
#include "util/log.h"
#include "util/time.h"
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Private helpers */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
static void _cnh_usb_emu_init(void);
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Hooks to usbhook module */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
static enum cnh_result _cnh_usb_emu_usbhook_default(struct cnh_usbhook_irp *irp);
static enum cnh_result
_cnh_usb_emu_usbhook_default(struct cnh_usbhook_irp *irp);
static enum cnh_result _cnh_usb_emu_usbhook_noop(struct cnh_usbhook_irp *irp);
static enum cnh_result _cnh_usb_emu_usbhook_find_busses(struct cnh_usbhook_irp *irp);
static enum cnh_result _cnh_usb_emu_usbhook_find_devices(struct cnh_usbhook_irp *irp);
static enum cnh_result
_cnh_usb_emu_usbhook_find_busses(struct cnh_usbhook_irp *irp);
static enum cnh_result
_cnh_usb_emu_usbhook_find_devices(struct cnh_usbhook_irp *irp);
static enum cnh_result _cnh_usb_emu_usbhook_open(struct cnh_usbhook_irp *irp);
static enum cnh_result _cnh_usb_emu_usbhook_close(struct cnh_usbhook_irp *irp);
static enum cnh_result _cnh_usb_emu_usbhook_reset(struct cnh_usbhook_irp *irp);
static enum cnh_result _cnh_usb_emu_usbhook_ctrl_msg(struct cnh_usbhook_irp *irp);
static enum cnh_result
_cnh_usb_emu_usbhook_ctrl_msg(struct cnh_usbhook_irp *irp);
static const cnh_usbhook_fn_t _cnh_usb_emu_usb_handlers[10] = {
[CNH_USBHOOK_IRP_OP_INIT] = _cnh_usb_emu_usbhook_default,
@@ -42,19 +50,21 @@ static const cnh_usbhook_fn_t _cnh_usb_emu_usb_handlers[10] = {
[CNH_USBHOOK_IRP_OP_CTRL_MSG] = _cnh_usb_emu_usbhook_ctrl_msg,
};
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Private state */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
struct usb_dev_handle {
struct cnh_usb_emu_virtdev* virtdev;
struct cnh_usb_emu_virtdev *virtdev;
};
struct cnh_usb_emu_virtdev {
const struct cnh_usb_emu_virtdev_ep* ep;
bool real_dev_avail;
bool enumerated;
struct usb_dev_handle usb_dev_handle;
const struct cnh_usb_emu_virtdev_ep *ep;
bool real_dev_avail;
bool enumerated;
struct usb_dev_handle usb_dev_handle;
};
static atomic_int _cnh_usb_emu_initted = ATOMIC_VAR_INIT(0);
@@ -63,432 +73,475 @@ static pthread_mutex_t _cnh_usb_emu_virtdevs_lock;
static struct cnh_usb_emu_virtdev *_cnh_usb_emu_virtdevs;
static size_t _cnh_usb_emu_nvirtdevs;
static struct cnh_usb_emu_virtdev* _cnh_usb_emu_get_virtdev(uint16_t vid, uint16_t pid);
static struct cnh_usb_emu_virtdev* _cnh_usb_emu_get_virtdev_by_handle(usb_dev_handle* handle);
static struct usb_device* _cnh_usb_emu_create_fakedev(uint16_t vid, uint16_t pid);
static struct cnh_usb_emu_virtdev *
_cnh_usb_emu_get_virtdev(uint16_t vid, uint16_t pid);
static struct cnh_usb_emu_virtdev *
_cnh_usb_emu_get_virtdev_by_handle(usb_dev_handle *handle);
static struct usb_device *
_cnh_usb_emu_create_fakedev(uint16_t vid, uint16_t pid);
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Public module functions */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
void cnh_usb_emu_add_virtdevep(const struct cnh_usb_emu_virtdev_ep* virtdevep)
void cnh_usb_emu_add_virtdevep(const struct cnh_usb_emu_virtdev_ep *virtdevep)
{
struct cnh_usb_emu_virtdev *new_array;
size_t new_size;
struct cnh_usb_emu_virtdev *new_array;
size_t new_size;
assert(virtdevep->enumerate);
assert(virtdevep->open);
assert(virtdevep->reset);
assert(virtdevep->control_msg);
assert(virtdevep->close);
assert(virtdevep->enumerate);
assert(virtdevep->open);
assert(virtdevep->reset);
assert(virtdevep->control_msg);
assert(virtdevep->close);
/* Ensure initialized */
_cnh_usb_emu_init();
/* Ensure initialized */
_cnh_usb_emu_init();
pthread_mutex_lock(&_cnh_usb_emu_virtdevs_lock);
pthread_mutex_lock(&_cnh_usb_emu_virtdevs_lock);
new_size = _cnh_usb_emu_nvirtdevs + 1;
new_array = realloc(_cnh_usb_emu_virtdevs, new_size * sizeof(struct cnh_usb_emu_virtdev));
new_size = _cnh_usb_emu_nvirtdevs + 1;
new_array = realloc(
_cnh_usb_emu_virtdevs, new_size * sizeof(struct cnh_usb_emu_virtdev));
if (new_array != NULL) {
_cnh_usb_emu_virtdevs = new_array;
if (new_array != NULL) {
_cnh_usb_emu_virtdevs = new_array;
_cnh_usb_emu_virtdevs[_cnh_usb_emu_nvirtdevs].enumerated = false;
_cnh_usb_emu_virtdevs[_cnh_usb_emu_nvirtdevs].real_dev_avail = false;
_cnh_usb_emu_virtdevs[_cnh_usb_emu_nvirtdevs].ep = virtdevep;
_cnh_usb_emu_virtdevs[_cnh_usb_emu_nvirtdevs].usb_dev_handle.virtdev = &_cnh_usb_emu_virtdevs[_cnh_usb_emu_nvirtdevs];
_cnh_usb_emu_nvirtdevs++;
} else {
log_die("Out of memory");
}
_cnh_usb_emu_virtdevs[_cnh_usb_emu_nvirtdevs].enumerated = false;
_cnh_usb_emu_virtdevs[_cnh_usb_emu_nvirtdevs].real_dev_avail = false;
_cnh_usb_emu_virtdevs[_cnh_usb_emu_nvirtdevs].ep = virtdevep;
_cnh_usb_emu_virtdevs[_cnh_usb_emu_nvirtdevs].usb_dev_handle.virtdev =
&_cnh_usb_emu_virtdevs[_cnh_usb_emu_nvirtdevs];
_cnh_usb_emu_nvirtdevs++;
} else {
log_die("Out of memory");
}
pthread_mutex_unlock(&_cnh_usb_emu_virtdevs_lock);
pthread_mutex_unlock(&_cnh_usb_emu_virtdevs_lock);
}
enum cnh_result cnh_usb_emu(struct cnh_usbhook_irp *irp)
{
cnh_usbhook_fn_t handler;
cnh_usbhook_fn_t handler;
/* Ensure initialized */
_cnh_usb_emu_init();
/* Ensure initialized */
_cnh_usb_emu_init();
handler = _cnh_usb_emu_usb_handlers[irp->op];
handler = _cnh_usb_emu_usb_handlers[irp->op];
assert(handler != NULL);
assert(handler != NULL);
return handler(irp);
return handler(irp);
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Hooked functions to usbhook module */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
static enum cnh_result _cnh_usb_emu_usbhook_default(struct cnh_usbhook_irp *irp)
{
return cnh_usbhook_invoke_next(irp);
return cnh_usbhook_invoke_next(irp);
}
static enum cnh_result _cnh_usb_emu_usbhook_noop(struct cnh_usbhook_irp *irp)
{
struct cnh_usb_emu_virtdev* virtdev;
struct cnh_usb_emu_virtdev *virtdev;
assert(irp->handle);
assert(irp->handle);
virtdev = _cnh_usb_emu_get_virtdev_by_handle(irp->handle);
virtdev = _cnh_usb_emu_get_virtdev_by_handle(irp->handle);
/* Not a virtual device handle, probably real handle from libusb */
if (virtdev == NULL) {
return cnh_usbhook_invoke_next(irp);
}
/* Not a virtual device handle, probably real handle from libusb */
if (virtdev == NULL) {
return cnh_usbhook_invoke_next(irp);
}
/* No-op */
/* No-op */
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
static enum cnh_result _cnh_usb_emu_usbhook_find_busses(struct cnh_usbhook_irp *irp)
static enum cnh_result
_cnh_usb_emu_usbhook_find_busses(struct cnh_usbhook_irp *irp)
{
enum cnh_result result;
enum cnh_result result;
result = cnh_usbhook_invoke_next(irp);
result = cnh_usbhook_invoke_next(irp);
// inject another custom bus for virtual devices
if (result == CNH_RESULT_SUCCESS) {
log_debug("Injecting usb bus for virtual devices");
irp->find_busses_res_num_busses++;
}
// inject another custom bus for virtual devices
if (result == CNH_RESULT_SUCCESS) {
log_debug("Injecting usb bus for virtual devices");
irp->find_busses_res_num_busses++;
}
return result;
return result;
}
static enum cnh_result _cnh_usb_emu_usbhook_find_devices(struct cnh_usbhook_irp *irp)
static enum cnh_result
_cnh_usb_emu_usbhook_find_devices(struct cnh_usbhook_irp *irp)
{
enum cnh_result result;
struct usb_bus* it;
int fakedev_count;
enum cnh_result result;
struct usb_bus *it;
int fakedev_count;
fakedev_count = 0;
fakedev_count = 0;
/* first, populate the list with real devices */
result = cnh_usbhook_invoke_next(irp);
/* first, populate the list with real devices */
result = cnh_usbhook_invoke_next(irp);
/* Iterate to the end of the list and add our stuff keeping real devices */
it = usb_get_busses();
/* Iterate to the end of the list and add our stuff keeping real devices */
it = usb_get_busses();
/* Iterate all busses */
do {
/* First, iterate all devices on each bus and check for all real
devices connected which are also part of our hook list */
if (it != NULL) {
/* Iterate devices on the current bus */
struct usb_device* dev = it->devices;
/* Iterate all busses */
do {
/* First, iterate all devices on each bus and check for all real
devices connected which are also part of our hook list */
if (it != NULL) {
/* Iterate devices on the current bus */
struct usb_device *dev = it->devices;
while (dev != NULL) {
struct cnh_usb_emu_virtdev* virt_dev = _cnh_usb_emu_get_virtdev((uint16_t) dev->descriptor.idVendor,
(uint16_t) dev->descriptor.idProduct);
while (dev != NULL) {
struct cnh_usb_emu_virtdev *virt_dev = _cnh_usb_emu_get_virtdev(
(uint16_t) dev->descriptor.idVendor,
(uint16_t) dev->descriptor.idProduct);
/* Real device connected for a hook */
if (virt_dev) {
log_debug("Detected real %04X:%04X device for virtual one", dev->descriptor.idVendor,
dev->descriptor.idProduct);
virt_dev->real_dev_avail = true;
}
/* Real device connected for a hook */
if (virt_dev) {
log_debug(
"Detected real %04X:%04X device for virtual one",
dev->descriptor.idVendor,
dev->descriptor.idProduct);
virt_dev->real_dev_avail = true;
}
dev = dev->next;
}
}
dev = dev->next;
}
}
/* it == NULL, nothing found on current bus which is our last bus
we added on usb_find_busses. We put our fakedevs on that bus */
if (it == NULL || it->next == NULL) {
struct usb_bus* fakebus;
struct usb_device* fakebus_dev_tail;
/* it == NULL, nothing found on current bus which is our last bus
we added on usb_find_busses. We put our fakedevs on that bus */
if (it == NULL || it->next == NULL) {
struct usb_bus *fakebus;
struct usb_device *fakebus_dev_tail;
/* Create an additional bus for our fakedevs */
fakebus = (struct usb_bus*) util_xmalloc(sizeof(struct usb_bus));
memset(fakebus, 0, sizeof(struct usb_bus));
/* Create an additional bus for our fakedevs */
fakebus = (struct usb_bus *) util_xmalloc(sizeof(struct usb_bus));
memset(fakebus, 0, sizeof(struct usb_bus));
/* Make sure to modify the linked list correctly. If we fuck up,
this works fine until Fiesta where they started to iterate
everything in a different manner (-> crash) */
if (it == NULL) {
usb_busses = fakebus;
/* Bus empty, no prev bus */
fakebus->prev = NULL;
} else {
/* Append at end of bus chain */
it->next = fakebus;
/* Keep doubly linked list intact */
fakebus->prev = it->next;
}
/* Make sure to modify the linked list correctly. If we fuck up,
this works fine until Fiesta where they started to iterate
everything in a different manner (-> crash) */
if (it == NULL) {
usb_busses = fakebus;
/* Bus empty, no prev bus */
fakebus->prev = NULL;
} else {
/* Append at end of bus chain */
it->next = fakebus;
/* Keep doubly linked list intact */
fakebus->prev = it->next;
}
fakebus_dev_tail = NULL;
fakebus_dev_tail = NULL;
pthread_mutex_lock(&_cnh_usb_emu_virtdevs_lock);
pthread_mutex_lock(&_cnh_usb_emu_virtdevs_lock);
for (size_t i = 0; i < _cnh_usb_emu_nvirtdevs; i++) {
struct cnh_usb_emu_virtdev* virtdev = &_cnh_usb_emu_virtdevs[i];
for (size_t i = 0; i < _cnh_usb_emu_nvirtdevs; i++) {
struct cnh_usb_emu_virtdev *virtdev = &_cnh_usb_emu_virtdevs[i];
virtdev->enumerated = virtdev->ep->enumerate(virtdev->real_dev_avail);
virtdev->enumerated = virtdev->ep->enumerate(virtdev->real_dev_avail);
if (virtdev->enumerated) {
if (virtdev->real_dev_avail) {
/* Suppress real device and detour everything to
our hook */
log_debug("Suppressing real device %04X:%04X", virtdev->ep->vid, virtdev->ep->pid);
} else {
/* Create a fakedev and add it to the bus */
struct usb_device* fakedev;
if (virtdev->enumerated) {
if (virtdev->real_dev_avail) {
/* Suppress real device and detour everything to
our hook */
log_debug(
"Suppressing real device %04X:%04X",
virtdev->ep->vid,
virtdev->ep->pid);
} else {
/* Create a fakedev and add it to the bus */
struct usb_device *fakedev;
{
/* Print this once. Pump Pro calls this
function every second */
static int counter = 0;
{
/* Print this once. Pump Pro calls this
function every second */
static int counter = 0;
if (counter++ == 0) {
log_info("Injecting fake usb device %04X:%04X into bus", virtdev->ep->vid,
virtdev->ep->pid);
} else {
counter = 1;
}
}
fakedev = _cnh_usb_emu_create_fakedev(virtdev->ep->vid, virtdev->ep->pid);
/* Append to linked list */
if (!fakebus->devices) {
/* Set root on bus */
fakebus->devices = fakedev;
}
/* Cur element */
fakedev->prev = fakebus_dev_tail;
fakedev->next = NULL;
/* Update prev element's next */
if (fakebus_dev_tail) {
fakebus_dev_tail->next = fakedev;
}
/* tail update */
fakebus_dev_tail = fakedev;
fakedev_count++;
}
} else {
log_debug("Reject enumerate hook for %04X:%04X", virtdev->ep->vid, virtdev->ep->pid);
}
if (counter++ == 0) {
log_info(
"Injecting fake usb device %04X:%04X into bus",
virtdev->ep->vid,
virtdev->ep->pid);
} else {
counter = 1;
}
}
pthread_mutex_unlock(&_cnh_usb_emu_virtdevs_lock);
fakedev =
_cnh_usb_emu_create_fakedev(virtdev->ep->vid, virtdev->ep->pid);
break;
}
/* End of if block which handles fakedevs and hooking */
/* Append to linked list */
if (!fakebus->devices) {
/* Set root on bus */
fakebus->devices = fakedev;
}
it = it->next;
}
while (it != NULL);
/* Cur element */
fakedev->prev = fakebus_dev_tail;
fakedev->next = NULL;
{
/* Print this once. Pump Pro calls this
function every second */
static int counter = 0;
/* Update prev element's next */
if (fakebus_dev_tail) {
fakebus_dev_tail->next = fakedev;
}
if (counter++ == 0) {
log_info("Added %d fakedevs to usb bus", fakedev_count);
/* tail update */
fakebus_dev_tail = fakedev;
fakedev_count++;
}
} else {
counter = 1;
log_debug(
"Reject enumerate hook for %04X:%04X",
virtdev->ep->vid,
virtdev->ep->pid);
}
}
}
/* include our fakedev count as well */
return result + fakedev_count;
pthread_mutex_unlock(&_cnh_usb_emu_virtdevs_lock);
break;
}
/* End of if block which handles fakedevs and hooking */
it = it->next;
} while (it != NULL);
{
/* Print this once. Pump Pro calls this
function every second */
static int counter = 0;
if (counter++ == 0) {
log_info("Added %d fakedevs to usb bus", fakedev_count);
} else {
counter = 1;
}
}
/* include our fakedev count as well */
return result + fakedev_count;
}
static enum cnh_result _cnh_usb_emu_usbhook_open(struct cnh_usbhook_irp *irp)
{
struct cnh_usb_emu_virtdev* virtdev;
enum cnh_result result;
struct cnh_usb_emu_virtdev *virtdev;
enum cnh_result result;
virtdev = _cnh_usb_emu_get_virtdev((uint16_t) irp->open_usb_dev->descriptor.idVendor,
(uint16_t) irp->open_usb_dev->descriptor.idProduct);
virtdev = _cnh_usb_emu_get_virtdev(
(uint16_t) irp->open_usb_dev->descriptor.idVendor,
(uint16_t) irp->open_usb_dev->descriptor.idProduct);
if (virtdev == NULL) {
return cnh_usbhook_invoke_next(irp);
}
if (virtdev == NULL) {
return cnh_usbhook_invoke_next(irp);
}
if (!virtdev->enumerated) {
log_debug("Virtdev %04X:%04X not enumerated, skipping open", virtdev->ep->vid, virtdev->ep->pid);
return cnh_usbhook_invoke_next(irp);
}
if (!virtdev->enumerated) {
log_debug(
"Virtdev %04X:%04X not enumerated, skipping open",
virtdev->ep->vid,
virtdev->ep->pid);
return cnh_usbhook_invoke_next(irp);
}
result = virtdev->ep->open();
result = virtdev->ep->open();
if (result == CNH_RESULT_SUCCESS) {
/* Return handle, use virtual device as fake handle */
irp->handle = &virtdev->usb_dev_handle;
}
if (result == CNH_RESULT_SUCCESS) {
/* Return handle, use virtual device as fake handle */
irp->handle = &virtdev->usb_dev_handle;
}
return result;
return result;
}
static enum cnh_result _cnh_usb_emu_usbhook_close(struct cnh_usbhook_irp *irp)
{
struct cnh_usb_emu_virtdev* virtdev;
struct cnh_usb_emu_virtdev *virtdev;
assert(irp->handle);
assert(irp->handle);
virtdev = _cnh_usb_emu_get_virtdev_by_handle(irp->handle);
virtdev = _cnh_usb_emu_get_virtdev_by_handle(irp->handle);
/* Not a virtual device handle, probably real handle from libusb */
if (virtdev == NULL) {
return cnh_usbhook_invoke_next(irp);
}
/* Not a virtual device handle, probably real handle from libusb */
if (virtdev == NULL) {
return cnh_usbhook_invoke_next(irp);
}
virtdev->ep->close();
virtdev->ep->close();
return CNH_RESULT_SUCCESS;
return CNH_RESULT_SUCCESS;
}
static enum cnh_result _cnh_usb_emu_usbhook_reset(struct cnh_usbhook_irp *irp)
{
struct cnh_usb_emu_virtdev* virtdev;
struct cnh_usb_emu_virtdev *virtdev;
assert(irp->handle);
assert(irp->handle);
virtdev = _cnh_usb_emu_get_virtdev_by_handle(irp->handle);
virtdev = _cnh_usb_emu_get_virtdev_by_handle(irp->handle);
/* Not a virtual device handle, probably real handle from libusb */
if (virtdev == NULL) {
return cnh_usbhook_invoke_next(irp);
}
/* Not a virtual device handle, probably real handle from libusb */
if (virtdev == NULL) {
return cnh_usbhook_invoke_next(irp);
}
return virtdev->ep->reset();
return virtdev->ep->reset();
}
static enum cnh_result _cnh_usb_emu_usbhook_ctrl_msg(struct cnh_usbhook_irp *irp)
static enum cnh_result
_cnh_usb_emu_usbhook_ctrl_msg(struct cnh_usbhook_irp *irp)
{
struct cnh_usb_emu_virtdev* virtdev;
struct cnh_usb_emu_virtdev *virtdev;
assert(irp->handle);
assert(irp->handle);
virtdev = _cnh_usb_emu_get_virtdev_by_handle(irp->handle);
virtdev = _cnh_usb_emu_get_virtdev_by_handle(irp->handle);
/* Not a virtual device handle, probably real handle from libusb */
if (virtdev == NULL) {
return cnh_usbhook_invoke_next(irp);
}
/* Not a virtual device handle, probably real handle from libusb */
if (virtdev == NULL) {
return cnh_usbhook_invoke_next(irp);
}
return virtdev->ep->control_msg(irp->ctrl_req_type, irp->ctrl_req, irp->ctrl_value, irp->ctrl_index,
&irp->ctrl_buffer, irp->ctrl_timeout);
return virtdev->ep->control_msg(
irp->ctrl_req_type,
irp->ctrl_req,
irp->ctrl_value,
irp->ctrl_index,
&irp->ctrl_buffer,
irp->ctrl_timeout);
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
/* Helper functions */
/* ------------------------------------------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------------------------------------------
*/
void _cnh_usb_emu_init(void)
{
int expected;
int expected;
if (atomic_load(&_cnh_usb_emu_initted) > 0) {
return;
if (atomic_load(&_cnh_usb_emu_initted) > 0) {
return;
}
expected = 0;
if (!atomic_compare_exchange_strong(
&_cnh_usb_emu_init_in_progress, &expected, 1)) {
while (atomic_load(&_cnh_usb_emu_init_in_progress) > 1) {
util_time_sleep_us(100);
}
expected = 0;
return;
}
if (!atomic_compare_exchange_strong(&_cnh_usb_emu_init_in_progress, &expected, 1)) {
while (atomic_load(&_cnh_usb_emu_init_in_progress) > 1) {
util_time_sleep_us(100);
}
return;
}
/* Check again to ensure the current thread yielded between the init'd check and setting init in progress */
if (atomic_load(&_cnh_usb_emu_initted) > 0) {
/* Revert init in progress, because nothing to do anymore */
atomic_store(&_cnh_usb_emu_init_in_progress, 0);
return;
}
pthread_mutex_init(&_cnh_usb_emu_virtdevs_lock, NULL);
atomic_store(&_cnh_usb_emu_initted, 1);
/* Check again to ensure the current thread yielded between the init'd check
* and setting init in progress */
if (atomic_load(&_cnh_usb_emu_initted) > 0) {
/* Revert init in progress, because nothing to do anymore */
atomic_store(&_cnh_usb_emu_init_in_progress, 0);
return;
}
pthread_mutex_init(&_cnh_usb_emu_virtdevs_lock, NULL);
atomic_store(&_cnh_usb_emu_initted, 1);
atomic_store(&_cnh_usb_emu_init_in_progress, 0);
}
static struct cnh_usb_emu_virtdev* _cnh_usb_emu_get_virtdev(uint16_t vid, uint16_t pid)
static struct cnh_usb_emu_virtdev *
_cnh_usb_emu_get_virtdev(uint16_t vid, uint16_t pid)
{
struct cnh_usb_emu_virtdev* virtdev;
struct cnh_usb_emu_virtdev* tmp;
struct cnh_usb_emu_virtdev *virtdev;
struct cnh_usb_emu_virtdev *tmp;
virtdev = NULL;
virtdev = NULL;
pthread_mutex_lock(&_cnh_usb_emu_virtdevs_lock);
pthread_mutex_lock(&_cnh_usb_emu_virtdevs_lock);
for (size_t i = 0; i < _cnh_usb_emu_nvirtdevs; i++) {
tmp = &_cnh_usb_emu_virtdevs[i];
for (size_t i = 0; i < _cnh_usb_emu_nvirtdevs; i++) {
tmp = &_cnh_usb_emu_virtdevs[i];
if (tmp->ep->vid == vid && tmp->ep->pid == pid) {
virtdev = tmp;
break;
}
if (tmp->ep->vid == vid && tmp->ep->pid == pid) {
virtdev = tmp;
break;
}
}
pthread_mutex_unlock(&_cnh_usb_emu_virtdevs_lock);
pthread_mutex_unlock(&_cnh_usb_emu_virtdevs_lock);
return virtdev;
return virtdev;
}
static struct cnh_usb_emu_virtdev* _cnh_usb_emu_get_virtdev_by_handle(usb_dev_handle* handle)
static struct cnh_usb_emu_virtdev *
_cnh_usb_emu_get_virtdev_by_handle(usb_dev_handle *handle)
{
struct cnh_usb_emu_virtdev* virtdev;
struct cnh_usb_emu_virtdev* tmp;
struct cnh_usb_emu_virtdev *virtdev;
struct cnh_usb_emu_virtdev *tmp;
virtdev = NULL;
virtdev = NULL;
pthread_mutex_lock(&_cnh_usb_emu_virtdevs_lock);
pthread_mutex_lock(&_cnh_usb_emu_virtdevs_lock);
for (size_t i = 0; i < _cnh_usb_emu_nvirtdevs; i++) {
tmp = &_cnh_usb_emu_virtdevs[i];
for (size_t i = 0; i < _cnh_usb_emu_nvirtdevs; i++) {
tmp = &_cnh_usb_emu_virtdevs[i];
if (tmp == handle->virtdev) {
virtdev = tmp;
break;
}
if (tmp == handle->virtdev) {
virtdev = tmp;
break;
}
}
pthread_mutex_unlock(&_cnh_usb_emu_virtdevs_lock);
pthread_mutex_unlock(&_cnh_usb_emu_virtdevs_lock);
return virtdev;
return virtdev;
}
static struct usb_device* _cnh_usb_emu_create_fakedev(uint16_t vid, uint16_t pid)
static struct usb_device *
_cnh_usb_emu_create_fakedev(uint16_t vid, uint16_t pid)
{
struct usb_device* fakedev = (struct usb_device*) util_xmalloc(sizeof(struct usb_device));
memset(fakedev, 0, sizeof(struct usb_device));
struct usb_device *fakedev =
(struct usb_device *) util_xmalloc(sizeof(struct usb_device));
memset(fakedev, 0, sizeof(struct usb_device));
/* Populate fakedev */
fakedev->descriptor.idVendor = vid;
fakedev->descriptor.idProduct = pid;
/* Populate fakedev */
fakedev->descriptor.idVendor = vid;
fakedev->descriptor.idProduct = pid;
/* Mark as fakedev */
fakedev->descriptor.bcdDevice = 0xBEEF;
/* Mark as fakedev */
fakedev->descriptor.bcdDevice = 0xBEEF;
fakedev->config = (struct usb_config_descriptor*) util_xmalloc(
sizeof(struct usb_config_descriptor));
memset(fakedev->config, 0, sizeof(struct usb_config_descriptor));
fakedev->config = (struct usb_config_descriptor *) util_xmalloc(
sizeof(struct usb_config_descriptor));
memset(fakedev->config, 0, sizeof(struct usb_config_descriptor));
fakedev->config->interface = (struct usb_interface*) util_xmalloc(
sizeof(struct usb_interface));
memset(fakedev->config->interface, 0, sizeof(struct usb_interface));
fakedev->config->interface =
(struct usb_interface *) util_xmalloc(sizeof(struct usb_interface));
memset(fakedev->config->interface, 0, sizeof(struct usb_interface));
fakedev->config->interface->altsetting = (struct usb_interface_descriptor*)
util_xmalloc(sizeof(struct usb_interface_descriptor));
memset(fakedev->config->interface->altsetting, 0,
sizeof(struct usb_interface_descriptor));
fakedev->config->interface->altsetting =
(struct usb_interface_descriptor *) util_xmalloc(
sizeof(struct usb_interface_descriptor));
memset(
fakedev->config->interface->altsetting,
0,
sizeof(struct usb_interface_descriptor));
return fakedev;
return fakedev;
}
+14 -9
View File
@@ -14,14 +14,19 @@
* Virtual device endpoint
*/
struct cnh_usb_emu_virtdev_ep {
uint16_t pid;
uint16_t vid;
bool (*enumerate)(bool real_exists);
enum cnh_result (*open)(void);
enum cnh_result (*reset)(void);
enum cnh_result (*control_msg)(int request_type, int request, int value, int index, struct cnh_iobuf* buffer,
int timeout);
void (*close)(void);
uint16_t pid;
uint16_t vid;
bool (*enumerate)(bool real_exists);
enum cnh_result (*open)(void);
enum cnh_result (*reset)(void);
enum cnh_result (*control_msg)(
int request_type,
int request,
int value,
int index,
struct cnh_iobuf *buffer,
int timeout);
void (*close)(void);
};
/**
@@ -29,7 +34,7 @@ struct cnh_usb_emu_virtdev_ep {
*
* @param virtdevep Virtual device endpoint to add
*/
void cnh_usb_emu_add_virtdevep(const struct cnh_usb_emu_virtdev_ep* virtdevep);
void cnh_usb_emu_add_virtdevep(const struct cnh_usb_emu_virtdev_ep *virtdevep);
/**
* Hook function to add to the hook module for emulating usb devices
+45 -45
View File
@@ -4,9 +4,9 @@
#include "util/log.h"
static enum cnh_result _cnh_usb_init_fix_default(struct cnh_usbhook_irp* irp);
static enum cnh_result _cnh_usb_init_fix_init(struct cnh_usbhook_irp* irp);
static enum cnh_result _cnh_usbio_emu_find_busses(struct cnh_usbhook_irp* irp);
static enum cnh_result _cnh_usb_init_fix_default(struct cnh_usbhook_irp *irp);
static enum cnh_result _cnh_usb_init_fix_init(struct cnh_usbhook_irp *irp);
static enum cnh_result _cnh_usbio_emu_find_busses(struct cnh_usbhook_irp *irp);
static const cnh_usbhook_fn_t _hook_usb_init_fix_handlers[10] = {
[CNH_USBHOOK_IRP_OP_INIT] = _cnh_usb_init_fix_init,
@@ -25,56 +25,56 @@ static int _cnh_usb_init_fix_init_count = 0;
enum cnh_result cnh_usb_init_fix(struct cnh_usbhook_irp *irp)
{
cnh_usbhook_fn_t handler;
cnh_usbhook_fn_t handler;
handler = _hook_usb_init_fix_handlers[irp->op];
handler = _hook_usb_init_fix_handlers[irp->op];
assert(handler != NULL);
assert(handler != NULL);
return handler(irp);
return handler(irp);
}
static enum cnh_result _cnh_usb_init_fix_default(struct cnh_usbhook_irp* irp)
static enum cnh_result _cnh_usb_init_fix_default(struct cnh_usbhook_irp *irp)
{
return cnh_usbhook_invoke_next(irp);
}
static enum cnh_result _cnh_usb_init_fix_init(struct cnh_usbhook_irp *irp)
{
/* On NXA, one programmer/multiple programmers had the bright idea to call
usb_init twice for reasons...
This breaks stuff in the usb-0.1 backend resulting in usb_find_busses
not even finding native devices anymore.
Make sure we call the real usb_init ONCE ONLY to fix that fuck up */
_cnh_usb_init_fix_init_count++;
if (_cnh_usb_init_fix_init_count <= 1) {
return cnh_usbhook_invoke_next(irp);
}
static enum cnh_result _cnh_usb_init_fix_init(struct cnh_usbhook_irp* irp)
{
/* On NXA, one programmer/multiple programmers had the bright idea to call
usb_init twice for reasons...
This breaks stuff in the usb-0.1 backend resulting in usb_find_busses
not even finding native devices anymore.
Make sure we call the real usb_init ONCE ONLY to fix that fuck up */
_cnh_usb_init_fix_init_count++;
if (_cnh_usb_init_fix_init_count <= 1) {
return cnh_usbhook_invoke_next(irp);
} else {
/* Pump Pro is even worse and calls usb_init approx. every second...
avoid overflow of counter if we really leave this running forever.
Furthermore, this avoids printing the log message below with ever
init call */
if (_cnh_usb_init_fix_init_count > 2) {
_cnh_usb_init_fix_init_count = 2;
} else {
/* Pump Pro is even worse and calls usb_init approx. every second...
avoid overflow of counter if we really leave this running forever.
Furthermore, this avoids printing the log message below with ever
init call */
if (_cnh_usb_init_fix_init_count > 2) {
_cnh_usb_init_fix_init_count = 2;
} else {
log_info("usb_init called multiple times, blocking further calls...");
}
return CNH_RESULT_SUCCESS;
}
}
static enum cnh_result _cnh_usbio_emu_find_busses(struct cnh_usbhook_irp* irp)
{
enum cnh_result result;
/* Fixes quirks with usb_init called multiple times on NXA */
if (_cnh_usb_init_fix_init_count <= 1) {
result = cnh_usbhook_invoke_next(irp);
} else {
result = CNH_RESULT_SUCCESS;
log_info("usb_init called multiple times, blocking further calls...");
}
return result;
return CNH_RESULT_SUCCESS;
}
}
static enum cnh_result _cnh_usbio_emu_find_busses(struct cnh_usbhook_irp *irp)
{
enum cnh_result result;
/* Fixes quirks with usb_init called multiple times on NXA */
if (_cnh_usb_init_fix_init_count <= 1) {
result = cnh_usbhook_invoke_next(irp);
} else {
result = CNH_RESULT_SUCCESS;
}
return result;
}
+84 -32
View File
@@ -4,7 +4,7 @@
#include "util/log.h"
static const char* _cnh_usbhook_mon_irp_op_str[] = {
static const char *_cnh_usbhook_mon_irp_op_str[] = {
"init",
"find_busses",
"find_devices",
@@ -14,42 +14,94 @@ static const char* _cnh_usbhook_mon_irp_op_str[] = {
"set_altinterface",
"set_configuration",
"claim_interface",
"ctrl_msg"
};
"ctrl_msg"};
enum cnh_result cnh_usbhook_mon(struct cnh_usbhook_irp *irp)
{
enum cnh_result result;
enum cnh_result result;
log_debug("[before][%s] next_handler %d, find_busses_res_num_busses %d, find_devices_res_num_devices %d, "
"open_usb_dev %p, handle %p, set_altinterface %d, set_configuration %d, claim_interface %d, ctrl_req_type %d, "
"ctrl_req %d, ctrl_value %d, ctrl_index %d, ctrl_buffer(bytes %p, nbytes %d, pos %d), ctrl_timeout %d",
_cnh_usbhook_mon_irp_op_str[irp->op], irp->next_handler, irp->find_busses_res_num_busses,
irp->find_devices_res_num_devices, irp->open_usb_dev, irp->handle, irp->set_altinterface,
irp->set_configuration, irp->claim_interface, irp->ctrl_req_type, irp->ctrl_req, irp->ctrl_value,
irp->ctrl_index, irp->ctrl_buffer.bytes, irp->ctrl_buffer.nbytes, irp->ctrl_buffer.pos, irp->ctrl_timeout);
log_debug(
"[before][%s] next_handler %d, find_busses_res_num_busses %d, "
"find_devices_res_num_devices %d, "
"open_usb_dev %p, handle %p, set_altinterface %d, set_configuration %d, "
"claim_interface %d, ctrl_req_type %d, "
"ctrl_req %d, ctrl_value %d, ctrl_index %d, ctrl_buffer(bytes %p, nbytes "
"%d, pos %d), ctrl_timeout %d",
_cnh_usbhook_mon_irp_op_str[irp->op],
irp->next_handler,
irp->find_busses_res_num_busses,
irp->find_devices_res_num_devices,
irp->open_usb_dev,
irp->handle,
irp->set_altinterface,
irp->set_configuration,
irp->claim_interface,
irp->ctrl_req_type,
irp->ctrl_req,
irp->ctrl_value,
irp->ctrl_index,
irp->ctrl_buffer.bytes,
irp->ctrl_buffer.nbytes,
irp->ctrl_buffer.pos,
irp->ctrl_timeout);
result = cnh_usbhook_invoke_next(irp);
result = cnh_usbhook_invoke_next(irp);
if (result != CNH_RESULT_SUCCESS) {
log_error("[after][%s] result %d, next_handler %d, find_busses_res_num_busses %d, "
"find_devices_res_num_devices %d, open_usb_dev %p, handle %p, set_altinterface %d, set_configuration %d, "
"claim_interface %d, ctrl_req_type %d, ctrl_req %d, ctrl_value %d, ctrl_index %d, ctrl_buffer(bytes %p, "
"nbytes %d, pos %d), ctrl_timeout %d", _cnh_usbhook_mon_irp_op_str[irp->op], result, irp->next_handler,
irp->find_busses_res_num_busses, irp->find_devices_res_num_devices, irp->open_usb_dev, irp->handle,
irp->set_altinterface, irp->set_configuration, irp->claim_interface, irp->ctrl_req_type, irp->ctrl_req,
irp->ctrl_value, irp->ctrl_index, irp->ctrl_buffer.bytes, irp->ctrl_buffer.nbytes, irp->ctrl_buffer.pos,
irp->ctrl_timeout);
} else {
log_debug("[after][%s] result %d, next_handler %d, find_busses_res_num_busses %d, "
"find_devices_res_num_devices %d, open_usb_dev %p, handle %p, set_altinterface %d, set_configuration %d, "
"claim_interface %d, ctrl_req_type %d, ctrl_req %d, ctrl_value %d, ctrl_index %d, ctrl_buffer(bytes %p, "
"nbytes %d, pos %d), ctrl_timeout %d", _cnh_usbhook_mon_irp_op_str[irp->op], result, irp->next_handler,
irp->find_busses_res_num_busses, irp->find_devices_res_num_devices, irp->open_usb_dev, irp->handle,
irp->set_altinterface, irp->set_configuration, irp->claim_interface, irp->ctrl_req_type, irp->ctrl_req,
irp->ctrl_value, irp->ctrl_index, irp->ctrl_buffer.bytes, irp->ctrl_buffer.nbytes, irp->ctrl_buffer.pos,
irp->ctrl_timeout);
}
if (result != CNH_RESULT_SUCCESS) {
log_error(
"[after][%s] result %d, next_handler %d, find_busses_res_num_busses "
"%d, "
"find_devices_res_num_devices %d, open_usb_dev %p, handle %p, "
"set_altinterface %d, set_configuration %d, "
"claim_interface %d, ctrl_req_type %d, ctrl_req %d, ctrl_value %d, "
"ctrl_index %d, ctrl_buffer(bytes %p, "
"nbytes %d, pos %d), ctrl_timeout %d",
_cnh_usbhook_mon_irp_op_str[irp->op],
result,
irp->next_handler,
irp->find_busses_res_num_busses,
irp->find_devices_res_num_devices,
irp->open_usb_dev,
irp->handle,
irp->set_altinterface,
irp->set_configuration,
irp->claim_interface,
irp->ctrl_req_type,
irp->ctrl_req,
irp->ctrl_value,
irp->ctrl_index,
irp->ctrl_buffer.bytes,
irp->ctrl_buffer.nbytes,
irp->ctrl_buffer.pos,
irp->ctrl_timeout);
} else {
log_debug(
"[after][%s] result %d, next_handler %d, find_busses_res_num_busses "
"%d, "
"find_devices_res_num_devices %d, open_usb_dev %p, handle %p, "
"set_altinterface %d, set_configuration %d, "
"claim_interface %d, ctrl_req_type %d, ctrl_req %d, ctrl_value %d, "
"ctrl_index %d, ctrl_buffer(bytes %p, "
"nbytes %d, pos %d), ctrl_timeout %d",
_cnh_usbhook_mon_irp_op_str[irp->op],
result,
irp->next_handler,
irp->find_busses_res_num_busses,
irp->find_devices_res_num_devices,
irp->open_usb_dev,
irp->handle,
irp->set_altinterface,
irp->set_configuration,
irp->claim_interface,
irp->ctrl_req_type,
irp->ctrl_req,
irp->ctrl_value,
irp->ctrl_index,
irp->ctrl_buffer.bytes,
irp->ctrl_buffer.nbytes,
irp->ctrl_buffer.pos,
irp->ctrl_timeout);
}
return result;
return result;
}
+24 -16
View File
@@ -4,26 +4,34 @@
#include "aes.h"
void crypt_aes_enc(uint8_t* key, enum crypt_aes_key_length key_len,
uint8_t* out, const uint8_t* in, size_t nbytes)
void crypt_aes_enc(
uint8_t *key,
enum crypt_aes_key_length key_len,
uint8_t *out,
const uint8_t *in,
size_t nbytes)
{
unsigned long rk[RKLENGTH(128)];
int nrounds;
unsigned long rk[RKLENGTH(128)];
int nrounds;
nrounds = rijndaelSetupEncrypt(rk, key, key_len * 8);
for (size_t i = 0; i < nbytes / key_len; i++) {
rijndaelEncrypt(rk, nrounds, &in[i * key_len], &out[i * key_len]);
}
nrounds = rijndaelSetupEncrypt(rk, key, key_len * 8);
for (size_t i = 0; i < nbytes / key_len; i++) {
rijndaelEncrypt(rk, nrounds, &in[i * key_len], &out[i * key_len]);
}
}
void crypt_aes_dec(uint8_t* key, enum crypt_aes_key_length key_len,
uint8_t* out, const uint8_t* in, size_t nbytes)
void crypt_aes_dec(
uint8_t *key,
enum crypt_aes_key_length key_len,
uint8_t *out,
const uint8_t *in,
size_t nbytes)
{
unsigned long rk[RKLENGTH(128)];
int nrounds;
unsigned long rk[RKLENGTH(128)];
int nrounds;
nrounds = rijndaelSetupDecrypt(rk, key, key_len * 8);
for (size_t i = 0; i < nbytes / key_len; i++) {
rijndaelDecrypt(rk, nrounds, &in[i * key_len], &out[i * key_len]);
}
nrounds = rijndaelSetupDecrypt(rk, key, key_len * 8);
for (size_t i = 0; i < nbytes / key_len; i++) {
rijndaelDecrypt(rk, nrounds, &in[i * key_len], &out[i * key_len]);
}
}
+18 -10
View File
@@ -8,12 +8,12 @@
* AES enc/dec key lengths
*/
enum crypt_aes_key_length {
/* 128 bit */
CRYPT_AES_KEY_LENGTH_16_BYTES = 16,
/* 192 bit */
CRYPT_AES_KEY_LENGTH_24_BYTES = 24,
/* 256 bit */
CRYPT_AES_KEY_LENGTH_32_BYTES = 32,
/* 128 bit */
CRYPT_AES_KEY_LENGTH_16_BYTES = 16,
/* 192 bit */
CRYPT_AES_KEY_LENGTH_24_BYTES = 24,
/* 256 bit */
CRYPT_AES_KEY_LENGTH_32_BYTES = 32,
};
/**
@@ -25,8 +25,12 @@ enum crypt_aes_key_length {
* @param in Input buffer to encrypt
* @param nbytes Number of bytes of input buffer to encrypt
*/
void crypt_aes_enc(uint8_t* key, enum crypt_aes_key_length key_len,
uint8_t* out, const uint8_t* in, size_t nbytes);
void crypt_aes_enc(
uint8_t *key,
enum crypt_aes_key_length key_len,
uint8_t *out,
const uint8_t *in,
size_t nbytes);
/**
* Decrypt data
@@ -37,7 +41,11 @@ void crypt_aes_enc(uint8_t* key, enum crypt_aes_key_length key_len,
* @param in Input buffer to decrypt
* @param nbytes Number of bytes of input buffer to decrypt
*/
void crypt_aes_dec(uint8_t* key, enum crypt_aes_key_length key_len,
uint8_t* out, const uint8_t* in, size_t nbytes);
void crypt_aes_dec(
uint8_t *key,
enum crypt_aes_key_length key_len,
uint8_t *out,
const uint8_t *in,
size_t nbytes);
#endif
+136 -144
View File
@@ -42,17 +42,16 @@ documentation and/or software.
#define S43 15
#define S44 21
static void MD5Transform (uint32_t [4], unsigned char [64]);
static void MD5Transform(uint32_t[4], unsigned char[64]);
static void Encode(unsigned char *, uint32_t *, unsigned int);
static void Decode(uint32_t *, unsigned char *, unsigned int);
static void MD5_memcpy(uint8_t *, uint8_t *, unsigned int);
static void MD5_memset(uint8_t *, int, unsigned int);
static unsigned char PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
/* F, G, H and I are basic MD5 functions.
*/
@@ -63,40 +62,43 @@ static unsigned char PADDING[64] = {
/* ROTATE_LEFT rotates x left n bits.
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
#define FF(a, b, c, d, x, s, ac) \
{ \
(a) += F((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
#define GG(a, b, c, d, x, s, ac) \
{ \
(a) += G((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
#define HH(a, b, c, d, x, s, ac) \
{ \
(a) += H((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
#define II(a, b, c, d, x, s, ac) \
{ \
(a) += I((b), (c), (d)) + (x) + (uint32_t)(ac); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
/* MD5 initialization. Begins an MD5 operation, writing a new context.
*/
void MD5Init (context)
MD5_CTX *context; /* context */
void MD5Init(context) MD5_CTX *context; /* context */
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants.
*/
*/
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
@@ -107,158 +109,152 @@ MD5_CTX *context; /* context */
operation, processing another message block, and updating the
context.
*/
void MD5Update (context, input, inputLen)
MD5_CTX *context; /* context */
unsigned char *input; /* input block */
unsigned int inputLen; /* length of input block */
void MD5Update(context, input, inputLen) MD5_CTX *context; /* context */
unsigned char *input; /* input block */
unsigned int inputLen; /* length of input block */
{
unsigned int i, index, partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((context->count[0] += ((uint32_t)inputLen << 3))
if ((context->count[0] += ((uint32_t) inputLen << 3))
< ((uint32_t)inputLen << 3))
context->count[1]++;
context->count[1] += ((uint32_t)inputLen >> 29);
< ((uint32_t) inputLen << 3))
context->count[1]++;
context->count[1] += ((uint32_t) inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible.
*/
*/
if (inputLen >= partLen) {
MD5_memcpy
((uint8_t *)&context->buffer[index], (uint8_t *)input, partLen);
MD5Transform (context->state, context->buffer);
MD5_memcpy((uint8_t *) &context->buffer[index], (uint8_t *) input, partLen);
MD5Transform(context->state, context->buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
MD5Transform (context->state, &input[i]);
for (i = partLen; i + 63 < inputLen; i += 64)
MD5Transform(context->state, &input[i]);
index = 0;
}
else
i = 0;
index = 0;
} else
i = 0;
/* Buffer remaining input */
MD5_memcpy
((uint8_t *)&context->buffer[index], (uint8_t *)&input[i],
inputLen-i);
MD5_memcpy(
(uint8_t *) &context->buffer[index], (uint8_t *) &input[i], inputLen - i);
}
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
the message digest and zeroizing the context.
*/
void MD5Final (digest, context)
unsigned char digest[16]; /* message digest */
MD5_CTX *context; /* context */
void MD5Final(digest, context) unsigned char digest[16]; /* message digest */
MD5_CTX *context; /* context */
{
unsigned char bits[8];
unsigned int index, padLen;
/* Save number of bits */
Encode (bits, context->count, 8);
Encode(bits, context->count, 8);
/* Pad out to 56 mod 64.
*/
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
*/
index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD5Update (context, PADDING, padLen);
MD5Update(context, PADDING, padLen);
/* Append length (before padding) */
MD5Update (context, bits, 8);
MD5Update(context, bits, 8);
/* Store state in digest */
Encode (digest, context->state, 16);
Encode(digest, context->state, 16);
/* Zeroize sensitive information.
*/
MD5_memset ((uint8_t *)context, 0, sizeof (*context));
*/
MD5_memset((uint8_t *) context, 0, sizeof(*context));
}
/* MD5 basic transformation. Transforms state based on block.
*/
static void MD5Transform (state, block)
uint32_t state[4];
static void MD5Transform(state, block) uint32_t state[4];
unsigned char block[64];
{
uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode (x, block, 64);
Decode(x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
/* Round 2 */
GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
@@ -268,66 +264,62 @@ unsigned char block[64];
/* Zeroize sensitive information.
*/
MD5_memset ((uint8_t *)x, 0, sizeof (x));
MD5_memset((uint8_t *) x, 0, sizeof(x));
}
/* Encodes input (uint32_t) into output (unsigned char). Assumes len is
a multiple of 4.
*/
static void Encode (output, input, len)
unsigned char *output;
static void Encode(output, input, len) unsigned char *output;
uint32_t *input;
unsigned int len;
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (unsigned char)(input[i] & 0xff);
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
output[j] = (unsigned char) (input[i] & 0xff);
output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
}
}
/* Decodes input (unsigned char) into output (uint32_t). Assumes len is
a multiple of 4.
*/
static void Decode (output, input, len)
uint32_t *output;
static void Decode(output, input, len) uint32_t *output;
unsigned char *input;
unsigned int len;
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) |
(((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24);
output[i] = ((uint32_t) input[j]) | (((uint32_t) input[j + 1]) << 8) |
(((uint32_t) input[j + 2]) << 16) | (((uint32_t) input[j + 3]) << 24);
}
/* Note: Replace "for loop" with standard memcpy if possible.
*/
static void MD5_memcpy (output, input, len)
uint8_t * output;
uint8_t * input;
static void MD5_memcpy(output, input, len) uint8_t *output;
uint8_t *input;
unsigned int len;
{
unsigned int i;
for (i = 0; i < len; i++)
output[i] = input[i];
output[i] = input[i];
}
/* Note: Replace "for loop" with standard memset if possible.
*/
static void MD5_memset (output, value, len)
uint8_t * output;
static void MD5_memset(output, value, len) uint8_t *output;
int value;
unsigned int len;
{
unsigned int i;
for (i = 0; i < len; i++)
((char *)output)[i] = (char)value;
((char *) output)[i] = (char) value;
}
+4 -5
View File
@@ -24,12 +24,11 @@ documentation and/or software.
/* MD5 context. */
typedef struct {
uint32_t state[4]; /* state (ABCD) */
uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
uint32_t state[4]; /* state (ABCD) */
uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} MD5_CTX;
void MD5Init(MD5_CTX *);
void MD5Update(MD5_CTX *, unsigned char *, unsigned int);
void MD5Final(unsigned char [16], MD5_CTX *);
void MD5Final(unsigned char[16], MD5_CTX *);
File diff suppressed because it is too large Load Diff
+17 -11
View File
@@ -1,17 +1,23 @@
#ifndef H__RIJNDAEL
#define H__RIJNDAEL
int rijndaelSetupEncrypt(unsigned long *rk, const unsigned char *key,
int keybits);
int rijndaelSetupDecrypt(unsigned long *rk, const unsigned char *key,
int keybits);
void rijndaelEncrypt(const unsigned long *rk, int nrounds,
const unsigned char plaintext[16], unsigned char ciphertext[16]);
void rijndaelDecrypt(const unsigned long *rk, int nrounds,
const unsigned char ciphertext[16], unsigned char plaintext[16]);
int rijndaelSetupEncrypt(
unsigned long *rk, const unsigned char *key, int keybits);
int rijndaelSetupDecrypt(
unsigned long *rk, const unsigned char *key, int keybits);
void rijndaelEncrypt(
const unsigned long *rk,
int nrounds,
const unsigned char plaintext[16],
unsigned char ciphertext[16]);
void rijndaelDecrypt(
const unsigned long *rk,
int nrounds,
const unsigned char ciphertext[16],
unsigned char plaintext[16]);
#define KEYLENGTH(keybits) ((keybits)/8)
#define RKLENGTH(keybits) ((keybits)/8+28)
#define NROUNDS(keybits) ((keybits)/32+6)
#define KEYLENGTH(keybits) ((keybits) / 8)
#define RKLENGTH(keybits) ((keybits) / 8 + 28)
#define NROUNDS(keybits) ((keybits) / 32 + 6)
#endif
+5 -5
View File
@@ -4,11 +4,11 @@
#include "md5.h"
void crypt_md5_hash(uint8_t* out, const uint8_t* in, size_t nbytes)
void crypt_md5_hash(uint8_t *out, const uint8_t *in, size_t nbytes)
{
MD5_CTX ctx;
MD5_CTX ctx;
MD5Init(&ctx);
MD5Update(&ctx, (unsigned char*) in, (unsigned int) nbytes);
MD5Final(out, &ctx);
MD5Init(&ctx);
MD5Update(&ctx, (unsigned char *) in, (unsigned int) nbytes);
MD5Final(out, &ctx);
}
+1 -1
View File
@@ -11,6 +11,6 @@
* @param in Input buffer to hash
* @param nbytes Number of bytes of input buffer to process
*/
void crypt_md5_hash(uint8_t* out, const uint8_t* in, size_t nbytes);
void crypt_md5_hash(uint8_t *out, const uint8_t *in, size_t nbytes);
#endif
+15 -14
View File
@@ -27,24 +27,25 @@ const struct util_options_defs hook_core_options_defs = {
// Just use something because this is not relevant/required here
.usage_param = '\r',
.defs = hook_core_options_def,
.ndefs = lengthof(hook_core_options_def)
};
.ndefs = lengthof(hook_core_options_def)};
void hook_core_options_init(int argc, char** argv, struct hook_core_options* options)
void hook_core_options_init(
int argc, char **argv, struct hook_core_options *options)
{
log_assert(argv);
log_assert(options);
log_assert(argv);
log_assert(options);
struct util_options_opts* options_opt;
struct util_options_opts *options_opt;
util_options_init(argc, argv);
options_opt = util_options_get(&hook_core_options_defs);
util_options_init(argc, argv);
options_opt = util_options_get(&hook_core_options_defs);
if (!options_opt) {
return;
}
if (!options_opt) {
return;
}
options->log.file = util_options_get_str(options_opt, HOOK_CORE_OPTIONS_STR_PATCH_UTIL_LOG_FILE);
options->log.level =
(enum util_log_level) util_options_get_int(options_opt, HOOK_CORE_OPTIONS_STR_PATCH_UTIL_LOG_LEVEL);
options->log.file = util_options_get_str(
options_opt, HOOK_CORE_OPTIONS_STR_PATCH_UTIL_LOG_FILE);
options->log.level = (enum util_log_level) util_options_get_int(
options_opt, HOOK_CORE_OPTIONS_STR_PATCH_UTIL_LOG_LEVEL);
}
+6 -5
View File
@@ -4,12 +4,13 @@
#include "util/log.h"
struct hook_core_options {
struct log {
const char* file;
enum util_log_level level;
} log;
struct log {
const char *file;
enum util_log_level level;
} log;
};
void hook_core_options_init(int argc, char** argv, struct hook_core_options* options);
void hook_core_options_init(
int argc, char **argv, struct hook_core_options *options);
#endif
+90 -80
View File
@@ -13,121 +13,131 @@
#include "util/str.h"
#include "util/sys-info.h"
static void hook_core_piu_log_application_args(int argc, char** argv)
static void hook_core_piu_log_application_args(int argc, char **argv)
{
const char* sep = "\n";
char* str = util_str_dup("");
char* tmp;
const char *sep = "\n";
char *str = util_str_dup("");
char *tmp;
for (int i = 0; i < argc; i++) {
if (strlen(str) > 0) {
tmp = util_str_merge(str, sep);
free(str);
str = tmp;
}
tmp = util_str_merge(str, argv[i]);
free(str);
str = tmp;
for (int i = 0; i < argc; i++) {
if (strlen(str) > 0) {
tmp = util_str_merge(str, sep);
free(str);
str = tmp;
}
log_info("Application arguments (%d):\n%s", argc, str);
tmp = util_str_merge(str, argv[i]);
free(str);
str = tmp;
}
log_info("Application arguments (%d):\n%s", argc, str);
free(str);
}
void hook_core_piu_log_init(int argc, char** argv)
void hook_core_piu_log_init(int argc, char **argv)
{
struct hook_core_options options;
struct hook_core_options options;
hook_core_options_init(argc, argv, &options);
hook_core_options_init(argc, argv, &options);
util_log_set_file(options.log.file, false);
util_log_set_level(options.log.level);
util_log_set_file(options.log.file, false);
util_log_set_level(options.log.level);
}
void hook_core_piu_log_info(int argc, char** argv)
void hook_core_piu_log_info(int argc, char **argv)
{
log_info("\n"
" _ _ \n"
" _ __ _ _ _ __ ___ _ __ | |_ ___ ___ | |___ \n"
" | '_ \\| | | | '_ ` _ \\| '_ \\| __/ _ \\ / _ \\| / __|\n"
" | |_) | |_| | | | | | | |_) | || (_) | (_) | \\__ \\\n"
" | .__/ \\__,_|_| |_| |_| .__/ \\__\\___/ \\___/|_|___/\n"
" |_| |_| ");
log_info(
"\n"
" _ _ \n"
" _ __ _ _ _ __ ___ _ __ | |_ ___ ___ | |___ \n"
" | '_ \\| | | | '_ ` _ \\| '_ \\| __/ _ \\ / _ \\| / __|\n"
" | |_) | |_| | | | | | | |_) | || (_) | (_) | \\__ \\\n"
" | .__/ \\__,_|_| |_| |_| .__/ \\__\\___/ \\___/|_|___/\n"
" |_| |_| ");
log_info("Pumptools build " __DATE__ " " __TIME__ " gitrev %s", STRINGIFY(GITREV));
log_info(
"Pumptools build " __DATE__ " " __TIME__ " gitrev %s", STRINGIFY(GITREV));
util_sys_info_log();
util_proc_log_info();
util_glibc_info_log();
hook_core_piu_log_application_args(argc, argv);
util_sys_info_log();
util_proc_log_info();
util_glibc_info_log();
hook_core_piu_log_application_args(argc, argv);
}
char* hook_core_piu_utils_get_and_verify_game_data_path(int argc, char** argv)
char *hook_core_piu_utils_get_and_verify_game_data_path(int argc, char **argv)
{
if (argc < 2) {
log_error("Missing game data path, usage for piu (stock args): piu <game folder> (e.g. piu ./game)");
exit(0);
}
if (argc < 2) {
log_error(
"Missing game data path, usage for piu (stock args): piu <game folder> "
"(e.g. piu ./game)");
exit(0);
}
char* game_data_path = util_str_dup(argv[1]);
char *game_data_path = util_str_dup(argv[1]);
log_info("Game data path: %s", game_data_path);
log_info("Game data path: %s", game_data_path);
/* remove trailing / for the hook. however, the game crashes without it */
if (util_str_ends_with(game_data_path, "/")) {
game_data_path[strlen(game_data_path) - 1] = '\0';
} else {
log_error("Game data path '%s' does not end with a trailing /, exiting because the game is going to "
"crash anyway!", game_data_path);
exit(0);
}
/* remove trailing / for the hook. however, the game crashes without it */
if (util_str_ends_with(game_data_path, "/")) {
game_data_path[strlen(game_data_path) - 1] = '\0';
} else {
log_error(
"Game data path '%s' does not end with a trailing /, exiting because "
"the game is going to "
"crash anyway!",
game_data_path);
exit(0);
}
/* depending on the version, the game also just crashes if the game folder or files within it were not found */
if (!util_fs_path_exists(game_data_path)) {
log_error("Game data path '%s' does not exist, exiting", game_data_path);
exit(0);
}
/* depending on the version, the game also just crashes if the game folder or
* files within it were not found */
if (!util_fs_path_exists(game_data_path)) {
log_error("Game data path '%s' does not exist, exiting", game_data_path);
exit(0);
}
return game_data_path;
return game_data_path;
}
void hook_core_piu_utils_verify_root_user()
{
log_info("Verifying process is running as root user.");
log_info("Verifying process is running as root user.");
if (!util_proc_is_running_as_root()) {
log_error("Process not running as root which is required for the game to work correctly.");
//exit(0);
}
if (!util_proc_is_running_as_root()) {
log_error(
"Process not running as root which is required for the game to work "
"correctly.");
// exit(0);
}
}
void hook_core_piu_utils_fix_locale()
{
log_info("Fixing locale settings.");
log_info("Fixing locale settings.");
if (setenv("LC_ALL", "C", 1) != 0) {
log_warn("Setting locale LC_ALL failed.");
}
if (setenv("LC_ALL", "C", 1) != 0) {
log_warn("Setting locale LC_ALL failed.");
}
if (unsetenv("LANGUAGE") != 0) {
log_warn("Unsetting LANGUAGE env var failed.");
}
if (unsetenv("LANGUAGE") != 0) {
log_warn("Unsetting LANGUAGE env var failed.");
}
}
bool hook_core_piu_block_non_piu_process_recursion(int argc, char** argv)
bool hook_core_piu_block_non_piu_process_recursion(int argc, char **argv)
{
/* Sanity check for arguments. If further child processes are started
from the current process, and using LD_PRELOAD on the current process,
all children are also getting the preloaded library. This causes
multiple calls to the trap main function and just crashes our
application at some point.
The executable file is required to contain the "piu" substring to make
this work properly */
if (!strstr(argv[0], "piu")) {
log_warn("Not attaching to non piu process %s", argv[0]);
return true;
} else {
return false;
}
/* Sanity check for arguments. If further child processes are started
from the current process, and using LD_PRELOAD on the current process,
all children are also getting the preloaded library. This causes
multiple calls to the trap main function and just crashes our
application at some point.
The executable file is required to contain the "piu" substring to make
this work properly */
if (!strstr(argv[0], "piu")) {
log_warn("Not attaching to non piu process %s", argv[0]);
return true;
} else {
return false;
}
}
+12 -10
View File
@@ -2,14 +2,15 @@
#define HOOK_CORE_PIU_UTILS_H
/**
* Initialize the logging system as early as possible to allow recording everything to a log file as well.
* Initialize the logging system as early as possible to allow recording
* everything to a log file as well.
*/
void hook_core_piu_log_init(int argc, char** argv);
void hook_core_piu_log_init(int argc, char **argv);
/**
* Log process and system relevant information.
*/
void hook_core_piu_log_info(int argc, char** argv);
void hook_core_piu_log_info(int argc, char **argv);
/**
* Check and verify the game data path argument passed to the game via argv
@@ -19,9 +20,10 @@ void hook_core_piu_log_info(int argc, char** argv);
*
* @param argc Argc from piu main
* @param argv Argv from piu main
* @return New string with game data path extracted from argv (caller has to free)
* @return New string with game data path extracted from argv (caller has to
* free)
*/
char* hook_core_piu_utils_get_and_verify_game_data_path(int argc, char** argv);
char *hook_core_piu_utils_get_and_verify_game_data_path(int argc, char **argv);
/**
* Verify that the current process is running as root user because the game
@@ -38,16 +40,16 @@ void hook_core_piu_utils_fix_locale();
/**
* If further child processes are started from the current process, and using
* LD_PRELOAD on the current process, all children are also getting the preloaded
* library. This causes multiple calls to the trap main function and just crashes our
* application at some point. The executable file is required to contain the "piu"
* substring to make this work properly.
* LD_PRELOAD on the current process, all children are also getting the
* preloaded library. This causes multiple calls to the trap main function and
* just crashes our application at some point. The executable file is required
* to contain the "piu" substring to make this work properly.
*
* @param argc Argc from piu main
* @param argv Argv from piu main
* @return True if we have to block this call by another process,
* false if the process calling this is the piu process.
*/
bool hook_core_piu_block_non_piu_process_recursion(int argc, char** argv);
bool hook_core_piu_block_non_piu_process_recursion(int argc, char **argv);
#endif
+74 -62
View File
@@ -10,89 +10,101 @@
#include "util/log.h"
#include "util/patch.h"
static int32_t exchook_eeprom_read(uint8_t* buffer, int32_t len);
static int32_t exchook_eeprom_write(const uint8_t* buffer, int32_t len);
static int32_t exchook_eeprom_read(uint8_t *buffer, int32_t len);
static int32_t exchook_eeprom_write(const uint8_t *buffer, int32_t len);
static char* exchook_eeprom_file;
static char *exchook_eeprom_file;
static uint8_t exchook_eeprom_buffer[8192];
void exchook_eeprom_init(const struct exchook_mempatch_table* patch_table, const char* eeprom_file)
void exchook_eeprom_init(
const struct exchook_mempatch_table *patch_table, const char *eeprom_file)
{
void* buffer;
size_t len;
void *buffer;
size_t len;
exchook_eeprom_file = util_fs_get_abs_path(eeprom_file);
/* EEPROM file does not exist, create new */
if (!exchook_eeprom_file) {
memset(exchook_eeprom_buffer, 0xFF, sizeof(exchook_eeprom_buffer));
FILE *file = fopen(eeprom_file, "wb+");
if (file == NULL) {
log_error(
"Creating new eeprom file %s failed: %s",
eeprom_file,
strerror(errno));
}
fwrite(exchook_eeprom_buffer, sizeof(exchook_eeprom_buffer), 1, file);
fclose(file);
exchook_eeprom_file = util_fs_get_abs_path(eeprom_file);
len = (size_t) -1;
} else {
if (util_file_load(exchook_eeprom_file, &buffer, &len, false)) {
if (len > sizeof(exchook_eeprom_buffer)) {
log_error(
"Contents of %s eeprom file exceed the max eeprom buffer "
" size of %d bytes",
eeprom_file,
sizeof(exchook_eeprom_buffer));
free(buffer);
return;
}
/* EEPROM file does not exist, create new */
if (!exchook_eeprom_file) {
memset(exchook_eeprom_buffer, 0xFF, sizeof(exchook_eeprom_buffer));
FILE* file = fopen(eeprom_file, "wb+");
if (file == NULL) {
log_error("Creating new eeprom file %s failed: %s", eeprom_file, strerror(errno));
}
fwrite(exchook_eeprom_buffer, sizeof(exchook_eeprom_buffer), 1, file);
fclose(file);
exchook_eeprom_file = util_fs_get_abs_path(eeprom_file);
len = (size_t) -1;
/* copy read contents */
memcpy(exchook_eeprom_buffer, buffer, len);
free(buffer);
} else {
if (util_file_load(exchook_eeprom_file, &buffer, &len, false)) {
if (len > sizeof(exchook_eeprom_buffer)) {
log_error("Contents of %s eeprom file exceed the max eeprom buffer "
" size of %d bytes", eeprom_file,
sizeof(exchook_eeprom_buffer));
free(buffer);
return;
}
/* copy read contents */
memcpy(exchook_eeprom_buffer, buffer, len);
free(buffer);
} else {
log_error("Loading eeprom file %s failed", exchook_eeprom_file);
}
log_error("Loading eeprom file %s failed", exchook_eeprom_file);
}
}
log_assert(exchook_eeprom_file);
log_assert(exchook_eeprom_file);
/* Hook eeprom */
util_patch_function(patch_table->addr_eeprom_read, exchook_eeprom_read);
util_patch_function(patch_table->addr_eeprom_write, exchook_eeprom_write);
/* Hook eeprom */
util_patch_function(patch_table->addr_eeprom_read, exchook_eeprom_read);
util_patch_function(patch_table->addr_eeprom_write, exchook_eeprom_write);
log_info("Initizlied (%s), eeprom file %s", len == -1 ? "new" : "loaded", eeprom_file);
log_info(
"Initizlied (%s), eeprom file %s",
len == -1 ? "new" : "loaded",
eeprom_file);
}
static int32_t exchook_eeprom_read(uint8_t* buffer, int32_t len)
static int32_t exchook_eeprom_read(uint8_t *buffer, int32_t len)
{
if (len > sizeof(exchook_eeprom_buffer)) {
log_error("Eeprom read %d exceeds buffer size %d", len,
sizeof(exchook_eeprom_buffer));
return 0;
}
if (len > sizeof(exchook_eeprom_buffer)) {
log_error(
"Eeprom read %d exceeds buffer size %d",
len,
sizeof(exchook_eeprom_buffer));
return 0;
}
memcpy(buffer, exchook_eeprom_buffer, len);
memcpy(buffer, exchook_eeprom_buffer, len);
return len;
return len;
}
static int32_t exchook_eeprom_write(const uint8_t* buffer, int32_t len)
static int32_t exchook_eeprom_write(const uint8_t *buffer, int32_t len)
{
if (len > sizeof(exchook_eeprom_buffer)) {
log_error("Eeprom write %d exceeds buffer size %d", len,
sizeof(exchook_eeprom_buffer));
return 0;
}
if (len > sizeof(exchook_eeprom_buffer)) {
log_error(
"Eeprom write %d exceeds buffer size %d",
len,
sizeof(exchook_eeprom_buffer));
return 0;
}
memcpy(exchook_eeprom_buffer, buffer, len);
memcpy(exchook_eeprom_buffer, buffer, len);
/* Write back to file */
if (!util_file_save(exchook_eeprom_file, exchook_eeprom_buffer, len)) {
log_error("Storing eeprom contents to file %s failed",
exchook_eeprom_file);
}
/* Write back to file */
if (!util_file_save(exchook_eeprom_file, exchook_eeprom_buffer, len)) {
log_error("Storing eeprom contents to file %s failed", exchook_eeprom_file);
}
return len;
return len;
}
+2 -1
View File
@@ -14,6 +14,7 @@
* @param eeprom_file Path to existing eeprom file to read from and new eeprom
* file to store to
*/
void exchook_eeprom_init(const struct exchook_mempatch_table* patch_table, const char* eeprom_file);
void exchook_eeprom_init(
const struct exchook_mempatch_table *patch_table, const char *eeprom_file);
#endif
+413 -405
View File
@@ -11,54 +11,53 @@
#include "util/patch.h"
/* Taken from ioarcade.hpp nx2 src dump */
#define GI_P1_1 0x00000001
#define GI_P1_3 0x00000002
#define GI_P1_5 0x00000004
#define GI_P1_7 0x00000008
#define GI_P1_9 0x00000010
#define GI_P1_1 0x00000001
#define GI_P1_3 0x00000002
#define GI_P1_5 0x00000004
#define GI_P1_7 0x00000008
#define GI_P1_9 0x00000010
#define GI_P2_1 0x00000100
#define GI_P2_3 0x00000200
#define GI_P2_5 0x00000400
#define GI_P2_7 0x00000800
#define GI_P2_9 0x00001000
#define GI_P2_1 0x00000100
#define GI_P2_3 0x00000200
#define GI_P2_5 0x00000400
#define GI_P2_7 0x00000800
#define GI_P2_9 0x00001000
#define GI_TEST 0x00010000
#define GI_SERVICE 0x00020000
#define GI_CLEAR 0x00040000
#define GI_TEST 0x00010000
#define GI_SERVICE 0x00020000
#define GI_CLEAR 0x00040000
#define GI_COIN 0x00100000
#define GI_COIN2 0x00200000
#define GI_COIN 0x00100000
#define GI_COIN2 0x00200000
struct exchook_io_sensores {
uint32_t lu : 4;
uint32_t ru : 4;
uint32_t cn : 4;
uint32_t ld : 4;
uint32_t rd : 4;
uint32_t padding : 12;
uint32_t lu : 4;
uint32_t ru : 4;
uint32_t cn : 4;
uint32_t ld : 4;
uint32_t rd : 4;
uint32_t padding : 12;
};
static const uint8_t exchook_io_sensor_mappings[] = {
1, 2, 3, 0
};
static const uint8_t exchook_io_sensor_mappings[] = {1, 2, 3, 0};
static struct ptapi_io_piuio_api exchook_piuio_api;
static uint16_t exchook_io_check(void* obj);
static int32_t exchook_io_light_all(void* obj, uint8_t on);
static int32_t exchook_io_light_neon(void* obj, uint8_t on);
static int32_t exchook_io_light_halogan(void* obj, uint8_t on, uint16_t light_id);
static int32_t exchook_io_light_p1_ccfl(void* obj, uint8_t on, uint16_t cmd);
static int32_t exchook_io_light_p2_ccfl(void* obj, uint8_t on, uint16_t cmd);
static int32_t exchook_io_input(void* obj);
static int32_t exchook_io_coin_input(void* obj);
static int32_t exchook_io_coin_input_2(void* obj);
static int32_t exchook_io_coin_counter_2(void* obj);
static uint16_t exchook_io_check(void *obj);
static int32_t exchook_io_light_all(void *obj, uint8_t on);
static int32_t exchook_io_light_neon(void *obj, uint8_t on);
static int32_t
exchook_io_light_halogan(void *obj, uint8_t on, uint16_t light_id);
static int32_t exchook_io_light_p1_ccfl(void *obj, uint8_t on, uint16_t cmd);
static int32_t exchook_io_light_p2_ccfl(void *obj, uint8_t on, uint16_t cmd);
static int32_t exchook_io_input(void *obj);
static int32_t exchook_io_coin_input(void *obj);
static int32_t exchook_io_coin_input_2(void *obj);
static int32_t exchook_io_coin_counter_2(void *obj);
static uint32_t* exchook_io_game_input_stat;
static uint32_t* exchook_io_game_input_down;
static uint32_t* exchook_io_game_input_up;
static uint32_t *exchook_io_game_input_stat;
static uint32_t *exchook_io_game_input_down;
static uint32_t *exchook_io_game_input_up;
static uint32_t exchook_io_game_input_stat_prev;
@@ -72,434 +71,443 @@ static struct ptapi_io_piuio_cab_outputs exchook_io_out_cab;
static bool exchook_io_exit_on_service_test;
void exchook_io_init(const struct exchook_mempatch_table* patch_table, const char* piuio_lib_path,
bool exit_on_service_test)
void exchook_io_init(
const struct exchook_mempatch_table *patch_table,
const char *piuio_lib_path,
bool exit_on_service_test)
{
if (!piuio_lib_path) {
log_error("NULL piuio (emu) lib path. Check that you have set-up and configured a piuio API implementation "
"correctly.");
return;
}
if (!piuio_lib_path) {
log_error(
"NULL piuio (emu) lib path. Check that you have set-up and configured "
"a piuio API implementation "
"correctly.");
return;
}
/* Load piuio library funcs */
log_info("Loading piuio api implementation %s", piuio_lib_path);
/* Load piuio library funcs */
log_info("Loading piuio api implementation %s", piuio_lib_path);
if (!ptapi_io_piuio_util_lib_load(piuio_lib_path, &exchook_piuio_api)) {
log_error("Loading piuio API from file %s failed", piuio_lib_path);
return;
}
if (!ptapi_io_piuio_util_lib_load(piuio_lib_path, &exchook_piuio_api)) {
log_error("Loading piuio API from file %s failed", piuio_lib_path);
return;
}
exchook_io_exit_on_service_test = exit_on_service_test;
exchook_io_exit_on_service_test = exit_on_service_test;
log_info("Service + Test exit %d", exchook_io_exit_on_service_test);
log_info("Service + Test exit %d", exchook_io_exit_on_service_test);
/* Hook MK5IO engine calls */
/* Why so many functions you might ask? Because the MK5 IO code is a pile
of shit created by a monkey */
/* Hook MK5IO engine calls */
/* Why so many functions you might ask? Because the MK5 IO code is a pile
of shit created by a monkey */
util_patch_function(patch_table->addr_io_check, exchook_io_check);
util_patch_function(patch_table->addr_io_light_all, exchook_io_light_all);
util_patch_function(patch_table->addr_io_light_neon, exchook_io_light_neon);
util_patch_function(patch_table->addr_io_light_halogan, exchook_io_light_halogan);
util_patch_function(patch_table->addr_io_light_p1_ccfl, exchook_io_light_p1_ccfl);
util_patch_function(patch_table->addr_io_light_p2_ccfl, exchook_io_light_p2_ccfl);
util_patch_function(patch_table->addr_io_input, exchook_io_input);
util_patch_function(patch_table->addr_io_coin_input, exchook_io_coin_input);
util_patch_function(patch_table->addr_io_coin_input_2, exchook_io_coin_input_2);
util_patch_function(patch_table->addr_io_coin_counter_2, exchook_io_coin_counter_2);
util_patch_function(patch_table->addr_io_check, exchook_io_check);
util_patch_function(patch_table->addr_io_light_all, exchook_io_light_all);
util_patch_function(patch_table->addr_io_light_neon, exchook_io_light_neon);
util_patch_function(
patch_table->addr_io_light_halogan, exchook_io_light_halogan);
util_patch_function(
patch_table->addr_io_light_p1_ccfl, exchook_io_light_p1_ccfl);
util_patch_function(
patch_table->addr_io_light_p2_ccfl, exchook_io_light_p2_ccfl);
util_patch_function(patch_table->addr_io_input, exchook_io_input);
util_patch_function(patch_table->addr_io_coin_input, exchook_io_coin_input);
util_patch_function(
patch_table->addr_io_coin_input_2, exchook_io_coin_input_2);
util_patch_function(
patch_table->addr_io_coin_counter_2, exchook_io_coin_counter_2);
exchook_io_game_input_stat = ((uint32_t*) patch_table->addr_io_game_input_stat);
exchook_io_game_input_down = ((uint32_t*) patch_table->addr_io_game_input_down);
exchook_io_game_input_up = ((uint32_t*) patch_table->addr_io_game_input_up);
exchook_io_game_input_stat =
((uint32_t *) patch_table->addr_io_game_input_stat);
exchook_io_game_input_down =
((uint32_t *) patch_table->addr_io_game_input_down);
exchook_io_game_input_up = ((uint32_t *) patch_table->addr_io_game_input_up);
/* there is an io init method but obviously requires another address to be
hooked...just init our backend here */
if (!exchook_piuio_api.open()) {
log_error("Opening io failed");
return;
}
/* there is an io init method but obviously requires another address to be
hooked...just init our backend here */
if (!exchook_piuio_api.open()) {
log_error("Opening io failed");
return;
}
log_info("Initialized");
log_info("Initialized");
}
void exchook_io_shutdown(void)
{
}
/* check? why can't you just call it get_fucking_inputs... */
static uint16_t exchook_io_check(void* obj)
static uint16_t exchook_io_check(void *obj)
{
struct ptapi_io_piuio_pad_inputs p1_pad_in;
struct ptapi_io_piuio_pad_inputs p2_pad_in;
struct ptapi_io_piuio_pad_inputs p1_pad_in;
struct ptapi_io_piuio_pad_inputs p2_pad_in;
/* Sensor states are expected to be returned using the object */
struct exchook_io_sensores* sensores_p1 =
(struct exchook_io_sensores*) obj;
struct exchook_io_sensores* sensores_p2 =
(struct exchook_io_sensores*) (((uint32_t*) obj) + 1);
/* Sensor states are expected to be returned using the object */
struct exchook_io_sensores *sensores_p1 = (struct exchook_io_sensores *) obj;
struct exchook_io_sensores *sensores_p2 =
(struct exchook_io_sensores *) (((uint32_t *) obj) + 1);
/* execute polling here */
/* execute polling here */
/* might delay output for a frame but whatever */
if (!exchook_piuio_api.send()) {
log_error("Piuio send failed");
}
/* might delay output for a frame but whatever */
if (!exchook_piuio_api.send()) {
log_error("Piuio send failed");
}
if (!exchook_piuio_api.recv()) {
log_error("Piuio receive failed");
}
if (!exchook_piuio_api.recv()) {
log_error("Piuio receive failed");
}
/* MK5 inputs state reset */
exchook_io_sensores_p1.lu = 0;
exchook_io_sensores_p1.ru = 0;
exchook_io_sensores_p1.cn = 0;
exchook_io_sensores_p1.ld = 0;
exchook_io_sensores_p1.rd = 0;
/* MK5 inputs state reset */
exchook_io_sensores_p1.lu = 0;
exchook_io_sensores_p1.ru = 0;
exchook_io_sensores_p1.cn = 0;
exchook_io_sensores_p1.ld = 0;
exchook_io_sensores_p1.rd = 0;
exchook_io_sensores_p2.lu = 0;
exchook_io_sensores_p2.ru = 0;
exchook_io_sensores_p2.cn = 0;
exchook_io_sensores_p2.ld = 0;
exchook_io_sensores_p2.rd = 0;
exchook_io_sensores_p2.lu = 0;
exchook_io_sensores_p2.ru = 0;
exchook_io_sensores_p2.cn = 0;
exchook_io_sensores_p2.ld = 0;
exchook_io_sensores_p2.rd = 0;
// State reset
memset(&p1_pad_in, 0, sizeof(struct ptapi_io_piuio_pad_inputs));
memset(&p2_pad_in, 0, sizeof(struct ptapi_io_piuio_pad_inputs));
// State reset
memset(&p1_pad_in, 0, sizeof(struct ptapi_io_piuio_pad_inputs));
memset(&p2_pad_in, 0, sizeof(struct ptapi_io_piuio_pad_inputs));
/* cycle all sensores */
for (uint8_t i = 0; i < 4; i++) {
exchook_piuio_api.get_input_pad(0, i, &p1_pad_in);
exchook_piuio_api.get_input_pad(1, i, &p2_pad_in);
/* cycle all sensores */
for (uint8_t i = 0; i < 4; i++) {
exchook_piuio_api.get_input_pad(0, i, &p1_pad_in);
exchook_piuio_api.get_input_pad(1, i, &p2_pad_in);
/* process inputs */
/* Player 1 */
if (p1_pad_in.lu) {
exchook_io_sensores_p1.lu |= (1 << exchook_io_sensor_mappings[i]);
}
if (p1_pad_in.ru) {
exchook_io_sensores_p1.ru |= (1 << exchook_io_sensor_mappings[i]);
}
if (p1_pad_in.cn) {
exchook_io_sensores_p1.cn |= (1 << exchook_io_sensor_mappings[i]);
}
if (p1_pad_in.ld) {
exchook_io_sensores_p1.ld |= (1 << exchook_io_sensor_mappings[i]);
}
if (p1_pad_in.rd) {
exchook_io_sensores_p1.rd |= (1 << exchook_io_sensor_mappings[i]);
}
/* Player 2 */
if (p2_pad_in.lu) {
exchook_io_sensores_p2.lu |= (1 << exchook_io_sensor_mappings[i]);
}
if (p2_pad_in.ru) {
exchook_io_sensores_p2.ru |= (1 << exchook_io_sensor_mappings[i]);
}
if (p2_pad_in.cn) {
exchook_io_sensores_p2.cn |= (1 << exchook_io_sensor_mappings[i]);
}
if (p2_pad_in.ld) {
exchook_io_sensores_p2.ld |= (1 << exchook_io_sensor_mappings[i]);
}
if (p2_pad_in.rd) {
exchook_io_sensores_p2.rd |= (1 << exchook_io_sensor_mappings[i]);
}
}
memcpy(sensores_p1, &exchook_io_sensores_p1, sizeof(exchook_io_sensores_p1));
memcpy(sensores_p2, &exchook_io_sensores_p2, sizeof(exchook_io_sensores_p2));
return 0;
}
static int32_t exchook_io_light_all(void* obj, uint8_t on)
{
if (on) {
memset(&exchook_io_out_pad_p1, 1, sizeof(exchook_io_out_pad_p1));
memset(&exchook_io_out_pad_p2, 1, sizeof(exchook_io_out_pad_p2));
memset(&exchook_io_out_cab, 1, sizeof(exchook_io_out_cab));
} else {
memset(&exchook_io_out_pad_p1, 0, sizeof(exchook_io_out_pad_p1));
memset(&exchook_io_out_pad_p2, 0, sizeof(exchook_io_out_pad_p2));
memset(&exchook_io_out_cab, 0, sizeof(exchook_io_out_cab));
}
exchook_piuio_api.set_output_pad(0, &exchook_io_out_pad_p1);
exchook_piuio_api.set_output_pad(1, &exchook_io_out_pad_p2);
exchook_piuio_api.set_output_cab(&exchook_io_out_cab);
return 0;
}
static int32_t exchook_io_light_neon(void* obj, uint8_t on)
{
if (on) {
exchook_io_out_cab.bass = true;
} else {
exchook_io_out_cab.bass = false;
}
exchook_piuio_api.set_output_cab(&exchook_io_out_cab);
return 0;
}
static int32_t exchook_io_light_halogan(void* obj, uint8_t on, uint16_t light_id)
{
if (light_id & 0x0400) {
exchook_io_out_cab.halo_l1 = on;
}
if (light_id & 0x0200) {
exchook_io_out_cab.halo_l2 = on;
}
if (light_id & 0x0100) {
exchook_io_out_cab.halo_r1 = on;
}
if (light_id & 0x0080) {
exchook_io_out_cab.halo_r2 = on;
}
exchook_piuio_api.set_output_cab(&exchook_io_out_cab);
return 0;
}
static int32_t exchook_io_light_p1_ccfl(void* obj, uint8_t on, uint16_t cmd)
{
if (cmd & 0x0004) {
exchook_io_out_pad_p1.lu = on;
}
if (cmd & 0x0008) {
exchook_io_out_pad_p1.ru = on;
}
if (cmd & 0x0010) {
exchook_io_out_pad_p1.cn = on;
}
if (cmd & 0x0020) {
exchook_io_out_pad_p1.ld = on;
}
if (cmd & 0x040) {
exchook_io_out_pad_p1.rd = on;
}
return 0;
}
static int32_t exchook_io_light_p2_ccfl(void* obj, uint8_t on, uint16_t cmd)
{
if (cmd & 0x0004) {
exchook_io_out_pad_p2.lu = on;
}
if (cmd & 0x0008) {
exchook_io_out_pad_p2.ru = on;
}
if (cmd & 0x0010) {
exchook_io_out_pad_p2.cn = on;
}
if (cmd & 0x0020) {
exchook_io_out_pad_p2.ld = on;
}
if (cmd & 0x040) {
exchook_io_out_pad_p2.rd = on;
}
return 0;
}
static int32_t exchook_io_input(void* obj)
{
uint32_t stat;
uint32_t stat_down;
uint32_t stat_up;
struct ptapi_io_piuio_sys_inputs sys_in;
memset(&sys_in, 0, sizeof(struct ptapi_io_piuio_sys_inputs));
exchook_piuio_api.get_input_sys(&sys_in);
/* For game loaders and stuff */
if (exchook_io_exit_on_service_test) {
if (sys_in.test && sys_in.service) {
log_info("Exit on service + test enabled and hit, bye");
exit(0);
}
}
/* process final input states for the game as well as service, test, clear
and coin which can't be handled in the check function */
stat = 0;
stat_down = 0;
stat_up = 0;
/* process inputs */
/* Player 1 */
if (exchook_io_sensores_p1.lu) {
stat |= GI_P1_7;
if (p1_pad_in.lu) {
exchook_io_sensores_p1.lu |= (1 << exchook_io_sensor_mappings[i]);
}
if (exchook_io_sensores_p1.ru) {
stat |= GI_P1_9;
if (p1_pad_in.ru) {
exchook_io_sensores_p1.ru |= (1 << exchook_io_sensor_mappings[i]);
}
if (exchook_io_sensores_p1.cn) {
stat |= GI_P1_5;
if (p1_pad_in.cn) {
exchook_io_sensores_p1.cn |= (1 << exchook_io_sensor_mappings[i]);
}
if (exchook_io_sensores_p1.ld) {
stat |= GI_P1_1;
if (p1_pad_in.ld) {
exchook_io_sensores_p1.ld |= (1 << exchook_io_sensor_mappings[i]);
}
if (exchook_io_sensores_p1.rd) {
stat |= GI_P1_3;
if (p1_pad_in.rd) {
exchook_io_sensores_p1.rd |= (1 << exchook_io_sensor_mappings[i]);
}
/* Player 2 */
if (exchook_io_sensores_p2.lu) {
stat |= GI_P2_7;
/* Player 2 */
if (p2_pad_in.lu) {
exchook_io_sensores_p2.lu |= (1 << exchook_io_sensor_mappings[i]);
}
if (exchook_io_sensores_p2.ru) {
stat |= GI_P2_9;
if (p2_pad_in.ru) {
exchook_io_sensores_p2.ru |= (1 << exchook_io_sensor_mappings[i]);
}
if (exchook_io_sensores_p2.cn) {
stat |= GI_P2_5;
if (p2_pad_in.cn) {
exchook_io_sensores_p2.cn |= (1 << exchook_io_sensor_mappings[i]);
}
if (exchook_io_sensores_p2.ld) {
stat |= GI_P2_1;
if (p2_pad_in.ld) {
exchook_io_sensores_p2.ld |= (1 << exchook_io_sensor_mappings[i]);
}
if (exchook_io_sensores_p2.rd) {
stat |= GI_P2_3;
if (p2_pad_in.rd) {
exchook_io_sensores_p2.rd |= (1 << exchook_io_sensor_mappings[i]);
}
}
/* Sys */
if (sys_in.test) {
stat |= GI_TEST;
}
memcpy(sensores_p1, &exchook_io_sensores_p1, sizeof(exchook_io_sensores_p1));
memcpy(sensores_p2, &exchook_io_sensores_p2, sizeof(exchook_io_sensores_p2));
if (sys_in.service) {
stat |= GI_SERVICE;
}
/* Taken from source but doesn't seem to work (on some versions?) */
if (sys_in.clear) {
stat |= GI_CLEAR;
}
if (sys_in.coin) {
stat |= GI_COIN;
}
if (sys_in.coin2) {
stat |= GI_COIN2;
}
/* iterate bits for up and down events */
for (uint8_t i = 0; i < 32; i++) {
if (!(exchook_io_game_input_stat_prev & (1 << i)) &&
(stat & (1 << i))) {
/* New push down */
stat_down |= (1 << i);
} else if ((exchook_io_game_input_stat_prev & (1 << i)) &&
!(stat & (1 << i))) {
/* New release */
stat_up |= (1 << i);
}
}
/* Extremely bad IO subsystem design */
*exchook_io_game_input_stat |= stat;
*exchook_io_game_input_down |= stat_down;
*exchook_io_game_input_up = stat_up;
/* swap for next iterateion */
exchook_io_game_input_stat_prev = *exchook_io_game_input_stat;
/* Welp, the game expects us to do output setting if a button is pressed
here...fuck that mess. Merge (i.e. |= not =) with other states set
by the game */
memset(&exchook_io_out_pad_press_p1, 0, sizeof(exchook_io_out_pad_press_p1));
memset(&exchook_io_out_pad_press_p2, 0, sizeof(exchook_io_out_pad_press_p2));
/* Player 1 */
exchook_io_out_pad_press_p1.lu |= exchook_io_sensores_p1.lu;
exchook_io_out_pad_press_p1.ru |= exchook_io_sensores_p1.ru;
exchook_io_out_pad_press_p1.cn |= exchook_io_sensores_p1.cn;
exchook_io_out_pad_press_p1.ld |= exchook_io_sensores_p1.ld;
exchook_io_out_pad_press_p1.rd |= exchook_io_sensores_p1.rd;
/* Player 2 */
exchook_io_out_pad_press_p2.lu |= exchook_io_sensores_p2.lu;
exchook_io_out_pad_press_p2.ru |= exchook_io_sensores_p2.ru;
exchook_io_out_pad_press_p2.cn |= exchook_io_sensores_p2.cn;
exchook_io_out_pad_press_p2.ld |= exchook_io_sensores_p2.ld;
exchook_io_out_pad_press_p2.rd |= exchook_io_sensores_p2.rd;
/* merge */
/* Player 1 */
exchook_io_out_pad_press_p1.lu |= exchook_io_out_pad_p1.lu;
exchook_io_out_pad_press_p1.ru |= exchook_io_out_pad_p1.ru;
exchook_io_out_pad_press_p1.cn |= exchook_io_out_pad_p1.cn;
exchook_io_out_pad_press_p1.ld |= exchook_io_out_pad_p1.ld;
exchook_io_out_pad_press_p1.rd |= exchook_io_out_pad_p1.rd;
/* Player 2 */
exchook_io_out_pad_press_p2.lu |= exchook_io_out_pad_p2.lu;
exchook_io_out_pad_press_p2.ru |= exchook_io_out_pad_p2.ru;
exchook_io_out_pad_press_p2.cn |= exchook_io_out_pad_p2.cn;
exchook_io_out_pad_press_p2.ld |= exchook_io_out_pad_p2.ld;
exchook_io_out_pad_press_p2.rd |= exchook_io_out_pad_p2.rd;
exchook_piuio_api.set_output_pad(0, &exchook_io_out_pad_press_p1);
exchook_piuio_api.set_output_pad(1, &exchook_io_out_pad_press_p2);
return 0;
return 0;
}
static int32_t exchook_io_coin_input(void* obj)
static int32_t exchook_io_light_all(void *obj, uint8_t on)
{
/* Stub */
if (on) {
memset(&exchook_io_out_pad_p1, 1, sizeof(exchook_io_out_pad_p1));
memset(&exchook_io_out_pad_p2, 1, sizeof(exchook_io_out_pad_p2));
memset(&exchook_io_out_cab, 1, sizeof(exchook_io_out_cab));
} else {
memset(&exchook_io_out_pad_p1, 0, sizeof(exchook_io_out_pad_p1));
memset(&exchook_io_out_pad_p2, 0, sizeof(exchook_io_out_pad_p2));
memset(&exchook_io_out_cab, 0, sizeof(exchook_io_out_cab));
}
return 0;
exchook_piuio_api.set_output_pad(0, &exchook_io_out_pad_p1);
exchook_piuio_api.set_output_pad(1, &exchook_io_out_pad_p2);
exchook_piuio_api.set_output_cab(&exchook_io_out_cab);
return 0;
}
static int32_t exchook_io_coin_input_2(void* obj)
static int32_t exchook_io_light_neon(void *obj, uint8_t on)
{
/* Stub */
if (on) {
exchook_io_out_cab.bass = true;
} else {
exchook_io_out_cab.bass = false;
}
return 0;
exchook_piuio_api.set_output_cab(&exchook_io_out_cab);
return 0;
}
static int32_t exchook_io_coin_counter_2(void* obj)
static int32_t
exchook_io_light_halogan(void *obj, uint8_t on, uint16_t light_id)
{
/* Stub */
if (light_id & 0x0400) {
exchook_io_out_cab.halo_l1 = on;
}
return 0;
if (light_id & 0x0200) {
exchook_io_out_cab.halo_l2 = on;
}
if (light_id & 0x0100) {
exchook_io_out_cab.halo_r1 = on;
}
if (light_id & 0x0080) {
exchook_io_out_cab.halo_r2 = on;
}
exchook_piuio_api.set_output_cab(&exchook_io_out_cab);
return 0;
}
static int32_t exchook_io_light_p1_ccfl(void *obj, uint8_t on, uint16_t cmd)
{
if (cmd & 0x0004) {
exchook_io_out_pad_p1.lu = on;
}
if (cmd & 0x0008) {
exchook_io_out_pad_p1.ru = on;
}
if (cmd & 0x0010) {
exchook_io_out_pad_p1.cn = on;
}
if (cmd & 0x0020) {
exchook_io_out_pad_p1.ld = on;
}
if (cmd & 0x040) {
exchook_io_out_pad_p1.rd = on;
}
return 0;
}
static int32_t exchook_io_light_p2_ccfl(void *obj, uint8_t on, uint16_t cmd)
{
if (cmd & 0x0004) {
exchook_io_out_pad_p2.lu = on;
}
if (cmd & 0x0008) {
exchook_io_out_pad_p2.ru = on;
}
if (cmd & 0x0010) {
exchook_io_out_pad_p2.cn = on;
}
if (cmd & 0x0020) {
exchook_io_out_pad_p2.ld = on;
}
if (cmd & 0x040) {
exchook_io_out_pad_p2.rd = on;
}
return 0;
}
static int32_t exchook_io_input(void *obj)
{
uint32_t stat;
uint32_t stat_down;
uint32_t stat_up;
struct ptapi_io_piuio_sys_inputs sys_in;
memset(&sys_in, 0, sizeof(struct ptapi_io_piuio_sys_inputs));
exchook_piuio_api.get_input_sys(&sys_in);
/* For game loaders and stuff */
if (exchook_io_exit_on_service_test) {
if (sys_in.test && sys_in.service) {
log_info("Exit on service + test enabled and hit, bye");
exit(0);
}
}
/* process final input states for the game as well as service, test, clear
and coin which can't be handled in the check function */
stat = 0;
stat_down = 0;
stat_up = 0;
/* Player 1 */
if (exchook_io_sensores_p1.lu) {
stat |= GI_P1_7;
}
if (exchook_io_sensores_p1.ru) {
stat |= GI_P1_9;
}
if (exchook_io_sensores_p1.cn) {
stat |= GI_P1_5;
}
if (exchook_io_sensores_p1.ld) {
stat |= GI_P1_1;
}
if (exchook_io_sensores_p1.rd) {
stat |= GI_P1_3;
}
/* Player 2 */
if (exchook_io_sensores_p2.lu) {
stat |= GI_P2_7;
}
if (exchook_io_sensores_p2.ru) {
stat |= GI_P2_9;
}
if (exchook_io_sensores_p2.cn) {
stat |= GI_P2_5;
}
if (exchook_io_sensores_p2.ld) {
stat |= GI_P2_1;
}
if (exchook_io_sensores_p2.rd) {
stat |= GI_P2_3;
}
/* Sys */
if (sys_in.test) {
stat |= GI_TEST;
}
if (sys_in.service) {
stat |= GI_SERVICE;
}
/* Taken from source but doesn't seem to work (on some versions?) */
if (sys_in.clear) {
stat |= GI_CLEAR;
}
if (sys_in.coin) {
stat |= GI_COIN;
}
if (sys_in.coin2) {
stat |= GI_COIN2;
}
/* iterate bits for up and down events */
for (uint8_t i = 0; i < 32; i++) {
if (!(exchook_io_game_input_stat_prev & (1 << i)) && (stat & (1 << i))) {
/* New push down */
stat_down |= (1 << i);
} else if (
(exchook_io_game_input_stat_prev & (1 << i)) && !(stat & (1 << i))) {
/* New release */
stat_up |= (1 << i);
}
}
/* Extremely bad IO subsystem design */
*exchook_io_game_input_stat |= stat;
*exchook_io_game_input_down |= stat_down;
*exchook_io_game_input_up = stat_up;
/* swap for next iterateion */
exchook_io_game_input_stat_prev = *exchook_io_game_input_stat;
/* Welp, the game expects us to do output setting if a button is pressed
here...fuck that mess. Merge (i.e. |= not =) with other states set
by the game */
memset(&exchook_io_out_pad_press_p1, 0, sizeof(exchook_io_out_pad_press_p1));
memset(&exchook_io_out_pad_press_p2, 0, sizeof(exchook_io_out_pad_press_p2));
/* Player 1 */
exchook_io_out_pad_press_p1.lu |= exchook_io_sensores_p1.lu;
exchook_io_out_pad_press_p1.ru |= exchook_io_sensores_p1.ru;
exchook_io_out_pad_press_p1.cn |= exchook_io_sensores_p1.cn;
exchook_io_out_pad_press_p1.ld |= exchook_io_sensores_p1.ld;
exchook_io_out_pad_press_p1.rd |= exchook_io_sensores_p1.rd;
/* Player 2 */
exchook_io_out_pad_press_p2.lu |= exchook_io_sensores_p2.lu;
exchook_io_out_pad_press_p2.ru |= exchook_io_sensores_p2.ru;
exchook_io_out_pad_press_p2.cn |= exchook_io_sensores_p2.cn;
exchook_io_out_pad_press_p2.ld |= exchook_io_sensores_p2.ld;
exchook_io_out_pad_press_p2.rd |= exchook_io_sensores_p2.rd;
/* merge */
/* Player 1 */
exchook_io_out_pad_press_p1.lu |= exchook_io_out_pad_p1.lu;
exchook_io_out_pad_press_p1.ru |= exchook_io_out_pad_p1.ru;
exchook_io_out_pad_press_p1.cn |= exchook_io_out_pad_p1.cn;
exchook_io_out_pad_press_p1.ld |= exchook_io_out_pad_p1.ld;
exchook_io_out_pad_press_p1.rd |= exchook_io_out_pad_p1.rd;
/* Player 2 */
exchook_io_out_pad_press_p2.lu |= exchook_io_out_pad_p2.lu;
exchook_io_out_pad_press_p2.ru |= exchook_io_out_pad_p2.ru;
exchook_io_out_pad_press_p2.cn |= exchook_io_out_pad_p2.cn;
exchook_io_out_pad_press_p2.ld |= exchook_io_out_pad_p2.ld;
exchook_io_out_pad_press_p2.rd |= exchook_io_out_pad_p2.rd;
exchook_piuio_api.set_output_pad(0, &exchook_io_out_pad_press_p1);
exchook_piuio_api.set_output_pad(1, &exchook_io_out_pad_press_p2);
return 0;
}
static int32_t exchook_io_coin_input(void *obj)
{
/* Stub */
return 0;
}
static int32_t exchook_io_coin_input_2(void *obj)
{
/* Stub */
return 0;
}
static int32_t exchook_io_coin_counter_2(void *obj)
{
/* Stub */
return 0;
}
+3 -1
View File
@@ -15,7 +15,9 @@
* @param piuio_lib_path Path to piuio lib to use for emulation
* @parma exit_on_service_test Exit the game when pressing service + test
*/
void exchook_io_init(const struct exchook_mempatch_table* patch_table, const char* piuio_lib_path,
void exchook_io_init(
const struct exchook_mempatch_table *patch_table,
const char *piuio_lib_path,
bool exit_on_service_test);
/**
+21 -21
View File
@@ -2,42 +2,42 @@
#include <stdlib.h>
#include "sec/lockchip/lockchip.h"
#include "sec/lockchip/lockchip-defs.h"
#include "sec/lockchip/lockchip.h"
#include "util/log.h"
#include "util/patch.h"
#include "lockchip.h"
static void exchook_lockchip_dec_chunk(uint8_t len, const uint8_t* src,
uint8_t* dest);
static void
exchook_lockchip_dec_chunk(uint8_t len, const uint8_t *src, uint8_t *dest);
void exchook_lockchip_init(const struct exchook_mempatch_table* patch_table)
void exchook_lockchip_init(const struct exchook_mempatch_table *patch_table)
{
sec_lockchip_init(
sec_lockchip_defs_transforms[SEC_LOCK_CHIP_DEFS_GAME_EXCEED]);
sec_lockchip_init(
sec_lockchip_defs_transforms[SEC_LOCK_CHIP_DEFS_GAME_EXCEED]);
/* Hook lockchip */
util_patch_function(patch_table->addr_lockchip_dec_chunk, exchook_lockchip_dec_chunk);
/* Hook lockchip */
util_patch_function(
patch_table->addr_lockchip_dec_chunk, exchook_lockchip_dec_chunk);
log_info("Initialized");
log_info("Initialized");
}
static void exchook_lockchip_dec_chunk(uint8_t len, const uint8_t* src,
uint8_t* dest)
static void
exchook_lockchip_dec_chunk(uint8_t len, const uint8_t *src, uint8_t *dest)
{
sec_lockchip_start();
sec_lockchip_start();
uint8_t last_res = sec_lockchip_step(src[0] ^ 0xFF);
uint8_t last_res = sec_lockchip_step(src[0] ^ 0xFF);
for (size_t i = 1; i < len; i++)
{
uint8_t result = sec_lockchip_step(src[i] ^ 0xFF);
dest[i - 1] = (uint8_t)((last_res >> 3) ^ (result << 5));
last_res = result;
}
for (size_t i = 1; i < len; i++) {
uint8_t result = sec_lockchip_step(src[i] ^ 0xFF);
dest[i - 1] = (uint8_t)((last_res >> 3) ^ (result << 5));
last_res = result;
}
uint8_t last_byte = sec_lockchip_step(0);
dest[len - 1] = (uint8_t)((last_res >> 3) ^ (last_byte << 5));
uint8_t last_byte = sec_lockchip_step(0);
dest[len - 1] = (uint8_t)((last_res >> 3) ^ (last_byte << 5));
}
+1 -1
View File
@@ -14,6 +14,6 @@
*
* @param patch_table Patch table with memory addresses
*/
void exchook_lockchip_init(const struct exchook_mempatch_table* patch_table);
void exchook_lockchip_init(const struct exchook_mempatch_table *patch_table);
#endif
+153 -133
View File
@@ -30,225 +30,245 @@
#include "mempatch.h"
#include "options.h"
static void exchook_bootstrapping(int argc, char** argv, struct exchook_options* options, char** game_data_path)
static void exchook_bootstrapping(
int argc,
char **argv,
struct exchook_options *options,
char **game_data_path)
{
log_assert(argc >= 0);
log_assert(argv);
log_assert(options);
log_assert(game_data_path);
log_assert(argc >= 0);
log_assert(argv);
log_assert(options);
log_assert(game_data_path);
if (hook_core_piu_block_non_piu_process_recursion(argc, argv)) {
return;
}
if (hook_core_piu_block_non_piu_process_recursion(argc, argv)) {
return;
}
hook_core_piu_log_init(argc, argv);
hook_core_piu_log_init(argc, argv);
if (!exchook_options_init(argc, argv, options)) {
exit(0);
}
if (!exchook_options_init(argc, argv, options)) {
exit(0);
}
hook_core_piu_log_info(argc, argv);
hook_core_piu_log_info(argc, argv);
*game_data_path = hook_core_piu_utils_get_and_verify_game_data_path(argc, argv);
*game_data_path =
hook_core_piu_utils_get_and_verify_game_data_path(argc, argv);
hook_core_piu_utils_verify_root_user();
hook_core_piu_utils_verify_root_user();
log_info("Initializing, piu game data path: %s", *game_data_path);
log_info("Initializing, piu game data path: %s", *game_data_path);
}
static void exchook_game_version_mempatch_table_init(
struct exchook_options* options,
const struct exchook_mempatch_table** patch_table)
struct exchook_options *options,
const struct exchook_mempatch_table **patch_table)
{
log_assert(options);
log_assert(patch_table);
log_assert(options);
log_assert(patch_table);
if (!options->game.version) {
log_die("No game version specified");
} else {
log_info("Game version configured: %s", options->game.version);
}
if (!options->game.version) {
log_die("No game version specified");
} else {
log_info("Game version configured: %s", options->game.version);
}
*patch_table = exchook_mempatch_get_table(options->game.version);
*patch_table = exchook_mempatch_get_table(options->game.version);
if (*patch_table == NULL) {
log_die("Unsupported game version %s", options->game.version);
}
if (*patch_table == NULL) {
log_die("Unsupported game version %s", options->game.version);
}
}
static void exchook_patch_fs_init(struct exchook_options* options)
static void exchook_patch_fs_init(struct exchook_options *options)
{
log_assert(options);
log_assert(options);
patch_hook_mon_init(
options->patch.hook_mon.io,
options->patch.hook_mon.file,
options->patch.hook_mon.fs,
options->patch.hook_mon.usb,
options->patch.hook_mon.open);
patch_hook_mon_init(
options->patch.hook_mon.io,
options->patch.hook_mon.file,
options->patch.hook_mon.fs,
options->patch.hook_mon.usb,
options->patch.hook_mon.open);
patch_redir_init();
patch_redir_init();
}
static void exchook_fs_redir_settings(struct exchook_options* options)
static void exchook_fs_redir_settings(struct exchook_options *options)
{
log_assert(options);
log_assert(options);
if (options->game.settings) {
if (!util_fs_path_exists(options->game.settings)) {
log_info("Settings path %s does not exist, creating", options->game.settings);
if (options->game.settings) {
if (!util_fs_path_exists(options->game.settings)) {
log_info(
"Settings path %s does not exist, creating", options->game.settings);
if (!util_fs_mkdir(options->game.settings)) {
log_error("Creating directory %s failed", options->game.settings);
}
}
char* abs_path = util_fs_get_abs_path(options->game.settings);
cnh_redir_add("/SETTINGS", abs_path);
free(abs_path);
} else {
log_warn("No settings path specified");
if (!util_fs_mkdir(options->game.settings)) {
log_error("Creating directory %s failed", options->game.settings);
}
}
char *abs_path = util_fs_get_abs_path(options->game.settings);
cnh_redir_add("/SETTINGS", abs_path);
free(abs_path);
} else {
log_warn("No settings path specified");
}
}
static void exchook_fs_redir_usb()
{
/* Needed on newer kernels */
cnh_redir_add("/proc/bus/usb/devices", "/sys/kernel/debug/usb/devices");
/* Needed on newer kernels */
cnh_redir_add("/proc/bus/usb/devices", "/sys/kernel/debug/usb/devices");
}
static void exchook_patch_gfx_init(struct exchook_options* options)
static void exchook_patch_gfx_init(struct exchook_options *options)
{
log_assert(options);
log_assert(options);
patch_gfx_init();
patch_gfx_init();
if (options->patch.gfx.windowed) {
patch_gfx_force_window_mode();
}
if (options->patch.gfx.windowed) {
patch_gfx_force_window_mode();
}
}
static void exchook_patch_main_loop_init(struct exchook_options* options)
static void exchook_patch_main_loop_init(struct exchook_options *options)
{
log_assert(options);
log_assert(options);
patch_main_loop_init(true, options->patch.main_loop.disable_built_in_inputs, false);
patch_main_loop_init(
true, options->patch.main_loop.disable_built_in_inputs, false);
if (options->patch.main_loop.x11_input_handler_api_lib) {
char* abs_path_x11_input_hook_lib = util_fs_get_abs_path(options->patch.main_loop.x11_input_handler_api_lib);
if (options->patch.main_loop.x11_input_handler_api_lib) {
char *abs_path_x11_input_hook_lib = util_fs_get_abs_path(
options->patch.main_loop.x11_input_handler_api_lib);
patch_main_loop_add_x11_input_handler(abs_path_x11_input_hook_lib);
free(abs_path_x11_input_hook_lib);
}
patch_main_loop_add_x11_input_handler(abs_path_x11_input_hook_lib);
free(abs_path_x11_input_hook_lib);
}
}
static void exchook_patch_sound_init(struct exchook_options* options, const struct exchook_mempatch_table* patch_table)
static void exchook_patch_sound_init(
struct exchook_options *options,
const struct exchook_mempatch_table *patch_table)
{
log_assert(options);
log_assert(patch_table);
log_assert(options);
log_assert(patch_table);
/* exceed crashes with its default device hw:0. use dmix instead */
if (strcmp(options->patch.sound.device, "dmix") != 0) {
log_warn("Game might crash with selected sound device %s, use 'dmix' instead if that happens",
options->patch.sound.device);
}
/* exceed crashes with its default device hw:0. use dmix instead */
if (strcmp(options->patch.sound.device, "dmix") != 0) {
log_warn(
"Game might crash with selected sound device %s, use 'dmix' instead if "
"that happens",
options->patch.sound.device);
}
patch_sound_init(options->patch.sound.device);
patch_asound_fix_init();
patch_sound_init(options->patch.sound.device);
patch_asound_fix_init();
/* return from StopAllEffects to avoid killing the sound thread */
util_patch_write_memory_byte(patch_table->addr_stop_all_effects_return, 0xC3);
/* return from StopAllEffects to avoid killing the sound thread */
util_patch_write_memory_byte(patch_table->addr_stop_all_effects_return, 0xC3);
}
static void exchook_patch_sigsegv_init(struct exchook_options* options)
static void exchook_patch_sigsegv_init(struct exchook_options *options)
{
log_assert(options);
log_assert(options);
patch_sigsegv_init(options->patch.sigsegv.halt_on_segv);
patch_sigsegv_init(options->patch.sigsegv.halt_on_segv);
}
static void exchook_patch_lockchip_init(const struct exchook_mempatch_table* patch_table)
static void
exchook_patch_lockchip_init(const struct exchook_mempatch_table *patch_table)
{
log_assert(patch_table);
log_assert(patch_table);
exchook_lockchip_init(patch_table);
exchook_lockchip_init(patch_table);
}
static void exchook_patch_eeprom_init(struct exchook_options* options, const struct exchook_mempatch_table* patch_table)
static void exchook_patch_eeprom_init(
struct exchook_options *options,
const struct exchook_mempatch_table *patch_table)
{
log_assert(options);
log_assert(patch_table);
log_assert(options);
log_assert(patch_table);
char* eeprom_path;
char *eeprom_path;
if (options->game.settings) {
char* abs_path = util_fs_get_abs_path(options->game.settings);
if (options->game.settings) {
char *abs_path = util_fs_get_abs_path(options->game.settings);
eeprom_path = util_str_merge(abs_path, "/eeprom.bin");
free(abs_path);
} else {
eeprom_path = util_str_dup("/tmp/eeprom.bin");
log_warn("No settings path specified to store eeprom data, defaulting to %s", eeprom_path);
}
eeprom_path = util_str_merge(abs_path, "/eeprom.bin");
free(abs_path);
} else {
eeprom_path = util_str_dup("/tmp/eeprom.bin");
log_warn(
"No settings path specified to store eeprom data, defaulting to %s",
eeprom_path);
}
exchook_eeprom_init(patch_table, eeprom_path);
free(eeprom_path);
exchook_eeprom_init(patch_table, eeprom_path);
free(eeprom_path);
}
static void exchook_patch_piuio_init(struct exchook_options* options, const struct exchook_mempatch_table* patch_table)
static void exchook_patch_piuio_init(
struct exchook_options *options,
const struct exchook_mempatch_table *patch_table)
{
log_assert(options);
log_assert(patch_table);
log_assert(options);
log_assert(patch_table);
if (options->patch.piuio.api_lib) {
char* abs_path_iolib = util_fs_get_abs_path(options->patch.piuio.api_lib);
if (options->patch.piuio.api_lib) {
char *abs_path_iolib = util_fs_get_abs_path(options->patch.piuio.api_lib);
exchook_io_init(patch_table, abs_path_iolib, options->patch.piuio.exit_test_serv);
free(abs_path_iolib);
}
exchook_io_init(
patch_table, abs_path_iolib, options->patch.piuio.exit_test_serv);
free(abs_path_iolib);
}
}
void exchook_constructor(void)
{
/* Nothing here */
/* Nothing here */
}
void exchook_destructor(void)
{
/* Nothing here */
/* Nothing here */
}
void exchook_trap_before_main(int argc, char** argv)
void exchook_trap_before_main(int argc, char **argv)
{
log_assert(argc >= 0);
log_assert(argv);
log_assert(argc >= 0);
log_assert(argv);
char* game_data_path;
struct exchook_options options;
const struct exchook_mempatch_table* mempatch_table;
char *game_data_path;
struct exchook_options options;
const struct exchook_mempatch_table *mempatch_table;
exchook_bootstrapping(argc, argv, &options, &game_data_path);
exchook_game_version_mempatch_table_init(&options, &mempatch_table);
exchook_patch_fs_init(&options);
exchook_fs_redir_settings(&options);
exchook_fs_redir_usb();
exchook_patch_gfx_init(&options);
exchook_patch_main_loop_init(&options);
exchook_patch_sound_init(&options, mempatch_table);
exchook_patch_sigsegv_init(&options);
exchook_patch_lockchip_init(mempatch_table);
exchook_patch_eeprom_init(&options, mempatch_table);
exchook_patch_piuio_init(&options, mempatch_table);
exchook_bootstrapping(argc, argv, &options, &game_data_path);
exchook_game_version_mempatch_table_init(&options, &mempatch_table);
exchook_patch_fs_init(&options);
exchook_fs_redir_settings(&options);
exchook_fs_redir_usb();
exchook_patch_gfx_init(&options);
exchook_patch_main_loop_init(&options);
exchook_patch_sound_init(&options, mempatch_table);
exchook_patch_sigsegv_init(&options);
exchook_patch_lockchip_init(mempatch_table);
exchook_patch_eeprom_init(&options, mempatch_table);
exchook_patch_piuio_init(&options, mempatch_table);
free(game_data_path);
free(game_data_path);
log_info("Hooking finished");
log_info("Hooking finished");
}
void exchook_trap_after_main(void)
{
exchook_io_shutdown();
exchook_io_shutdown();
}
LIB_MAIN_CONSTRUCTOR(exchook_constructor);
+8 -7
View File
@@ -48,15 +48,16 @@ static const struct exchook_mempatch_table _exchook_mempatch_table[] = {
},
};
const struct exchook_mempatch_table* exchook_mempatch_get_table(const char* version)
const struct exchook_mempatch_table *
exchook_mempatch_get_table(const char *version)
{
size_t entries = lengthof(_exchook_mempatch_table);
size_t entries = lengthof(_exchook_mempatch_table);
for (uint32_t i = 0; i < entries; i++) {
if (!strcmp(_exchook_mempatch_table[i].version, version)) {
return &_exchook_mempatch_table[i];
}
for (uint32_t i = 0; i < entries; i++) {
if (!strcmp(_exchook_mempatch_table[i].version, version)) {
return &_exchook_mempatch_table[i];
}
}
return NULL;
return NULL;
}
+20 -19
View File
@@ -4,26 +4,27 @@
#include <stdint.h>
struct exchook_mempatch_table {
const char* version;
uintptr_t addr_eeprom_read;
uintptr_t addr_eeprom_write;
uintptr_t addr_io_check;
uintptr_t addr_io_light_all;
uintptr_t addr_io_light_neon;
uintptr_t addr_io_light_halogan;
uintptr_t addr_io_light_p1_ccfl;
uintptr_t addr_io_light_p2_ccfl;
uintptr_t addr_io_input;
uintptr_t addr_io_coin_input;
uintptr_t addr_io_coin_input_2;
uintptr_t addr_io_coin_counter_2;
uintptr_t addr_io_game_input_stat;
uintptr_t addr_io_game_input_down;
uintptr_t addr_io_game_input_up;
uintptr_t addr_lockchip_dec_chunk;
uintptr_t addr_stop_all_effects_return;
const char *version;
uintptr_t addr_eeprom_read;
uintptr_t addr_eeprom_write;
uintptr_t addr_io_check;
uintptr_t addr_io_light_all;
uintptr_t addr_io_light_neon;
uintptr_t addr_io_light_halogan;
uintptr_t addr_io_light_p1_ccfl;
uintptr_t addr_io_light_p2_ccfl;
uintptr_t addr_io_input;
uintptr_t addr_io_coin_input;
uintptr_t addr_io_coin_input_2;
uintptr_t addr_io_coin_counter_2;
uintptr_t addr_io_game_input_stat;
uintptr_t addr_io_game_input_down;
uintptr_t addr_io_game_input_up;
uintptr_t addr_lockchip_dec_chunk;
uintptr_t addr_stop_all_effects_return;
};
const struct exchook_mempatch_table* exchook_mempatch_get_table(const char* version);
const struct exchook_mempatch_table *
exchook_mempatch_get_table(const char *version);
#endif
+63 -40
View File
@@ -10,12 +10,16 @@
#define EXCHOOK_OPTIONS_STR_PATCH_HOOK_MON_IO "patch.hook_mon.io"
#define EXCHOOK_OPTIONS_STR_PATCH_HOOK_MON_OPEN "patch.hook_mon.open"
#define EXCHOOK_OPTIONS_STR_PATCH_HOOK_MON_USB "patch.hook_mon.usb"
#define EXCHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS "patch.hook_main_loop.disable_built_in_inputs"
#define EXCHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_X11_INPUT_HANDLER "patch_hook_main_loop.x11_input_handler"
#define EXCHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS \
"patch.hook_main_loop.disable_built_in_inputs"
#define EXCHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_X11_INPUT_HANDLER \
"patch_hook_main_loop.x11_input_handler"
#define EXCHOOK_OPTIONS_STR_PATCH_PIUIO_EMU_LIB "patch.piuio.emu_lib"
#define EXCHOOK_OPTIONS_STR_PATCH_PIUIO_EXIT_TEST_SERV "patch.piuio_exit.test_serv"
#define EXCHOOK_OPTIONS_STR_PATCH_PIUIO_EXIT_TEST_SERV \
"patch.piuio_exit.test_serv"
#define EXCHOOK_OPTIONS_STR_PATCH_SOUND_DEVICE "patch.sound.device"
#define EXCHOOK_OPTIONS_STR_PATCH_SIGSEGV_HALT_ON_SEGV "patch.sigsegv.halt_on_segv"
#define EXCHOOK_OPTIONS_STR_PATCH_SIGSEGV_HALT_ON_SEGV \
"patch.sigsegv.halt_on_segv"
#define EXCHOOK_OPTIONS_STR_PATCH_UTIL_LOG_FILE "util.log.file"
#define EXCHOOK_OPTIONS_STR_PATCH_UTIL_LOG_LEVEL "util.log.level"
@@ -29,7 +33,9 @@ static const struct util_options_def exchook_options_def[] = {
},
{
.name = EXCHOOK_OPTIONS_STR_GAME_VERSION,
.description = "Version of the game (format YYYYMMDD). Make sure this matches exactly the version you are"
.description =
"Version of the game (format YYYYMMDD). Make sure this matches "
"exactly the version you are"
" running because the hook lib has to apply memory patches.",
.param = 'v',
.type = UTIL_OPTIONS_TYPE_STR,
@@ -78,22 +84,26 @@ static const struct util_options_def exchook_options_def[] = {
.default_value.b = false,
},
{
.name = EXCHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS,
.description = "Disable the built in keyboard inputs for test (F1), service (F2) and clear (F3)",
.name =
EXCHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS,
.description = "Disable the built in keyboard inputs for test (F1), "
"service (F2) and clear (F3)",
.param = 'k',
.type = UTIL_OPTIONS_TYPE_BOOL,
.default_value.b = false,
},
{
.name = EXCHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_X11_INPUT_HANDLER,
.description = "Path to a library implementing the x11-input-handler api to capture X11 keyboard inputs",
.description = "Path to a library implementing the x11-input-handler "
"api to capture X11 keyboard inputs",
.param = 'q',
.type = UTIL_OPTIONS_TYPE_STR,
.default_value.str = NULL,
},
{
.name = EXCHOOK_OPTIONS_STR_PATCH_PIUIO_EMU_LIB,
.description = "Path to library implementing the piuio api for piuio emulation",
.description =
"Path to library implementing the piuio api for piuio emulation",
.param = 'p',
.type = UTIL_OPTIONS_TYPE_STR,
.default_value.str = NULL,
@@ -144,41 +154,54 @@ static const struct util_options_defs exchook_options_defs = {
.ndefs = lengthof(exchook_options_def)
};
bool exchook_options_init(int argc, char** argv, struct exchook_options* options)
bool exchook_options_init(
int argc, char **argv, struct exchook_options *options)
{
log_assert(argv);
log_assert(options);
log_assert(argv);
log_assert(options);
struct util_options_opts* options_opt;
struct util_options_opts *options_opt;
util_options_init(argc, argv);
options_opt = util_options_get(&exchook_options_defs);
util_options_init(argc, argv);
options_opt = util_options_get(&exchook_options_defs);
if (!options_opt) {
return false;
}
if (!options_opt) {
return false;
}
options->game.settings = util_options_get_str(options_opt, EXCHOOK_OPTIONS_STR_GAME_SETTINGS);
options->game.version = util_options_get_str(options_opt, EXCHOOK_OPTIONS_STR_GAME_VERSION);
options->patch.gfx.windowed = util_options_get_bool(options_opt, EXCHOOK_OPTIONS_STR_PATCH_GFX_WINDOWED);
options->patch.hook_mon.file = util_options_get_bool(options_opt, EXCHOOK_OPTIONS_STR_PATCH_HOOK_MON_FILE);
options->patch.hook_mon.fs = util_options_get_bool(options_opt, EXCHOOK_OPTIONS_STR_PATCH_HOOK_MON_FS);
options->patch.hook_mon.io = util_options_get_bool(options_opt, EXCHOOK_OPTIONS_STR_PATCH_HOOK_MON_IO);
options->patch.hook_mon.open = util_options_get_bool(options_opt, EXCHOOK_OPTIONS_STR_PATCH_HOOK_MON_OPEN);
options->patch.hook_mon.usb = util_options_get_bool(options_opt, EXCHOOK_OPTIONS_STR_PATCH_HOOK_MON_USB);
options->patch.main_loop.disable_built_in_inputs = util_options_get_bool(options_opt,
EXCHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS);
options->patch.main_loop.x11_input_handler_api_lib =
util_options_get_str(options_opt, EXCHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_X11_INPUT_HANDLER);
options->patch.piuio.api_lib = util_options_get_str(options_opt, EXCHOOK_OPTIONS_STR_PATCH_PIUIO_EMU_LIB);
options->patch.piuio.exit_test_serv =
util_options_get_bool(options_opt, EXCHOOK_OPTIONS_STR_PATCH_PIUIO_EXIT_TEST_SERV);
options->patch.sound.device = util_options_get_str(options_opt, EXCHOOK_OPTIONS_STR_PATCH_SOUND_DEVICE);
options->patch.sigsegv.halt_on_segv =
util_options_get_bool(options_opt, EXCHOOK_OPTIONS_STR_PATCH_SIGSEGV_HALT_ON_SEGV);
options->log.file = util_options_get_str(options_opt, EXCHOOK_OPTIONS_STR_PATCH_UTIL_LOG_FILE);
options->log.level =
(enum util_log_level) util_options_get_int(options_opt, EXCHOOK_OPTIONS_STR_PATCH_UTIL_LOG_LEVEL);
options->game.settings =
util_options_get_str(options_opt, EXCHOOK_OPTIONS_STR_GAME_SETTINGS);
options->game.version =
util_options_get_str(options_opt, EXCHOOK_OPTIONS_STR_GAME_VERSION);
options->patch.gfx.windowed = util_options_get_bool(
options_opt, EXCHOOK_OPTIONS_STR_PATCH_GFX_WINDOWED);
options->patch.hook_mon.file = util_options_get_bool(
options_opt, EXCHOOK_OPTIONS_STR_PATCH_HOOK_MON_FILE);
options->patch.hook_mon.fs =
util_options_get_bool(options_opt, EXCHOOK_OPTIONS_STR_PATCH_HOOK_MON_FS);
options->patch.hook_mon.io =
util_options_get_bool(options_opt, EXCHOOK_OPTIONS_STR_PATCH_HOOK_MON_IO);
options->patch.hook_mon.open = util_options_get_bool(
options_opt, EXCHOOK_OPTIONS_STR_PATCH_HOOK_MON_OPEN);
options->patch.hook_mon.usb = util_options_get_bool(
options_opt, EXCHOOK_OPTIONS_STR_PATCH_HOOK_MON_USB);
options->patch.main_loop.disable_built_in_inputs = util_options_get_bool(
options_opt,
EXCHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS);
options->patch.main_loop.x11_input_handler_api_lib = util_options_get_str(
options_opt, EXCHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_X11_INPUT_HANDLER);
options->patch.piuio.api_lib = util_options_get_str(
options_opt, EXCHOOK_OPTIONS_STR_PATCH_PIUIO_EMU_LIB);
options->patch.piuio.exit_test_serv = util_options_get_bool(
options_opt, EXCHOOK_OPTIONS_STR_PATCH_PIUIO_EXIT_TEST_SERV);
options->patch.sound.device =
util_options_get_str(options_opt, EXCHOOK_OPTIONS_STR_PATCH_SOUND_DEVICE);
options->patch.sigsegv.halt_on_segv = util_options_get_bool(
options_opt, EXCHOOK_OPTIONS_STR_PATCH_SIGSEGV_HALT_ON_SEGV);
options->log.file = util_options_get_str(
options_opt, EXCHOOK_OPTIONS_STR_PATCH_UTIL_LOG_FILE);
options->log.level = (enum util_log_level) util_options_get_int(
options_opt, EXCHOOK_OPTIONS_STR_PATCH_UTIL_LOG_LEVEL);
return true;
return true;
}
+36 -35
View File
@@ -7,49 +7,50 @@
#include "util/log.h"
struct exchook_options {
struct game {
const char* settings;
const char* version;
} game;
struct game {
const char *settings;
const char *version;
} game;
struct patch {
struct gfx {
bool windowed;
} gfx;
struct patch {
struct gfx {
bool windowed;
} gfx;
struct hook_mon {
bool file;
bool fs;
bool io;
bool open;
bool usb;
} hook_mon;
struct hook_mon {
bool file;
bool fs;
bool io;
bool open;
bool usb;
} hook_mon;
struct main_loop {
bool disable_built_in_inputs;
const char* x11_input_handler_api_lib;
} main_loop;
struct main_loop {
bool disable_built_in_inputs;
const char *x11_input_handler_api_lib;
} main_loop;
struct piuio {
const char* api_lib;
bool exit_test_serv;
} piuio;
struct piuio {
const char *api_lib;
bool exit_test_serv;
} piuio;
struct sound {
const char* device;
} sound;
struct sound {
const char *device;
} sound;
struct sigsegv {
bool halt_on_segv;
} sigsegv;
} patch;
struct sigsegv {
bool halt_on_segv;
} sigsegv;
} patch;
struct log {
const char* file;
enum util_log_level level;
} log;
struct log {
const char *file;
enum util_log_level level;
} log;
};
bool exchook_options_init(int argc, char** argv, struct exchook_options* options);
bool exchook_options_init(
int argc, char **argv, struct exchook_options *options);
#endif
+125 -112
View File
@@ -17,8 +17,8 @@
#include "hook/patch/hook-mon.h"
#include "hook/patch/main-loop.h"
#include "hook/patch/mounts.h"
#include "hook/patch/piuio.h"
#include "hook/patch/piuio-exit.h"
#include "hook/patch/piuio.h"
#include "hook/patch/redir.h"
#include "hook/patch/sigsegv.h"
#include "hook/patch/sound.h"
@@ -39,204 +39,217 @@ extern const uint8_t _binary_f2hook_hdd_raw_end[];
extern const uint8_t _binary_f2hook_hasp_key_start[];
extern const uint8_t _binary_f2hook_hasp_key_end[];
static void f2hook_bootstrapping(int argc, char** argv, struct f2hook_options* options, char** game_data_path)
static void f2hook_bootstrapping(
int argc,
char **argv,
struct f2hook_options *options,
char **game_data_path)
{
log_assert(argc >= 0);
log_assert(argv);
log_assert(options);
log_assert(game_data_path);
log_assert(argc >= 0);
log_assert(argv);
log_assert(options);
log_assert(game_data_path);
if (hook_core_piu_block_non_piu_process_recursion(argc, argv)) {
return;
}
if (hook_core_piu_block_non_piu_process_recursion(argc, argv)) {
return;
}
hook_core_piu_log_init(argc, argv);
hook_core_piu_log_init(argc, argv);
if (!f2hook_options_init(argc, argv, options)) {
exit(0);
}
if (!f2hook_options_init(argc, argv, options)) {
exit(0);
}
hook_core_piu_log_info(argc, argv);
hook_core_piu_log_info(argc, argv);
*game_data_path = hook_core_piu_utils_get_and_verify_game_data_path(argc, argv);
*game_data_path =
hook_core_piu_utils_get_and_verify_game_data_path(argc, argv);
hook_core_piu_utils_verify_root_user();
hook_core_piu_utils_verify_root_user();
hook_core_piu_utils_fix_locale();
hook_core_piu_utils_fix_locale();
log_info("Initializing, piu game data path: %s", *game_data_path);
log_info("Initializing, piu game data path: %s", *game_data_path);
}
static void f2hook_patch_fs_init(struct f2hook_options* options)
static void f2hook_patch_fs_init(struct f2hook_options *options)
{
log_assert(options);
log_assert(options);
patch_hook_mon_init(
options->patch.hook_mon.io,
options->patch.hook_mon.file,
options->patch.hook_mon.fs,
options->patch.hook_mon.usb,
options->patch.hook_mon.open);
patch_hook_mon_init(
options->patch.hook_mon.io,
options->patch.hook_mon.file,
options->patch.hook_mon.fs,
options->patch.hook_mon.usb,
options->patch.hook_mon.open);
patch_redir_init();
patch_redir_init();
}
static void f2hook_fs_redir_settings(struct f2hook_options* options)
static void f2hook_fs_redir_settings(struct f2hook_options *options)
{
log_assert(options);
log_assert(options);
if (options->game.settings) {
if (!util_fs_path_exists(options->game.settings)) {
log_info("Settings path %s does not exist, creating", options->game.settings);
if (options->game.settings) {
if (!util_fs_path_exists(options->game.settings)) {
log_info(
"Settings path %s does not exist, creating", options->game.settings);
if (!util_fs_mkdir(options->game.settings)) {
log_error("Creating directory %s failed", options->game.settings);
}
}
char* abs_path = util_fs_get_abs_path(options->game.settings);
cnh_redir_add("/SETTINGS", abs_path);
free(abs_path);
} else {
log_warn("No settings path specified");
if (!util_fs_mkdir(options->game.settings)) {
log_error("Creating directory %s failed", options->game.settings);
}
}
char *abs_path = util_fs_get_abs_path(options->game.settings);
cnh_redir_add("/SETTINGS", abs_path);
free(abs_path);
} else {
log_warn("No settings path specified");
}
}
static void f2hook_fs_redir_usb()
{
/* Needed on newer kernels */
cnh_redir_add("/proc/bus/usb/devices", "/sys/kernel/debug/usb/devices");
patch_usbfs_init();
/* Needed on newer kernels */
cnh_redir_add("/proc/bus/usb/devices", "/sys/kernel/debug/usb/devices");
patch_usbfs_init();
}
static void f2hook_fs_redirs_init(struct f2hook_options* options, const char* game_data_path)
static void f2hook_fs_redirs_init(
struct f2hook_options *options, const char *game_data_path)
{
log_assert(options);
log_assert(game_data_path);
log_assert(options);
log_assert(game_data_path);
f2hook_fs_redir_settings(options);
f2hook_fs_redir_settings(options);
f2hook_fs_redir_usb();
f2hook_fs_redir_usb();
}
static void f2hook_patch_fs_mounting_init()
{
patch_mounts_init();
patch_mounts_init();
patch_usb_mnt_init();
patch_usb_mnt_init();
}
static void f2hook_patch_gfx_init(struct f2hook_options* options)
static void f2hook_patch_gfx_init(struct f2hook_options *options)
{
log_assert(options);
log_assert(options);
patch_gfx_init();
patch_gfx_init();
if (options->patch.gfx.windowed) {
patch_gfx_force_window_mode();
}
if (options->patch.gfx.windowed) {
patch_gfx_force_window_mode();
}
}
static void f2hook_patch_main_loop_init(struct f2hook_options* options)
static void f2hook_patch_main_loop_init(struct f2hook_options *options)
{
log_assert(options);
log_assert(options);
patch_main_loop_init(false, options->patch.main_loop.disable_built_in_inputs, false);
patch_main_loop_init(
false, options->patch.main_loop.disable_built_in_inputs, false);
if (options->patch.main_loop.x11_input_handler_api_lib) {
char* abs_path_x11_input_hook_lib = util_fs_get_abs_path(options->patch.main_loop.x11_input_handler_api_lib);
if (options->patch.main_loop.x11_input_handler_api_lib) {
char *abs_path_x11_input_hook_lib = util_fs_get_abs_path(
options->patch.main_loop.x11_input_handler_api_lib);
patch_main_loop_add_x11_input_handler(abs_path_x11_input_hook_lib);
free(abs_path_x11_input_hook_lib);
}
patch_main_loop_add_x11_input_handler(abs_path_x11_input_hook_lib);
free(abs_path_x11_input_hook_lib);
}
}
static void f2hook_patch_sound_init(struct f2hook_options* options)
static void f2hook_patch_sound_init(struct f2hook_options *options)
{
log_assert(options);
log_assert(options);
patch_sound_init(options->patch.sound.device);
patch_axmier_block_init();
patch_sound_init(options->patch.sound.device);
patch_axmier_block_init();
}
static void f2hook_patch_sigsegv_init(struct f2hook_options* options)
static void f2hook_patch_sigsegv_init(struct f2hook_options *options)
{
log_assert(options);
log_assert(options);
patch_sigsegv_init(options->patch.sigsegv.halt_on_segv);
patch_sigsegv_init(options->patch.sigsegv.halt_on_segv);
}
static void f2hook_patch_dongle_init()
{
patch_hasp_init((const uint8_t*) _binary_f2hook_hasp_key_start,
((uintptr_t) &_binary_f2hook_hasp_key_end - (uintptr_t) &_binary_f2hook_hasp_key_start));
patch_hasp_init(
(const uint8_t *) _binary_f2hook_hasp_key_start,
((uintptr_t) &_binary_f2hook_hasp_key_end -
(uintptr_t) &_binary_f2hook_hasp_key_start));
}
static void f2hook_patch_hdd_check_init()
{
patch_hdd_check_init((const uint8_t*) _binary_f2hook_hdd_raw_start,
((uintptr_t) &_binary_f2hook_hdd_raw_end - (uintptr_t) &_binary_f2hook_hdd_raw_start));
patch_hdd_check_init(
(const uint8_t *) _binary_f2hook_hdd_raw_start,
((uintptr_t) &_binary_f2hook_hdd_raw_end -
(uintptr_t) &_binary_f2hook_hdd_raw_start));
}
static void f2hook_patch_piuio_init(struct f2hook_options* options)
static void f2hook_patch_piuio_init(struct f2hook_options *options)
{
log_assert(options);
log_assert(options);
/* Hook before IO emulation */
if (options->patch.piuio.exit_test_serv) {
patch_piuio_exit_init();
}
/* Hook before IO emulation */
if (options->patch.piuio.exit_test_serv) {
patch_piuio_exit_init();
}
patch_usb_init_fix_init();
patch_usb_emu_init();
patch_usb_init_fix_init();
patch_usb_emu_init();
if (options->patch.piuio.api_lib) {
char* abs_path_iolib = util_fs_get_abs_path(options->patch.piuio.api_lib);
if (options->patch.piuio.api_lib) {
char *abs_path_iolib = util_fs_get_abs_path(options->patch.piuio.api_lib);
patch_piuio_init(abs_path_iolib);
free(abs_path_iolib);
}
patch_piuio_init(abs_path_iolib);
free(abs_path_iolib);
}
}
void f2hook_constructor(void)
{
/* Nothing here */
/* Nothing here */
}
void f2hook_destructor(void)
{
/* Nothing here */
/* Nothing here */
}
void f2hook_trap_before_main(int argc, char** argv)
void f2hook_trap_before_main(int argc, char **argv)
{
log_assert(argc >= 0);
log_assert(argv);
log_assert(argc >= 0);
log_assert(argv);
char* game_data_path;
struct f2hook_options options;
char *game_data_path;
struct f2hook_options options;
f2hook_bootstrapping(argc, argv, &options, &game_data_path);
f2hook_patch_fs_init(&options);
f2hook_fs_redirs_init(&options, game_data_path);
f2hook_patch_fs_mounting_init();
f2hook_patch_gfx_init(&options);
f2hook_patch_main_loop_init(&options);
f2hook_patch_sound_init(&options);
f2hook_patch_sigsegv_init(&options);
f2hook_patch_dongle_init();
f2hook_patch_hdd_check_init();
f2hook_patch_piuio_init(&options);
f2hook_bootstrapping(argc, argv, &options, &game_data_path);
f2hook_patch_fs_init(&options);
f2hook_fs_redirs_init(&options, game_data_path);
f2hook_patch_fs_mounting_init();
f2hook_patch_gfx_init(&options);
f2hook_patch_main_loop_init(&options);
f2hook_patch_sound_init(&options);
f2hook_patch_sigsegv_init(&options);
f2hook_patch_dongle_init();
f2hook_patch_hdd_check_init();
f2hook_patch_piuio_init(&options);
free(game_data_path);
free(game_data_path);
log_info("Hooking finished");
log_info("Hooking finished");
}
void f2hook_trap_after_main(void)
{
patch_piuio_shutdown();
patch_piuio_shutdown();
}
LIB_MAIN_CONSTRUCTOR(f2hook_constructor);
+66 -44
View File
@@ -9,14 +9,19 @@
#define F2HOOK_OPTIONS_STR_PATCH_HOOK_MON_IO "patch.hook_mon.io"
#define F2HOOK_OPTIONS_STR_PATCH_HOOK_MON_OPEN "patch.hook_mon.open"
#define F2HOOK_OPTIONS_STR_PATCH_HOOK_MON_USB "patch.hook_mon.usb"
#define F2HOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS "patch.hook_main_loop.disable_built_in_inputs"
#define F2HOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_X11_INPUT_HANDLER "patch_hook_main_loop.x11_input_handler"
#define F2HOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS \
"patch.hook_main_loop.disable_built_in_inputs"
#define F2HOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_X11_INPUT_HANDLER \
"patch_hook_main_loop.x11_input_handler"
#define F2HOOK_OPTIONS_STR_PATCH_NET_PROFILE_SERVER "patch.net_profile.server"
#define F2HOOK_OPTIONS_STR_PATCH_NET_PROFILE_MACHINE_ID "patch.net_profile.machine_id"
#define F2HOOK_OPTIONS_STR_PATCH_NET_PROFILE_MACHINE_ID \
"patch.net_profile.machine_id"
#define F2HOOK_OPTIONS_STR_PATCH_PIUIO_EMU_LIB "patch.piuio.emu_lib"
#define F2HOOK_OPTIONS_STR_PATCH_PIUIO_EXIT_TEST_SERV "patch.piuio_exit.test_serv"
#define F2HOOK_OPTIONS_STR_PATCH_PIUIO_EXIT_TEST_SERV \
"patch.piuio_exit.test_serv"
#define F2HOOK_OPTIONS_STR_PATCH_SOUND_DEVICE "patch.sound.device"
#define F2HOOK_OPTIONS_STR_PATCH_SIGSEGV_HALT_ON_SEGV "patch.sigsegv.halt_on_segv"
#define F2HOOK_OPTIONS_STR_PATCH_SIGSEGV_HALT_ON_SEGV \
"patch.sigsegv.halt_on_segv"
#define F2HOOK_OPTIONS_STR_PATCH_UTIL_LOG_FILE "util.log.file"
#define F2HOOK_OPTIONS_STR_PATCH_UTIL_LOG_LEVEL "util.log.level"
@@ -72,21 +77,24 @@ const struct util_options_def f2hook_options_def[] = {
},
{
.name = F2HOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS,
.description = "Disable the built in keyboard inputs for test (F1), service (F2) and clear (F3)",
.description = "Disable the built in keyboard inputs for test (F1), "
"service (F2) and clear (F3)",
.param = 'k',
.type = UTIL_OPTIONS_TYPE_BOOL,
.default_value.b = false,
},
{
.name = F2HOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_X11_INPUT_HANDLER,
.description = "Path to a library implementing the x11-input-handler api to capture X11 keyboard inputs",
.description = "Path to a library implementing the x11-input-handler "
"api to capture X11 keyboard inputs",
.param = 'q',
.type = UTIL_OPTIONS_TYPE_STR,
.default_value.str = NULL,
},
{
.name = F2HOOK_OPTIONS_STR_PATCH_NET_PROFILE_SERVER,
.description = "Address and port of pumpnet server (e.g. 127.0.0.1:1234)",
.description =
"Address and port of pumpnet server (e.g. 127.0.0.1:1234)",
.param = 'n',
.type = UTIL_OPTIONS_TYPE_STR,
.default_value.str = NULL,
@@ -100,7 +108,8 @@ const struct util_options_def f2hook_options_def[] = {
},
{
.name = F2HOOK_OPTIONS_STR_PATCH_PIUIO_EMU_LIB,
.description = "Path to library implementing the piuio api for piuio emulation",
.description =
"Path to library implementing the piuio api for piuio emulation",
.param = 'p',
.type = UTIL_OPTIONS_TYPE_STR,
.default_value.str = NULL,
@@ -151,45 +160,58 @@ const struct util_options_defs f2hook_options_defs = {
.ndefs = lengthof(f2hook_options_def)
};
bool f2hook_options_init(int argc, char** argv, struct f2hook_options* options)
bool f2hook_options_init(int argc, char **argv, struct f2hook_options *options)
{
log_assert(argv);
log_assert(options);
log_assert(argv);
log_assert(options);
struct util_options_opts* options_opt;
struct util_options_opts *options_opt;
util_options_init(argc, argv);
options_opt = util_options_get(&f2hook_options_defs);
util_options_init(argc, argv);
options_opt = util_options_get(&f2hook_options_defs);
if (!options_opt) {
return false;
}
if (!options_opt) {
return false;
}
options->game.settings = util_options_get_str(options_opt, F2HOOK_OPTIONS_STR_GAME_SETTINGS);
options->patch.gfx.windowed = util_options_get_bool(options_opt, F2HOOK_OPTIONS_STR_PATCH_GFX_WINDOWED);
options->patch.hook_mon.file = util_options_get_bool(options_opt, F2HOOK_OPTIONS_STR_PATCH_HOOK_MON_FILE);
options->patch.hook_mon.fs = util_options_get_bool(options_opt, F2HOOK_OPTIONS_STR_PATCH_HOOK_MON_FS);
options->patch.hook_mon.io = util_options_get_bool(options_opt, F2HOOK_OPTIONS_STR_PATCH_HOOK_MON_IO);
options->patch.hook_mon.open = util_options_get_bool(options_opt, F2HOOK_OPTIONS_STR_PATCH_HOOK_MON_OPEN);
options->patch.hook_mon.usb = util_options_get_bool(options_opt, F2HOOK_OPTIONS_STR_PATCH_HOOK_MON_USB);
options->patch.main_loop.disable_built_in_inputs = util_options_get_bool(options_opt,
F2HOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS);
options->patch.main_loop.x11_input_handler_api_lib =
util_options_get_str(options_opt, F2HOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_X11_INPUT_HANDLER);
options->patch.net.server = util_options_get_str(options_opt, F2HOOK_OPTIONS_STR_PATCH_NET_PROFILE_SERVER);
options->patch.net.machine_id = strtoul(
util_options_get_str(options_opt, F2HOOK_OPTIONS_STR_PATCH_NET_PROFILE_MACHINE_ID),
NULL,
16);
options->patch.piuio.api_lib = util_options_get_str(options_opt, F2HOOK_OPTIONS_STR_PATCH_PIUIO_EMU_LIB);
options->patch.piuio.exit_test_serv =
util_options_get_bool(options_opt, F2HOOK_OPTIONS_STR_PATCH_PIUIO_EXIT_TEST_SERV);
options->patch.sound.device = util_options_get_str(options_opt, F2HOOK_OPTIONS_STR_PATCH_SOUND_DEVICE);
options->patch.sigsegv.halt_on_segv =
util_options_get_bool(options_opt, F2HOOK_OPTIONS_STR_PATCH_SIGSEGV_HALT_ON_SEGV);
options->log.file = util_options_get_str(options_opt, F2HOOK_OPTIONS_STR_PATCH_UTIL_LOG_FILE);
options->log.level =
(enum util_log_level) util_options_get_int(options_opt, F2HOOK_OPTIONS_STR_PATCH_UTIL_LOG_LEVEL);
options->game.settings =
util_options_get_str(options_opt, F2HOOK_OPTIONS_STR_GAME_SETTINGS);
options->patch.gfx.windowed =
util_options_get_bool(options_opt, F2HOOK_OPTIONS_STR_PATCH_GFX_WINDOWED);
options->patch.hook_mon.file = util_options_get_bool(
options_opt, F2HOOK_OPTIONS_STR_PATCH_HOOK_MON_FILE);
options->patch.hook_mon.fs =
util_options_get_bool(options_opt, F2HOOK_OPTIONS_STR_PATCH_HOOK_MON_FS);
options->patch.hook_mon.io =
util_options_get_bool(options_opt, F2HOOK_OPTIONS_STR_PATCH_HOOK_MON_IO);
options->patch.hook_mon.open = util_options_get_bool(
options_opt, F2HOOK_OPTIONS_STR_PATCH_HOOK_MON_OPEN);
options->patch.hook_mon.usb =
util_options_get_bool(options_opt, F2HOOK_OPTIONS_STR_PATCH_HOOK_MON_USB);
options->patch.main_loop.disable_built_in_inputs = util_options_get_bool(
options_opt,
F2HOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS);
options->patch.main_loop.x11_input_handler_api_lib = util_options_get_str(
options_opt, F2HOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_X11_INPUT_HANDLER);
options->patch.net.server = util_options_get_str(
options_opt, F2HOOK_OPTIONS_STR_PATCH_NET_PROFILE_SERVER);
options->patch.net.machine_id = strtoul(
util_options_get_str(
options_opt, F2HOOK_OPTIONS_STR_PATCH_NET_PROFILE_MACHINE_ID),
NULL,
16);
options->patch.piuio.api_lib =
util_options_get_str(options_opt, F2HOOK_OPTIONS_STR_PATCH_PIUIO_EMU_LIB);
options->patch.piuio.exit_test_serv = util_options_get_bool(
options_opt, F2HOOK_OPTIONS_STR_PATCH_PIUIO_EXIT_TEST_SERV);
options->patch.sound.device =
util_options_get_str(options_opt, F2HOOK_OPTIONS_STR_PATCH_SOUND_DEVICE);
options->patch.sigsegv.halt_on_segv = util_options_get_bool(
options_opt, F2HOOK_OPTIONS_STR_PATCH_SIGSEGV_HALT_ON_SEGV);
options->log.file =
util_options_get_str(options_opt, F2HOOK_OPTIONS_STR_PATCH_UTIL_LOG_FILE);
options->log.level = (enum util_log_level) util_options_get_int(
options_opt, F2HOOK_OPTIONS_STR_PATCH_UTIL_LOG_LEVEL);
return true;
return true;
}
+38 -38
View File
@@ -7,53 +7,53 @@
#include "util/log.h"
struct f2hook_options {
struct game {
const char* settings;
} game;
struct game {
const char *settings;
} game;
struct patch {
struct gfx {
bool windowed;
} gfx;
struct patch {
struct gfx {
bool windowed;
} gfx;
struct hook_mon {
bool file;
bool fs;
bool io;
bool open;
bool usb;
} hook_mon;
struct hook_mon {
bool file;
bool fs;
bool io;
bool open;
bool usb;
} hook_mon;
struct main_loop {
bool disable_built_in_inputs;
const char* x11_input_handler_api_lib;
} main_loop;
struct main_loop {
bool disable_built_in_inputs;
const char *x11_input_handler_api_lib;
} main_loop;
struct net {
const char* server;
uint32_t machine_id;
} net;
struct net {
const char *server;
uint32_t machine_id;
} net;
struct piuio {
const char* api_lib;
bool exit_test_serv;
} piuio;
struct piuio {
const char *api_lib;
bool exit_test_serv;
} piuio;
struct sound {
const char* device;
} sound;
struct sound {
const char *device;
} sound;
struct sigsegv {
bool halt_on_segv;
} sigsegv;
} patch;
struct sigsegv {
bool halt_on_segv;
} sigsegv;
} patch;
struct log {
const char* file;
enum util_log_level level;
} log;
struct log {
const char *file;
enum util_log_level level;
} log;
};
bool f2hook_options_init(int argc, char** argv, struct f2hook_options* options);
bool f2hook_options_init(int argc, char **argv, struct f2hook_options *options);
#endif
+124 -111
View File
@@ -17,8 +17,8 @@
#include "hook/patch/main-loop.h"
#include "hook/patch/microdog40.h"
#include "hook/patch/mounts.h"
#include "hook/patch/piuio.h"
#include "hook/patch/piuio-exit.h"
#include "hook/patch/piuio.h"
#include "hook/patch/redir.h"
#include "hook/patch/sigsegv.h"
#include "hook/patch/sound.h"
@@ -39,202 +39,215 @@ extern const uint8_t _binary_fexhook_hdd_raw_end[];
extern const uint8_t _binary_fexhook_dog_key_start[];
extern const uint8_t _binary_fexhook_dog_key_end[];
static void fexhook_bootstrapping(int argc, char** argv, struct fexhook_options* options, char** game_data_path)
static void fexhook_bootstrapping(
int argc,
char **argv,
struct fexhook_options *options,
char **game_data_path)
{
log_assert(argc >= 0);
log_assert(argv);
log_assert(options);
log_assert(game_data_path);
log_assert(argc >= 0);
log_assert(argv);
log_assert(options);
log_assert(game_data_path);
if (hook_core_piu_block_non_piu_process_recursion(argc, argv)) {
return;
}
if (hook_core_piu_block_non_piu_process_recursion(argc, argv)) {
return;
}
hook_core_piu_log_init(argc, argv);
hook_core_piu_log_init(argc, argv);
if (!fexhook_options_init(argc, argv, options)) {
exit(0);
}
if (!fexhook_options_init(argc, argv, options)) {
exit(0);
}
hook_core_piu_log_info(argc, argv);
hook_core_piu_log_info(argc, argv);
*game_data_path = hook_core_piu_utils_get_and_verify_game_data_path(argc, argv);
*game_data_path =
hook_core_piu_utils_get_and_verify_game_data_path(argc, argv);
hook_core_piu_utils_verify_root_user();
hook_core_piu_utils_verify_root_user();
log_info("Initializing, piu game data path: %s", *game_data_path);
log_info("Initializing, piu game data path: %s", *game_data_path);
}
static void fexhook_patch_fs_init(struct fexhook_options* options)
static void fexhook_patch_fs_init(struct fexhook_options *options)
{
log_assert(options);
log_assert(options);
patch_hook_mon_init(
options->patch.hook_mon.io,
options->patch.hook_mon.file,
options->patch.hook_mon.fs,
options->patch.hook_mon.usb,
options->patch.hook_mon.open);
patch_hook_mon_init(
options->patch.hook_mon.io,
options->patch.hook_mon.file,
options->patch.hook_mon.fs,
options->patch.hook_mon.usb,
options->patch.hook_mon.open);
patch_redir_init();
patch_redir_init();
}
static void fexhook_fs_redir_settings(struct fexhook_options* options)
static void fexhook_fs_redir_settings(struct fexhook_options *options)
{
log_assert(options);
log_assert(options);
if (options->game.settings) {
if (!util_fs_path_exists(options->game.settings)) {
log_info("Settings path %s does not exist, creating", options->game.settings);
if (options->game.settings) {
if (!util_fs_path_exists(options->game.settings)) {
log_info(
"Settings path %s does not exist, creating", options->game.settings);
if (!util_fs_mkdir(options->game.settings)) {
log_error("Creating directory %s failed", options->game.settings);
}
}
char* abs_path = util_fs_get_abs_path(options->game.settings);
cnh_redir_add("/SETTINGS", abs_path);
free(abs_path);
} else {
log_warn("No settings path specified");
if (!util_fs_mkdir(options->game.settings)) {
log_error("Creating directory %s failed", options->game.settings);
}
}
char *abs_path = util_fs_get_abs_path(options->game.settings);
cnh_redir_add("/SETTINGS", abs_path);
free(abs_path);
} else {
log_warn("No settings path specified");
}
}
static void fexhook_fs_redir_usb()
{
/* Needed on newer kernels */
cnh_redir_add("/proc/bus/usb/devices", "/sys/kernel/debug/usb/devices");
patch_usbfs_init();
/* Needed on newer kernels */
cnh_redir_add("/proc/bus/usb/devices", "/sys/kernel/debug/usb/devices");
patch_usbfs_init();
}
static void fexhook_fs_redirs_init(struct fexhook_options* options, const char* game_data_path)
static void fexhook_fs_redirs_init(
struct fexhook_options *options, const char *game_data_path)
{
log_assert(options);
log_assert(game_data_path);
log_assert(options);
log_assert(game_data_path);
fexhook_fs_redir_settings(options);
fexhook_fs_redir_settings(options);
fexhook_fs_redir_usb();
fexhook_fs_redir_usb();
}
static void fexhook_patch_fs_mounting_init()
{
patch_mounts_init();
patch_mounts_init();
patch_usb_mnt_init();
patch_usb_mnt_init();
}
static void fexhook_patch_gfx_init(struct fexhook_options* options)
static void fexhook_patch_gfx_init(struct fexhook_options *options)
{
log_assert(options);
log_assert(options);
patch_gfx_init();
patch_gfx_init();
if (options->patch.gfx.windowed) {
patch_gfx_force_window_mode();
}
if (options->patch.gfx.windowed) {
patch_gfx_force_window_mode();
}
}
static void fexhook_patch_main_loop_init(struct fexhook_options* options)
static void fexhook_patch_main_loop_init(struct fexhook_options *options)
{
log_assert(options);
log_assert(options);
patch_main_loop_init(false, options->patch.main_loop.disable_built_in_inputs, false);
patch_main_loop_init(
false, options->patch.main_loop.disable_built_in_inputs, false);
if (options->patch.main_loop.x11_input_handler_api_lib) {
char* abs_path_x11_input_hook_lib = util_fs_get_abs_path(options->patch.main_loop.x11_input_handler_api_lib);
if (options->patch.main_loop.x11_input_handler_api_lib) {
char *abs_path_x11_input_hook_lib = util_fs_get_abs_path(
options->patch.main_loop.x11_input_handler_api_lib);
patch_main_loop_add_x11_input_handler(abs_path_x11_input_hook_lib);
free(abs_path_x11_input_hook_lib);
}
patch_main_loop_add_x11_input_handler(abs_path_x11_input_hook_lib);
free(abs_path_x11_input_hook_lib);
}
}
static void fexhook_patch_sound_init(struct fexhook_options* options)
static void fexhook_patch_sound_init(struct fexhook_options *options)
{
log_assert(options);
log_assert(options);
patch_sound_init(options->patch.sound.device);
patch_axmier_block_init();
patch_sound_init(options->patch.sound.device);
patch_axmier_block_init();
}
static void fexhook_patch_sigsegv_init(struct fexhook_options* options)
static void fexhook_patch_sigsegv_init(struct fexhook_options *options)
{
log_assert(options);
log_assert(options);
patch_sigsegv_init(options->patch.sigsegv.halt_on_segv);
patch_sigsegv_init(options->patch.sigsegv.halt_on_segv);
}
static void fexhook_patch_dongle_init()
{
patch_microdog40_init((const uint8_t*) _binary_fexhook_dog_key_start,
((uintptr_t) &_binary_fexhook_dog_key_end - (uintptr_t) &_binary_fexhook_dog_key_start));
patch_microdog40_init(
(const uint8_t *) _binary_fexhook_dog_key_start,
((uintptr_t) &_binary_fexhook_dog_key_end -
(uintptr_t) &_binary_fexhook_dog_key_start));
}
static void fexhook_patch_hdd_check_init()
{
patch_hdd_check_init((const uint8_t*) _binary_fexhook_hdd_raw_start,
((uintptr_t) &_binary_fexhook_hdd_raw_end - (uintptr_t) &_binary_fexhook_hdd_raw_start));
patch_hdd_check_init(
(const uint8_t *) _binary_fexhook_hdd_raw_start,
((uintptr_t) &_binary_fexhook_hdd_raw_end -
(uintptr_t) &_binary_fexhook_hdd_raw_start));
}
static void fexhook_patch_piuio_init(struct fexhook_options* options)
static void fexhook_patch_piuio_init(struct fexhook_options *options)
{
log_assert(options);
log_assert(options);
/* Hook before IO emulation */
if (options->patch.piuio.exit_test_serv) {
patch_piuio_exit_init();
}
/* Hook before IO emulation */
if (options->patch.piuio.exit_test_serv) {
patch_piuio_exit_init();
}
patch_usb_init_fix_init();
patch_usb_emu_init();
patch_usb_init_fix_init();
patch_usb_emu_init();
if (options->patch.piuio.api_lib) {
char* abs_path_iolib = util_fs_get_abs_path(options->patch.piuio.api_lib);
if (options->patch.piuio.api_lib) {
char *abs_path_iolib = util_fs_get_abs_path(options->patch.piuio.api_lib);
patch_piuio_init(abs_path_iolib);
free(abs_path_iolib);
}
patch_piuio_init(abs_path_iolib);
free(abs_path_iolib);
}
}
void fexhook_constructor(void)
{
/* Nothing here */
/* Nothing here */
}
void fexhook_destructor(void)
{
/* Nothing here */
/* Nothing here */
}
void fexhook_trap_before_main(int argc, char** argv)
void fexhook_trap_before_main(int argc, char **argv)
{
log_assert(argc >= 0);
log_assert(argv);
log_assert(argc >= 0);
log_assert(argv);
char* game_data_path;
struct fexhook_options options;
char *game_data_path;
struct fexhook_options options;
fexhook_bootstrapping(argc, argv, &options, &game_data_path);
fexhook_patch_fs_init(&options);
fexhook_fs_redirs_init(&options, game_data_path);
fexhook_patch_fs_mounting_init();
fexhook_patch_gfx_init(&options);
fexhook_patch_main_loop_init(&options);
fexhook_patch_sound_init(&options);
fexhook_patch_sigsegv_init(&options);
fexhook_patch_dongle_init();
fexhook_patch_hdd_check_init();
fexhook_patch_piuio_init(&options);
fexhook_bootstrapping(argc, argv, &options, &game_data_path);
fexhook_patch_fs_init(&options);
fexhook_fs_redirs_init(&options, game_data_path);
fexhook_patch_fs_mounting_init();
fexhook_patch_gfx_init(&options);
fexhook_patch_main_loop_init(&options);
fexhook_patch_sound_init(&options);
fexhook_patch_sigsegv_init(&options);
fexhook_patch_dongle_init();
fexhook_patch_hdd_check_init();
fexhook_patch_piuio_init(&options);
free(game_data_path);
free(game_data_path);
log_info("Hooking finished");
log_info("Hooking finished");
}
void fexhook_trap_after_main(void)
{
patch_piuio_shutdown();
patch_piuio_shutdown();
}
LIB_MAIN_CONSTRUCTOR(fexhook_constructor);
+69 -45
View File
@@ -9,14 +9,19 @@
#define FEXHOOK_OPTIONS_STR_PATCH_HOOK_MON_IO "patch.hook_mon.io"
#define FEXHOOK_OPTIONS_STR_PATCH_HOOK_MON_OPEN "patch.hook_mon.open"
#define FEXHOOK_OPTIONS_STR_PATCH_HOOK_MON_USB "patch.hook_mon.usb"
#define FEXHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS "patch.hook_main_loop.disable_built_in_inputs"
#define FEXHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_X11_INPUT_HANDLER "patch_hook_main_loop.x11_input_handler"
#define FEXHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS \
"patch.hook_main_loop.disable_built_in_inputs"
#define FEXHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_X11_INPUT_HANDLER \
"patch_hook_main_loop.x11_input_handler"
#define FEXHOOK_OPTIONS_STR_PATCH_NET_PROFILE_SERVER "patch.net_profile.server"
#define FEXHOOK_OPTIONS_STR_PATCH_NET_PROFILE_MACHINE_ID "patch.net_profile.machine_id"
#define FEXHOOK_OPTIONS_STR_PATCH_NET_PROFILE_MACHINE_ID \
"patch.net_profile.machine_id"
#define FEXHOOK_OPTIONS_STR_PATCH_PIUIO_EMU_LIB "patch.piuio.emu_lib"
#define FEXHOOK_OPTIONS_STR_PATCH_PIUIO_EXIT_TEST_SERV "patch.piuio_exit.test_serv"
#define FEXHOOK_OPTIONS_STR_PATCH_PIUIO_EXIT_TEST_SERV \
"patch.piuio_exit.test_serv"
#define FEXHOOK_OPTIONS_STR_PATCH_SOUND_DEVICE "patch.sound.device"
#define FEXHOOK_OPTIONS_STR_PATCH_SIGSEGV_HALT_ON_SEGV "patch.sigsegv.halt_on_segv"
#define FEXHOOK_OPTIONS_STR_PATCH_SIGSEGV_HALT_ON_SEGV \
"patch.sigsegv.halt_on_segv"
#define FEXHOOK_OPTIONS_STR_PATCH_UTIL_LOG_FILE "util.log.file"
#define FEXHOOK_OPTIONS_STR_PATCH_UTIL_LOG_LEVEL "util.log.level"
@@ -71,22 +76,26 @@ const struct util_options_def fexhook_options_def[] = {
.default_value.b = false,
},
{
.name = FEXHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS,
.description = "Disable the built in keyboard inputs for test (F1), service (F2) and clear (F3)",
.name =
FEXHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS,
.description = "Disable the built in keyboard inputs for test (F1), "
"service (F2) and clear (F3)",
.param = 'k',
.type = UTIL_OPTIONS_TYPE_BOOL,
.default_value.b = false,
},
{
.name = FEXHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_X11_INPUT_HANDLER,
.description = "Path to a library implementing the x11-input-handler api to capture X11 keyboard inputs",
.description = "Path to a library implementing the x11-input-handler "
"api to capture X11 keyboard inputs",
.param = 'q',
.type = UTIL_OPTIONS_TYPE_STR,
.default_value.str = NULL,
},
{
.name = FEXHOOK_OPTIONS_STR_PATCH_NET_PROFILE_SERVER,
.description = "Address and port of pumpnet server (e.g. 127.0.0.1:1234)",
.description =
"Address and port of pumpnet server (e.g. 127.0.0.1:1234)",
.param = 'n',
.type = UTIL_OPTIONS_TYPE_STR,
.default_value.str = NULL,
@@ -100,7 +109,8 @@ const struct util_options_def fexhook_options_def[] = {
},
{
.name = FEXHOOK_OPTIONS_STR_PATCH_PIUIO_EMU_LIB,
.description = "Path to library implementing the piuio api for piuio emulation",
.description =
"Path to library implementing the piuio api for piuio emulation",
.param = 'p',
.type = UTIL_OPTIONS_TYPE_STR,
.default_value.str = NULL,
@@ -151,45 +161,59 @@ const struct util_options_defs fexhook_options_defs = {
.ndefs = lengthof(fexhook_options_def)
};
bool fexhook_options_init(int argc, char** argv, struct fexhook_options* options)
bool fexhook_options_init(
int argc, char **argv, struct fexhook_options *options)
{
log_assert(argv);
log_assert(options);
log_assert(argv);
log_assert(options);
struct util_options_opts* options_opt;
struct util_options_opts *options_opt;
util_options_init(argc, argv);
options_opt = util_options_get(&fexhook_options_defs);
util_options_init(argc, argv);
options_opt = util_options_get(&fexhook_options_defs);
if (!options_opt) {
return false;
}
if (!options_opt) {
return false;
}
options->game.settings = util_options_get_str(options_opt, FEXHOOK_OPTIONS_STR_GAME_SETTINGS);
options->patch.gfx.windowed = util_options_get_bool(options_opt, FEXHOOK_OPTIONS_STR_PATCH_GFX_WINDOWED);
options->patch.hook_mon.file = util_options_get_bool(options_opt, FEXHOOK_OPTIONS_STR_PATCH_HOOK_MON_FILE);
options->patch.hook_mon.fs = util_options_get_bool(options_opt, FEXHOOK_OPTIONS_STR_PATCH_HOOK_MON_FS);
options->patch.hook_mon.io = util_options_get_bool(options_opt, FEXHOOK_OPTIONS_STR_PATCH_HOOK_MON_IO);
options->patch.hook_mon.open = util_options_get_bool(options_opt, FEXHOOK_OPTIONS_STR_PATCH_HOOK_MON_OPEN);
options->patch.hook_mon.usb = util_options_get_bool(options_opt, FEXHOOK_OPTIONS_STR_PATCH_HOOK_MON_USB);
options->patch.main_loop.disable_built_in_inputs = util_options_get_bool(options_opt,
FEXHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS);
options->patch.main_loop.x11_input_handler_api_lib =
util_options_get_str(options_opt, FEXHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_X11_INPUT_HANDLER);
options->patch.net.server = util_options_get_str(options_opt, FEXHOOK_OPTIONS_STR_PATCH_NET_PROFILE_SERVER);
options->patch.net.machine_id = strtoul(
util_options_get_str(options_opt, FEXHOOK_OPTIONS_STR_PATCH_NET_PROFILE_MACHINE_ID),
NULL,
16);
options->patch.piuio.api_lib = util_options_get_str(options_opt, FEXHOOK_OPTIONS_STR_PATCH_PIUIO_EMU_LIB);
options->patch.piuio.exit_test_serv =
util_options_get_bool(options_opt, FEXHOOK_OPTIONS_STR_PATCH_PIUIO_EXIT_TEST_SERV);
options->patch.sound.device = util_options_get_str(options_opt, FEXHOOK_OPTIONS_STR_PATCH_SOUND_DEVICE);
options->patch.sigsegv.halt_on_segv =
util_options_get_bool(options_opt, FEXHOOK_OPTIONS_STR_PATCH_SIGSEGV_HALT_ON_SEGV);
options->log.file = util_options_get_str(options_opt, FEXHOOK_OPTIONS_STR_PATCH_UTIL_LOG_FILE);
options->log.level =
(enum util_log_level) util_options_get_int(options_opt, FEXHOOK_OPTIONS_STR_PATCH_UTIL_LOG_LEVEL);
options->game.settings =
util_options_get_str(options_opt, FEXHOOK_OPTIONS_STR_GAME_SETTINGS);
options->patch.gfx.windowed = util_options_get_bool(
options_opt, FEXHOOK_OPTIONS_STR_PATCH_GFX_WINDOWED);
options->patch.hook_mon.file = util_options_get_bool(
options_opt, FEXHOOK_OPTIONS_STR_PATCH_HOOK_MON_FILE);
options->patch.hook_mon.fs =
util_options_get_bool(options_opt, FEXHOOK_OPTIONS_STR_PATCH_HOOK_MON_FS);
options->patch.hook_mon.io =
util_options_get_bool(options_opt, FEXHOOK_OPTIONS_STR_PATCH_HOOK_MON_IO);
options->patch.hook_mon.open = util_options_get_bool(
options_opt, FEXHOOK_OPTIONS_STR_PATCH_HOOK_MON_OPEN);
options->patch.hook_mon.usb = util_options_get_bool(
options_opt, FEXHOOK_OPTIONS_STR_PATCH_HOOK_MON_USB);
options->patch.main_loop.disable_built_in_inputs = util_options_get_bool(
options_opt,
FEXHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS);
options->patch.main_loop.x11_input_handler_api_lib = util_options_get_str(
options_opt, FEXHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_X11_INPUT_HANDLER);
options->patch.net.server = util_options_get_str(
options_opt, FEXHOOK_OPTIONS_STR_PATCH_NET_PROFILE_SERVER);
options->patch.net.machine_id = strtoul(
util_options_get_str(
options_opt, FEXHOOK_OPTIONS_STR_PATCH_NET_PROFILE_MACHINE_ID),
NULL,
16);
options->patch.piuio.api_lib = util_options_get_str(
options_opt, FEXHOOK_OPTIONS_STR_PATCH_PIUIO_EMU_LIB);
options->patch.piuio.exit_test_serv = util_options_get_bool(
options_opt, FEXHOOK_OPTIONS_STR_PATCH_PIUIO_EXIT_TEST_SERV);
options->patch.sound.device =
util_options_get_str(options_opt, FEXHOOK_OPTIONS_STR_PATCH_SOUND_DEVICE);
options->patch.sigsegv.halt_on_segv = util_options_get_bool(
options_opt, FEXHOOK_OPTIONS_STR_PATCH_SIGSEGV_HALT_ON_SEGV);
options->log.file = util_options_get_str(
options_opt, FEXHOOK_OPTIONS_STR_PATCH_UTIL_LOG_FILE);
options->log.level = (enum util_log_level) util_options_get_int(
options_opt, FEXHOOK_OPTIONS_STR_PATCH_UTIL_LOG_LEVEL);
return true;
return true;
}
+39 -38
View File
@@ -7,53 +7,54 @@
#include "util/log.h"
struct fexhook_options {
struct game {
const char* settings;
} game;
struct game {
const char *settings;
} game;
struct patch {
struct gfx {
bool windowed;
} gfx;
struct patch {
struct gfx {
bool windowed;
} gfx;
struct hook_mon {
bool file;
bool fs;
bool io;
bool open;
bool usb;
} hook_mon;
struct hook_mon {
bool file;
bool fs;
bool io;
bool open;
bool usb;
} hook_mon;
struct main_loop {
bool disable_built_in_inputs;
const char* x11_input_handler_api_lib;
} main_loop;
struct main_loop {
bool disable_built_in_inputs;
const char *x11_input_handler_api_lib;
} main_loop;
struct net {
const char* server;
uint32_t machine_id;
} net;
struct net {
const char *server;
uint32_t machine_id;
} net;
struct piuio {
const char* api_lib;
bool exit_test_serv;
} piuio;
struct piuio {
const char *api_lib;
bool exit_test_serv;
} piuio;
struct sound {
const char* device;
} sound;
struct sound {
const char *device;
} sound;
struct sigsegv {
bool halt_on_segv;
} sigsegv;
} patch;
struct sigsegv {
bool halt_on_segv;
} sigsegv;
} patch;
struct log {
const char* file;
enum util_log_level level;
} log;
struct log {
const char *file;
enum util_log_level level;
} log;
};
bool fexhook_options_init(int argc, char** argv, struct fexhook_options* options);
bool fexhook_options_init(
int argc, char **argv, struct fexhook_options *options);
#endif
+124 -111
View File
@@ -17,8 +17,8 @@
#include "hook/patch/main-loop.h"
#include "hook/patch/microdog40.h"
#include "hook/patch/mounts.h"
#include "hook/patch/piuio.h"
#include "hook/patch/piuio-exit.h"
#include "hook/patch/piuio.h"
#include "hook/patch/redir.h"
#include "hook/patch/sigsegv.h"
#include "hook/patch/sound.h"
@@ -39,202 +39,215 @@ extern const uint8_t _binary_fsthook_hdd_raw_end[];
extern const uint8_t _binary_fsthook_dog_key_start[];
extern const uint8_t _binary_fsthook_dog_key_end[];
static void fsthook_bootstrapping(int argc, char** argv, struct fsthook_options* options, char** game_data_path)
static void fsthook_bootstrapping(
int argc,
char **argv,
struct fsthook_options *options,
char **game_data_path)
{
log_assert(argc >= 0);
log_assert(argv);
log_assert(options);
log_assert(game_data_path);
log_assert(argc >= 0);
log_assert(argv);
log_assert(options);
log_assert(game_data_path);
if (hook_core_piu_block_non_piu_process_recursion(argc, argv)) {
return;
}
if (hook_core_piu_block_non_piu_process_recursion(argc, argv)) {
return;
}
hook_core_piu_log_init(argc, argv);
hook_core_piu_log_init(argc, argv);
if (!fsthook_options_init(argc, argv, options)) {
exit(0);
}
if (!fsthook_options_init(argc, argv, options)) {
exit(0);
}
hook_core_piu_log_info(argc, argv);
hook_core_piu_log_info(argc, argv);
*game_data_path = hook_core_piu_utils_get_and_verify_game_data_path(argc, argv);
*game_data_path =
hook_core_piu_utils_get_and_verify_game_data_path(argc, argv);
hook_core_piu_utils_verify_root_user();
hook_core_piu_utils_verify_root_user();
log_info("Initializing, piu game data path: %s", *game_data_path);
log_info("Initializing, piu game data path: %s", *game_data_path);
}
static void fsthook_patch_fs_init(struct fsthook_options* options)
static void fsthook_patch_fs_init(struct fsthook_options *options)
{
log_assert(options);
log_assert(options);
patch_hook_mon_init(
options->patch.hook_mon.io,
options->patch.hook_mon.file,
options->patch.hook_mon.fs,
options->patch.hook_mon.usb,
options->patch.hook_mon.open);
patch_hook_mon_init(
options->patch.hook_mon.io,
options->patch.hook_mon.file,
options->patch.hook_mon.fs,
options->patch.hook_mon.usb,
options->patch.hook_mon.open);
patch_redir_init();
patch_redir_init();
}
static void fsthook_fs_redir_settings(struct fsthook_options* options)
static void fsthook_fs_redir_settings(struct fsthook_options *options)
{
log_assert(options);
log_assert(options);
if (options->game.settings) {
if (!util_fs_path_exists(options->game.settings)) {
log_info("Settings path %s does not exist, creating", options->game.settings);
if (options->game.settings) {
if (!util_fs_path_exists(options->game.settings)) {
log_info(
"Settings path %s does not exist, creating", options->game.settings);
if (!util_fs_mkdir(options->game.settings)) {
log_error("Creating directory %s failed", options->game.settings);
}
}
char* abs_path = util_fs_get_abs_path(options->game.settings);
cnh_redir_add("/SETTINGS", abs_path);
free(abs_path);
} else {
log_warn("No settings path specified");
if (!util_fs_mkdir(options->game.settings)) {
log_error("Creating directory %s failed", options->game.settings);
}
}
char *abs_path = util_fs_get_abs_path(options->game.settings);
cnh_redir_add("/SETTINGS", abs_path);
free(abs_path);
} else {
log_warn("No settings path specified");
}
}
static void fsthook_fs_redir_usb()
{
/* Needed on newer kernels */
cnh_redir_add("/proc/bus/usb/devices", "/sys/kernel/debug/usb/devices");
patch_usbfs_init();
/* Needed on newer kernels */
cnh_redir_add("/proc/bus/usb/devices", "/sys/kernel/debug/usb/devices");
patch_usbfs_init();
}
static void fsthook_fs_redirs_init(struct fsthook_options* options, const char* game_data_path)
static void fsthook_fs_redirs_init(
struct fsthook_options *options, const char *game_data_path)
{
log_assert(options);
log_assert(game_data_path);
log_assert(options);
log_assert(game_data_path);
fsthook_fs_redir_settings(options);
fsthook_fs_redir_settings(options);
fsthook_fs_redir_usb();
fsthook_fs_redir_usb();
}
static void fsthook_patch_fs_mounting_init()
{
patch_mounts_init();
patch_mounts_init();
patch_usb_mnt_init();
patch_usb_mnt_init();
}
static void fsthook_patch_gfx_init(struct fsthook_options* options)
static void fsthook_patch_gfx_init(struct fsthook_options *options)
{
log_assert(options);
log_assert(options);
patch_gfx_init();
patch_gfx_init();
if (options->patch.gfx.windowed) {
patch_gfx_force_window_mode();
}
if (options->patch.gfx.windowed) {
patch_gfx_force_window_mode();
}
}
static void fsthook_patch_main_loop_init(struct fsthook_options* options)
static void fsthook_patch_main_loop_init(struct fsthook_options *options)
{
log_assert(options);
log_assert(options);
patch_main_loop_init(false, options->patch.main_loop.disable_built_in_inputs, false);
patch_main_loop_init(
false, options->patch.main_loop.disable_built_in_inputs, false);
if (options->patch.main_loop.x11_input_handler_api_lib) {
char* abs_path_x11_input_hook_lib = util_fs_get_abs_path(options->patch.main_loop.x11_input_handler_api_lib);
if (options->patch.main_loop.x11_input_handler_api_lib) {
char *abs_path_x11_input_hook_lib = util_fs_get_abs_path(
options->patch.main_loop.x11_input_handler_api_lib);
patch_main_loop_add_x11_input_handler(abs_path_x11_input_hook_lib);
free(abs_path_x11_input_hook_lib);
}
patch_main_loop_add_x11_input_handler(abs_path_x11_input_hook_lib);
free(abs_path_x11_input_hook_lib);
}
}
static void fsthook_patch_sound_init(struct fsthook_options* options)
static void fsthook_patch_sound_init(struct fsthook_options *options)
{
log_assert(options);
log_assert(options);
patch_sound_init(options->patch.sound.device);
patch_axmier_block_init();
patch_sound_init(options->patch.sound.device);
patch_axmier_block_init();
}
static void fsthook_patch_sigsegv_init(struct fsthook_options* options)
static void fsthook_patch_sigsegv_init(struct fsthook_options *options)
{
log_assert(options);
log_assert(options);
patch_sigsegv_init(options->patch.sigsegv.halt_on_segv);
patch_sigsegv_init(options->patch.sigsegv.halt_on_segv);
}
static void fsthook_patch_dongle_init()
{
patch_microdog40_init((const uint8_t*) _binary_fsthook_dog_key_start,
((uintptr_t) &_binary_fsthook_dog_key_end - (uintptr_t) &_binary_fsthook_dog_key_start));
patch_microdog40_init(
(const uint8_t *) _binary_fsthook_dog_key_start,
((uintptr_t) &_binary_fsthook_dog_key_end -
(uintptr_t) &_binary_fsthook_dog_key_start));
}
static void fsthook_patch_hdd_check_init()
{
patch_hdd_check_init((const uint8_t*) _binary_fsthook_hdd_raw_start,
((uintptr_t) &_binary_fsthook_hdd_raw_end - (uintptr_t) &_binary_fsthook_hdd_raw_start));
patch_hdd_check_init(
(const uint8_t *) _binary_fsthook_hdd_raw_start,
((uintptr_t) &_binary_fsthook_hdd_raw_end -
(uintptr_t) &_binary_fsthook_hdd_raw_start));
}
static void fsthook_patch_piuio_init(struct fsthook_options* options)
static void fsthook_patch_piuio_init(struct fsthook_options *options)
{
log_assert(options);
log_assert(options);
/* Hook before IO emulation */
if (options->patch.piuio.exit_test_serv) {
patch_piuio_exit_init();
}
/* Hook before IO emulation */
if (options->patch.piuio.exit_test_serv) {
patch_piuio_exit_init();
}
patch_usb_init_fix_init();
patch_usb_emu_init();
patch_usb_init_fix_init();
patch_usb_emu_init();
if (options->patch.piuio.api_lib) {
char* abs_path_iolib = util_fs_get_abs_path(options->patch.piuio.api_lib);
if (options->patch.piuio.api_lib) {
char *abs_path_iolib = util_fs_get_abs_path(options->patch.piuio.api_lib);
patch_piuio_init(abs_path_iolib);
free(abs_path_iolib);
}
patch_piuio_init(abs_path_iolib);
free(abs_path_iolib);
}
}
void fsthook_constructor(void)
{
/* Nothing here */
/* Nothing here */
}
void fsthook_destructor(void)
{
/* Nothing here */
/* Nothing here */
}
void fsthook_trap_before_main(int argc, char** argv)
void fsthook_trap_before_main(int argc, char **argv)
{
log_assert(argc >= 0);
log_assert(argv);
log_assert(argc >= 0);
log_assert(argv);
char* game_data_path;
struct fsthook_options options;
char *game_data_path;
struct fsthook_options options;
fsthook_bootstrapping(argc, argv, &options, &game_data_path);
fsthook_patch_fs_init(&options);
fsthook_fs_redirs_init(&options, game_data_path);
fsthook_patch_fs_mounting_init();
fsthook_patch_gfx_init(&options);
fsthook_patch_main_loop_init(&options);
fsthook_patch_sound_init(&options);
fsthook_patch_sigsegv_init(&options);
fsthook_patch_dongle_init();
fsthook_patch_hdd_check_init();
fsthook_patch_piuio_init(&options);
fsthook_bootstrapping(argc, argv, &options, &game_data_path);
fsthook_patch_fs_init(&options);
fsthook_fs_redirs_init(&options, game_data_path);
fsthook_patch_fs_mounting_init();
fsthook_patch_gfx_init(&options);
fsthook_patch_main_loop_init(&options);
fsthook_patch_sound_init(&options);
fsthook_patch_sigsegv_init(&options);
fsthook_patch_dongle_init();
fsthook_patch_hdd_check_init();
fsthook_patch_piuio_init(&options);
free(game_data_path);
free(game_data_path);
log_info("Hooking finished");
log_info("Hooking finished");
}
void fsthook_trap_after_main(void)
{
patch_piuio_shutdown();
patch_piuio_shutdown();
}
LIB_MAIN_CONSTRUCTOR(fsthook_constructor);
+70 -46
View File
@@ -9,14 +9,19 @@
#define FSTHOOK_OPTIONS_STR_PATCH_HOOK_MON_IO "patch.hook_mon.io"
#define FSTHOOK_OPTIONS_STR_PATCH_HOOK_MON_OPEN "patch.hook_mon.open"
#define FSTHOOK_OPTIONS_STR_PATCH_HOOK_MON_USB "patch.hook_mon.usb"
#define FSTHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS "patch.hook_main_loop.disable_built_in_inputs"
#define FSTHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_X11_INPUT_HANDLER "patch_hook_main_loop.x11_input_handler"
#define FSTHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS \
"patch.hook_main_loop.disable_built_in_inputs"
#define FSTHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_X11_INPUT_HANDLER \
"patch_hook_main_loop.x11_input_handler"
#define FSTHOOK_OPTIONS_STR_PATCH_NET_PROFILE_SERVER "patch.net_profile.server"
#define FSTHOOK_OPTIONS_STR_PATCH_NET_PROFILE_MACHINE_ID "patch.net_profile.machine_id"
#define FSTHOOK_OPTIONS_STR_PATCH_NET_PROFILE_MACHINE_ID \
"patch.net_profile.machine_id"
#define FSTHOOK_OPTIONS_STR_PATCH_PIUIO_EMU_LIB "patch.piuio.emu_lib"
#define FSTHOOK_OPTIONS_STR_PATCH_PIUIO_EXIT_TEST_SERV "patch.piuio_exit.test_serv"
#define FSTHOOK_OPTIONS_STR_PATCH_PIUIO_EXIT_TEST_SERV \
"patch.piuio_exit.test_serv"
#define FSTHOOK_OPTIONS_STR_PATCH_SOUND_DEVICE "patch.sound.device"
#define FSTHOOK_OPTIONS_STR_PATCH_SIGSEGV_HALT_ON_SEGV "patch.sigsegv.halt_on_segv"
#define FSTHOOK_OPTIONS_STR_PATCH_SIGSEGV_HALT_ON_SEGV \
"patch.sigsegv.halt_on_segv"
#define FSTHOOK_OPTIONS_STR_PATCH_UTIL_LOG_FILE "util.log.file"
#define FSTHOOK_OPTIONS_STR_PATCH_UTIL_LOG_LEVEL "util.log.level"
@@ -26,7 +31,7 @@ const struct util_options_def fsthook_options_def[] = {
.description = "Path to game settings (SETTINGS) folder",
.param = 's',
.type = UTIL_OPTIONS_TYPE_STR,
.default_value.str = "./save",
.default_value.str = "./save",
},
{
.name = FSTHOOK_OPTIONS_STR_PATCH_GFX_WINDOWED,
@@ -71,22 +76,26 @@ const struct util_options_def fsthook_options_def[] = {
.default_value.b = false,
},
{
.name = FSTHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS,
.description = "Disable the built in keyboard inputs for test (F1), service (F2) and clear (F3)",
.name =
FSTHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS,
.description = "Disable the built in keyboard inputs for test (F1), "
"service (F2) and clear (F3)",
.param = 'k',
.type = UTIL_OPTIONS_TYPE_BOOL,
.default_value.b = false,
},
{
.name = FSTHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_X11_INPUT_HANDLER,
.description = "Path to a library implementing the x11-input-handler api to capture X11 keyboard inputs",
.description = "Path to a library implementing the x11-input-handler "
"api to capture X11 keyboard inputs",
.param = 'q',
.type = UTIL_OPTIONS_TYPE_STR,
.default_value.str = NULL,
},
{
.name = FSTHOOK_OPTIONS_STR_PATCH_NET_PROFILE_SERVER,
.description = "Address and port of pumpnet server (e.g. 127.0.0.1:1234)",
.description =
"Address and port of pumpnet server (e.g. 127.0.0.1:1234)",
.param = 'n',
.type = UTIL_OPTIONS_TYPE_STR,
.default_value.str = NULL,
@@ -100,7 +109,8 @@ const struct util_options_def fsthook_options_def[] = {
},
{
.name = FSTHOOK_OPTIONS_STR_PATCH_PIUIO_EMU_LIB,
.description = "Path to library implementing the piuio api for piuio emulation",
.description =
"Path to library implementing the piuio api for piuio emulation",
.param = 'p',
.type = UTIL_OPTIONS_TYPE_STR,
.default_value.str = NULL,
@@ -151,45 +161,59 @@ const struct util_options_defs fsthook_options_defs = {
.ndefs = lengthof(fsthook_options_def)
};
bool fsthook_options_init(int argc, char** argv, struct fsthook_options* options)
bool fsthook_options_init(
int argc, char **argv, struct fsthook_options *options)
{
log_assert(argv);
log_assert(options);
log_assert(argv);
log_assert(options);
struct util_options_opts* options_opt;
struct util_options_opts *options_opt;
util_options_init(argc, argv);
options_opt = util_options_get(&fsthook_options_defs);
util_options_init(argc, argv);
options_opt = util_options_get(&fsthook_options_defs);
if (!options_opt) {
return false;
}
if (!options_opt) {
return false;
}
options->game.settings = util_options_get_str(options_opt, FSTHOOK_OPTIONS_STR_GAME_SETTINGS);
options->patch.gfx.windowed = util_options_get_bool(options_opt, FSTHOOK_OPTIONS_STR_PATCH_GFX_WINDOWED);
options->patch.hook_mon.file = util_options_get_bool(options_opt, FSTHOOK_OPTIONS_STR_PATCH_HOOK_MON_FILE);
options->patch.hook_mon.fs = util_options_get_bool(options_opt, FSTHOOK_OPTIONS_STR_PATCH_HOOK_MON_FS);
options->patch.hook_mon.io = util_options_get_bool(options_opt, FSTHOOK_OPTIONS_STR_PATCH_HOOK_MON_IO);
options->patch.hook_mon.open = util_options_get_bool(options_opt, FSTHOOK_OPTIONS_STR_PATCH_HOOK_MON_OPEN);
options->patch.hook_mon.usb = util_options_get_bool(options_opt, FSTHOOK_OPTIONS_STR_PATCH_HOOK_MON_USB);
options->patch.main_loop.disable_built_in_inputs = util_options_get_bool(options_opt,
FSTHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS);
options->patch.main_loop.x11_input_handler_api_lib =
util_options_get_str(options_opt, FSTHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_X11_INPUT_HANDLER);
options->patch.net.server = util_options_get_str(options_opt, FSTHOOK_OPTIONS_STR_PATCH_NET_PROFILE_SERVER);
options->patch.net.machine_id = strtoul(
util_options_get_str(options_opt, FSTHOOK_OPTIONS_STR_PATCH_NET_PROFILE_MACHINE_ID),
NULL,
16);
options->patch.piuio.api_lib = util_options_get_str(options_opt, FSTHOOK_OPTIONS_STR_PATCH_PIUIO_EMU_LIB);
options->patch.piuio.exit_test_serv =
util_options_get_bool(options_opt, FSTHOOK_OPTIONS_STR_PATCH_PIUIO_EXIT_TEST_SERV);
options->patch.sound.device = util_options_get_str(options_opt, FSTHOOK_OPTIONS_STR_PATCH_SOUND_DEVICE);
options->patch.sigsegv.halt_on_segv =
util_options_get_bool(options_opt, FSTHOOK_OPTIONS_STR_PATCH_SIGSEGV_HALT_ON_SEGV);
options->log.file = util_options_get_str(options_opt, FSTHOOK_OPTIONS_STR_PATCH_UTIL_LOG_FILE);
options->log.level =
(enum util_log_level) util_options_get_int(options_opt, FSTHOOK_OPTIONS_STR_PATCH_UTIL_LOG_LEVEL);
options->game.settings =
util_options_get_str(options_opt, FSTHOOK_OPTIONS_STR_GAME_SETTINGS);
options->patch.gfx.windowed = util_options_get_bool(
options_opt, FSTHOOK_OPTIONS_STR_PATCH_GFX_WINDOWED);
options->patch.hook_mon.file = util_options_get_bool(
options_opt, FSTHOOK_OPTIONS_STR_PATCH_HOOK_MON_FILE);
options->patch.hook_mon.fs =
util_options_get_bool(options_opt, FSTHOOK_OPTIONS_STR_PATCH_HOOK_MON_FS);
options->patch.hook_mon.io =
util_options_get_bool(options_opt, FSTHOOK_OPTIONS_STR_PATCH_HOOK_MON_IO);
options->patch.hook_mon.open = util_options_get_bool(
options_opt, FSTHOOK_OPTIONS_STR_PATCH_HOOK_MON_OPEN);
options->patch.hook_mon.usb = util_options_get_bool(
options_opt, FSTHOOK_OPTIONS_STR_PATCH_HOOK_MON_USB);
options->patch.main_loop.disable_built_in_inputs = util_options_get_bool(
options_opt,
FSTHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_DISABLE_BUILT_IN_INPUTS);
options->patch.main_loop.x11_input_handler_api_lib = util_options_get_str(
options_opt, FSTHOOK_OPTIONS_STR_PATCH_HOOK_MAIN_LOOP_X11_INPUT_HANDLER);
options->patch.net.server = util_options_get_str(
options_opt, FSTHOOK_OPTIONS_STR_PATCH_NET_PROFILE_SERVER);
options->patch.net.machine_id = strtoul(
util_options_get_str(
options_opt, FSTHOOK_OPTIONS_STR_PATCH_NET_PROFILE_MACHINE_ID),
NULL,
16);
options->patch.piuio.api_lib = util_options_get_str(
options_opt, FSTHOOK_OPTIONS_STR_PATCH_PIUIO_EMU_LIB);
options->patch.piuio.exit_test_serv = util_options_get_bool(
options_opt, FSTHOOK_OPTIONS_STR_PATCH_PIUIO_EXIT_TEST_SERV);
options->patch.sound.device =
util_options_get_str(options_opt, FSTHOOK_OPTIONS_STR_PATCH_SOUND_DEVICE);
options->patch.sigsegv.halt_on_segv = util_options_get_bool(
options_opt, FSTHOOK_OPTIONS_STR_PATCH_SIGSEGV_HALT_ON_SEGV);
options->log.file = util_options_get_str(
options_opt, FSTHOOK_OPTIONS_STR_PATCH_UTIL_LOG_FILE);
options->log.level = (enum util_log_level) util_options_get_int(
options_opt, FSTHOOK_OPTIONS_STR_PATCH_UTIL_LOG_LEVEL);
return true;
return true;
}
+39 -38
View File
@@ -7,53 +7,54 @@
#include "util/log.h"
struct fsthook_options {
struct game {
const char* settings;
} game;
struct game {
const char *settings;
} game;
struct patch {
struct gfx {
bool windowed;
} gfx;
struct patch {
struct gfx {
bool windowed;
} gfx;
struct hook_mon {
bool file;
bool fs;
bool io;
bool open;
bool usb;
} hook_mon;
struct hook_mon {
bool file;
bool fs;
bool io;
bool open;
bool usb;
} hook_mon;
struct main_loop {
bool disable_built_in_inputs;
const char* x11_input_handler_api_lib;
} main_loop;
struct main_loop {
bool disable_built_in_inputs;
const char *x11_input_handler_api_lib;
} main_loop;
struct net {
const char* server;
uint32_t machine_id;
} net;
struct net {
const char *server;
uint32_t machine_id;
} net;
struct piuio {
const char* api_lib;
bool exit_test_serv;
} piuio;
struct piuio {
const char *api_lib;
bool exit_test_serv;
} piuio;
struct sound {
const char* device;
} sound;
struct sound {
const char *device;
} sound;
struct sigsegv {
bool halt_on_segv;
} sigsegv;
} patch;
struct sigsegv {
bool halt_on_segv;
} sigsegv;
} patch;
struct log {
const char* file;
enum util_log_level level;
} log;
struct log {
const char *file;
enum util_log_level level;
} log;
};
bool fsthook_options_init(int argc, char** argv, struct fsthook_options* options);
bool fsthook_options_init(
int argc, char **argv, struct fsthook_options *options);
#endif
+26 -19
View File
@@ -10,32 +10,39 @@
typedef int (*cnh_fshook_chdir_t)(const char *path);
static cnh_fshook_chdir_t mk3hook_1st_2nd_fs_fix_real_chdir;
static char* mk3hook_1st_2nd_fs_fix_path_game_dir_abs;
static char *mk3hook_1st_2nd_fs_fix_path_game_dir_abs;
int chdir(const char *path)
{
if (!mk3hook_1st_2nd_fs_fix_real_chdir) {
mk3hook_1st_2nd_fs_fix_real_chdir = (cnh_fshook_chdir_t) cnh_lib_get_func_addr("chdir");
}
if (!mk3hook_1st_2nd_fs_fix_real_chdir) {
mk3hook_1st_2nd_fs_fix_real_chdir =
(cnh_fshook_chdir_t) cnh_lib_get_func_addr("chdir");
}
// This seems to be some kind of probe the game is doing to determine something...I assume which folder layout to
// use? When we change directory to our "game" dir which contains all stuff at that point, everything's fine.
// If we do not do that, the game will error not being able to find any files. When loading files, the code also
// does some odd iterating the file system starting at / at that point. I assume that this is some sort of search
// trying to look for the file on the filesystem. However, that breaks a lot of other stuf with the hooking code
// and therefore should not be triggered.
if (mk3hook_1st_2nd_fs_fix_path_game_dir_abs && !strcmp(path, "/datas/bga")) {
log_debug("Trapping /datas/bga chdir, chdir to %s", mk3hook_1st_2nd_fs_fix_path_game_dir_abs);
// This seems to be some kind of probe the game is doing to determine
// something...I assume which folder layout to use? When we change directory
// to our "game" dir which contains all stuff at that point, everything's
// fine. If we do not do that, the game will error not being able to find any
// files. When loading files, the code also does some odd iterating the file
// system starting at / at that point. I assume that this is some sort of
// search trying to look for the file on the filesystem. However, that breaks
// a lot of other stuf with the hooking code and therefore should not be
// triggered.
if (mk3hook_1st_2nd_fs_fix_path_game_dir_abs && !strcmp(path, "/datas/bga")) {
log_debug(
"Trapping /datas/bga chdir, chdir to %s",
mk3hook_1st_2nd_fs_fix_path_game_dir_abs);
return mk3hook_1st_2nd_fs_fix_real_chdir(mk3hook_1st_2nd_fs_fix_path_game_dir_abs);
} else {
return mk3hook_1st_2nd_fs_fix_real_chdir(path);
}
return mk3hook_1st_2nd_fs_fix_real_chdir(
mk3hook_1st_2nd_fs_fix_path_game_dir_abs);
} else {
return mk3hook_1st_2nd_fs_fix_real_chdir(path);
}
}
void mk3hook_1st_2nd_fs_fix_init(const char* path_game_dir_abs)
void mk3hook_1st_2nd_fs_fix_init(const char *path_game_dir_abs)
{
mk3hook_1st_2nd_fs_fix_path_game_dir_abs = util_str_dup(path_game_dir_abs);
mk3hook_1st_2nd_fs_fix_path_game_dir_abs = util_str_dup(path_game_dir_abs);
log_info("Initialized");
log_info("Initialized");
}
+5 -3
View File
@@ -1,5 +1,6 @@
/**
* Fixes an issue with the engine of 1st and 2nd when redirecting all game data to one game folder, e.g. ./game/.
* Fixes an issue with the engine of 1st and 2nd when redirecting all game data
* to one game folder, e.g. ./game/.
*/
#ifndef MK3HOOK_1ST_2ND_FS_FIX_H
#define MK3HOOK_1ST_2ND_FS_FIX_H
@@ -7,8 +8,9 @@
/**
* Initialize the module.
*
* @param path_game_dir_abs The absolute path to the "game" dir containing all game assets.
* @param path_game_dir_abs The absolute path to the "game" dir containing all
* game assets.
*/
void mk3hook_1st_2nd_fs_fix_init(const char* path_game_dir_abs);
void mk3hook_1st_2nd_fs_fix_init(const char *path_game_dir_abs);
#endif

Some files were not shown because too many files have changed in this diff Show More